Skip to main content

link_argv/
link_argv.rs

1//! Links from a GNU ld command line, as the `qld` binary does.
2//!
3//! ```sh
4//! cargo run --example link_argv -- -o hello /usr/lib/crt1.o hello.o -lc
5//! ```
6//!
7//! The binary adds process-level behavior on top of this (`--fork`, exit
8//! codes, plugin fatal errors exiting the process); a library caller gets
9//! everything else from the same two calls, [`qld::parse_gnu`] and
10//! [`qld::link`].
11
12use std::process::ExitCode;
13
14use qld::ParseOutcome;
15use qld::diag::{Diagnostic, DiagnosticSink, Stderr};
16
17fn main() -> ExitCode {
18    // argv[0] selects the flavor, as for the binary: `ld.qld` is GNU,
19    // `ld64.qld` is Apple's ld64.
20    let args: Vec<_> = std::iter::once("ld".into())
21        .chain(std::env::args_os().skip(1))
22        .collect();
23    let diagnostics = Stderr::new(qld::PROGRAM_NAME);
24    match link(&args, &diagnostics) {
25        Ok(()) => ExitCode::SUCCESS,
26        Err(qld::Error::Reported { .. }) => ExitCode::FAILURE,
27        Err(error) => {
28            eprintln!("{}: error: {error}", qld::PROGRAM_NAME);
29            ExitCode::FAILURE
30        }
31    }
32}
33
34fn link(args: &[std::ffi::OsString], diagnostics: &dyn DiagnosticSink) -> qld::Result<()> {
35    let options = match qld::parse_gnu(args)? {
36        ParseOutcome::Link(options) => options,
37        ParseOutcome::Help => {
38            print!("{}", qld::args::usage());
39            return Ok(());
40        }
41        ParseOutcome::Version => {
42            println!("{}", qld::version_line());
43            return Ok(());
44        }
45    };
46    // Parsing does no reporting: warnings such as an unknown `-z` keyword
47    // come back in the options, for the caller to emit.
48    if !options.no_warnings {
49        for warning in &options.warnings {
50            diagnostics.emit(Diagnostic::warning(warning.clone()));
51        }
52    }
53    if options.fatal_warnings && !options.warnings.is_empty() {
54        return Err(qld::Error::Reported {
55            errors: options.warnings.len(),
56        });
57    }
58    qld::link(&options, diagnostics)
59}