mod raw_dylib;

use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs::{File, OpenOptions, read};
use std::io::{BufReader, BufWriter, Write};
use std::ops::{ControlFlow, Deref};
use std::path::{Path, PathBuf};
use std::process::{Output, Stdio};
use std::{env, fmt, fs, io, mem, str};

use find_msvc_tools;
use itertools::Itertools;
use object::{Object, ObjectSection, ObjectSymbol};
use regex::Regex;
use rustc_arena::TypedArena;
use rustc_attr_parsing::eval_config_entry;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize};
use rustc_hir::attrs::NativeLibKind;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_macros::LintDiagnostic;
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
use rustc_metadata::{
    EncodedMetadata, NativeLibSearchFallback, find_native_static_library,
    walk_native_lib_search_dirs,
};
use rustc_middle::bug;
use rustc_middle::lint::lint_level;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_session::config::{
    self, CFGuard, CrateType, DebugInfo, LinkerFeaturesCli, OutFileName, OutputFilenames,
    OutputType, PrintKind, SplitDwarfKind, Strip,
};
use rustc_session::lint::builtin::LINKER_MESSAGES;
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
use rustc_session::search_paths::PathKind;
/// For all the linkers we support, and information they might
/// need out of the shared crate context before we get rid of it.
use rustc_session::{Session, filesearch};
use rustc_span::Symbol;
use rustc_target::spec::crt_objects::CrtObjects;
use rustc_target::spec::{
    Abi, BinaryFormat, Cc, Env, LinkOutputKind, LinkSelfContainedComponents,
    LinkSelfContainedDefault, LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, Os, RelocModel,
    RelroLevel, SanitizerSet, SplitDebuginfo,
};
use tracing::{debug, info, warn};

use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
use super::command::Command;
use super::linker::{self, Linker};
use super::metadata::{MetadataPosition, create_wrapper_file};
use super::rpath::{self, RPathConfig};
use super::{apple, versioned_llvm_target};
use crate::base::needs_allocator_shim_for_linking;
use crate::{
    CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, looks_like_rust_object_file,
};

pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
    if let Err(e) = fs::remove_file(path) {
        if e.kind() != io::ErrorKind::NotFound {
            dcx.err(format!("failed to remove {}: {}", path.display(), e));
        }
    }
}

/// Performs the linkage portion of the compilation phase. This will generate all
/// of the requested outputs for this compilation session.
pub fn link_binary(
    sess: &Session,
    archive_builder_builder: &dyn ArchiveBuilderBuilder,
    codegen_results: CodegenResults,
    metadata: EncodedMetadata,
    outputs: &OutputFilenames,
    codegen_backend: &'static str,
) {
    let _timer = sess.timer("link_binary");
    let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
    let mut tempfiles_for_stdout_output: Vec<PathBuf> = Vec::new();
    for &crate_type in &codegen_results.crate_info.crate_types {
        // Ignore executable crates if we have -Z no-codegen, as they will error.
        if (sess.opts.unstable_opts.no_codegen || !sess.opts.output_types.should_codegen())
            && !output_metadata
            && crate_type == CrateType::Executable
        {
            continue;
        }

        if invalid_output_for_target(sess, crate_type) {
            bug!("invalid output type `{:?}` for target `{}`", crate_type, sess.opts.target_triple);
        }

        sess.time("link_binary_check_files_are_writeable", || {
            for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
                check_file_is_writeable(obj, sess);
            }
        });

        if outputs.outputs.should_link() {
            let output = out_filename(
                sess,
                crate_type,
                outputs,
                codegen_results.crate_info.local_crate_name,
            );
            let tmpdir = TempDirBuilder::new()
                .prefix("rustc")
                .tempdir_in(output.parent().unwrap_or_else(|| Path::new(".")))
                .unwrap_or_else(|error| sess.dcx().emit_fatal(errors::CreateTempDir { error }));
            let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps);

            let crate_name = format!("{}", codegen_results.crate_info.local_crate_name);
            let out_filename = output.file_for_writing(
                outputs,
                OutputType::Exe,
                &crate_name,
                sess.invocation_temp.as_deref(),
            );
            match crate_type {
                CrateType::Rlib => {
                    let _timer = sess.timer("link_rlib");
                    info!("preparing rlib to {:?}", out_filename);
                    link_rlib(
                        sess,
                        archive_builder_builder,
                        &codegen_results,
                        &metadata,
                        RlibFlavor::Normal,
                        &path,
                    )
                    .build(&out_filename);
                }
                CrateType::StaticLib => {
                    link_staticlib(
                        sess,
                        archive_builder_builder,
                        &codegen_results,
                        &metadata,
                        &out_filename,
                        &path,
                    );
                }
                _ => {
                    link_natively(
                        sess,
                        archive_builder_builder,
                        crate_type,
                        &out_filename,
                        &codegen_results,
                        &metadata,
                        path.as_ref(),
                        codegen_backend,
                    );
                }
            }
            if sess.opts.json_artifact_notifications {
                sess.dcx().emit_artifact_notification(&out_filename, "link");
            }

            if sess.prof.enabled()
                && let Some(artifact_name) = out_filename.file_name()
            {
                // Record size for self-profiling
                let file_size = std::fs::metadata(&out_filename).map(|m| m.len()).unwrap_or(0);

                sess.prof.artifact_size(
                    "linked_artifact",
                    artifact_name.to_string_lossy(),
                    file_size,
                );
            }

            if sess.target.binary_format == BinaryFormat::Elf {
                if let Err(err) = warn_if_linked_with_gold(sess, &out_filename) {
                    info!(?err, "Error while checking if gold was the linker");
                }
            }

            if output.is_stdout() {
                if output.is_tty() {
                    sess.dcx().emit_err(errors::BinaryOutputToTty {
                        shorthand: OutputType::Exe.shorthand(),
                    });
                } else if let Err(e) = copy_to_stdout(&out_filename) {
                    sess.dcx().emit_err(errors::CopyPath::new(&out_filename, output.as_path(), e));
                }
                tempfiles_for_stdout_output.push(out_filename);
            }
        }
    }

    // Remove the temporary object file and metadata if we aren't saving temps.
    sess.time("link_binary_remove_temps", || {
        // If the user requests that temporaries are saved, don't delete any.
        if sess.opts.cg.save_temps {
            return;
        }

        let maybe_remove_temps_from_module =
            |preserve_objects: bool, preserve_dwarf_objects: bool, module: &CompiledModule| {
                if !preserve_objects && let Some(ref obj) = module.object {
                    ensure_removed(sess.dcx(), obj);
                }

                if !preserve_dwarf_objects && let Some(ref dwo_obj) = module.dwarf_object {
                    ensure_removed(sess.dcx(), dwo_obj);
                }
            };

        let remove_temps_from_module =
            |module: &CompiledModule| maybe_remove_temps_from_module(false, false, module);

        // Otherwise, always remove the allocator module temporaries.
        if let Some(ref allocator_module) = codegen_results.allocator_module {
            remove_temps_from_module(allocator_module);
        }

        // Remove the temporary files if output goes to stdout
        for temp in tempfiles_for_stdout_output {
            ensure_removed(sess.dcx(), &temp);
        }

        // If no requested outputs require linking, then the object temporaries should
        // be kept.
        if !sess.opts.output_types.should_link() {
            return;
        }

        // Potentially keep objects for their debuginfo.
        let (preserve_objects, preserve_dwarf_objects) = preserve_objects_for_their_debuginfo(sess);
        debug!(?preserve_objects, ?preserve_dwarf_objects);

        for module in &codegen_results.modules {
            maybe_remove_temps_from_module(preserve_objects, preserve_dwarf_objects, module);
        }
    });
}

// Crate type is not passed when calculating the dylibs to include for LTO. In that case all
// crate types must use the same dependency formats.
pub fn each_linked_rlib(
    info: &CrateInfo,
    crate_type: Option<CrateType>,
    f: &mut dyn FnMut(CrateNum, &Path),
) -> Result<(), errors::LinkRlibError> {
    let fmts = if let Some(crate_type) = crate_type {
        let Some(fmts) = info.dependency_formats.get(&crate_type) else {
            return Err(errors::LinkRlibError::MissingFormat);
        };

        fmts
    } else {
        let mut dep_formats = info.dependency_formats.iter();
        let (ty1, list1) = dep_formats.next().ok_or(errors::LinkRlibError::MissingFormat)?;
        if let Some((ty2, list2)) = dep_formats.find(|(_, list2)| list1 != *list2) {
            return Err(errors::LinkRlibError::IncompatibleDependencyFormats {
                ty1: format!("{ty1:?}"),
                ty2: format!("{ty2:?}"),
                list1: format!("{list1:?}"),
                list2: format!("{list2:?}"),
            });
        }
        list1
    };

    let used_dep_crates = info.used_crates.iter();
    for &cnum in used_dep_crates {
        match fmts.get(cnum) {
            Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
            Some(_) => {}
            None => return Err(errors::LinkRlibError::MissingFormat),
        }
        let crate_name = info.crate_name[&cnum];
        let used_crate_source = &info.used_crate_source[&cnum];
        if let Some(path) = &used_crate_source.rlib {
            f(cnum, path);
        } else if used_crate_source.rmeta.is_some() {
            return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name });
        } else {
            return Err(errors::LinkRlibError::NotFound { crate_name });
        }
    }
    Ok(())
}

/// Create an 'rlib'.
///
/// An rlib in its current incarnation is essentially a renamed .a file (with "dummy" object files).
/// The rlib primarily contains the object file of the crate, but it also some of the object files
/// from native libraries.
fn link_rlib<'a>(
    sess: &'a Session,
    archive_builder_builder: &dyn ArchiveBuilderBuilder,
    codegen_results: &CodegenResults,
    metadata: &EncodedMetadata,
    flavor: RlibFlavor,
    tmpdir: &MaybeTempDir,
) -> Box<dyn ArchiveBuilder + 'a> {
    let mut ab = archive_builder_builder.new_archive_builder(sess);

    let trailing_metadata = match flavor {
        RlibFlavor::Normal => {
            let (metadata, metadata_position) =
                create_wrapper_file(sess, ".rmeta".to_string(), metadata.stub_or_full());
            let metadata = emit_wrapper_file(sess, &metadata, tmpdir.as_ref(), METADATA_FILENAME);
            match metadata_position {
                MetadataPosition::First => {
                    // Most of the time metadata in rlib files is wrapped in a "dummy" object
                    // file for the target platform so the rlib can be processed entirely by
                    // normal linkers for the platform. Sometimes this is not possible however.
                    // If it is possible however, placing the metadata object first improves
                    // performance of getting metadata from rlibs.
                    ab.add_file(&metadata);
                    None
                }
                MetadataPosition::Last => Some(metadata),
            }
        }

        RlibFlavor::StaticlibBase => None,
    };

    for m in &codegen_results.modules {
        if let Some(obj) = m.object.as_ref() {
            ab.add_file(obj);
        }

        if let Some(dwarf_obj) = m.dwarf_object.as_ref() {
            ab.add_file(dwarf_obj);
        }
    }

    match flavor {
        RlibFlavor::Normal => {}
        RlibFlavor::StaticlibBase => {
            let obj = codegen_results.allocator_module.as_ref().and_then(|m| m.object.as_ref());
            if let Some(obj) = obj {
                ab.add_file(obj);
            }
        }
    }

    // Used if packed_bundled_libs flag enabled.
    let mut packed_bundled_libs = Vec::new();

    // Note that in this loop we are ignoring the value of `lib.cfg`. That is,
    // we may not be configured to actually include a static library if we're
    // adding it here. That's because later when we consume this rlib we'll
    // decide whether we actually needed the static library or not.
    //
    // To do this "correctly" we'd need to keep track of which libraries added
    // which object files to the archive. We don't do that here, however. The
    // #[link(cfg(..))] feature is unstable, though, and only intended to get
    // liblibc working. In that sense the check below just indicates that if
    // there are any libraries we want to omit object files for at link time we
    // just exclude all custom object files.
    //
    // Eventually if we want to stabilize or flesh out the #[link(cfg(..))]
    // feature then we'll need to figure out how to record what objects were
    // loaded from the libraries found here and then encode that into the
    // metadata of the rlib we're generating somehow.
    for lib in codegen_results.crate_info.used_libraries.iter() {
        let NativeLibKind::Static { bundle: None | Some(true), .. } = lib.kind else {
            continue;
        };
        if flavor == RlibFlavor::Normal
            && let Some(filename) = lib.filename
        {
            let path = find_native_static_library(filename.as_str(), true, sess);
            let src = read(path)
                .unwrap_or_else(|e| sess.dcx().emit_fatal(errors::ReadFileError { message: e }));
            let (data, _) = create_wrapper_file(sess, ".bundled_lib".to_string(), &src);
            let wrapper_file = emit_wrapper_file(sess, &data, tmpdir.as_ref(), filename.as_str());
            packed_bundled_libs.push(wrapper_file);
        } else {
            let path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess);
            ab.add_archive(&path, Box::new(|_| false)).unwrap_or_else(|error| {
                sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: path, error })
            });
        }
    }

    // On Windows, we add the raw-dylib import libraries to the rlibs already.
    // But on ELF, this is not possible, as a shared object cannot be a member of a static library.
    // Instead, we add all raw-dylibs to the final link on ELF.
    if sess.target.is_like_windows {
        for output_path in raw_dylib::create_raw_dylib_dll_import_libs(
            sess,
            archive_builder_builder,
            codegen_results.crate_info.used_libraries.iter(),
            tmpdir.as_ref(),
            true,
        ) {
            ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
                sess.dcx()
                    .emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
            });
        }
    }

    if let Some(trailing_metadata) = trailing_metadata {
        // Note that it is important that we add all of our non-object "magical
        // files" *after* all of the object files in the archive. The reason for
        // this is as follows:
        //
        // * When performing LTO, this archive will be modified to remove
        //   objects from above. The reason for this is described below.
        //
        // * When the system linker looks at an archive, it will attempt to
        //   determine the architecture of the archive in order to see whether its
        //   linkable.
        //
        //   The algorithm for this detection is: iterate over the files in the
        //   archive. Skip magical SYMDEF names. Interpret the first file as an
        //   object file. Read architecture from the object file.
        //
        // * As one can probably see, if "metadata" and "foo.bc" were placed
        //   before all of the objects, then the architecture of this archive would
        //   not be correctly inferred once 'foo.o' is removed.
        //
        // * Most of the time metadata in rlib files is wrapped in a "dummy" object
        //   file for the target platform so the rlib can be processed entirely by
        //   normal linkers for the platform. Sometimes this is not possible however.
        //
        // Basically, all this means is that this code should not move above the
        // code above.
        ab.add_file(&trailing_metadata);
    }

    // Add all bundled static native library dependencies.
    // Archives added to the end of .rlib archive, see comment above for the reason.
    for lib in packed_bundled_libs {
        ab.add_file(&lib)
    }

    ab
}

/// Create a static archive.
///
/// This is essentially the same thing as an rlib, but it also involves adding all of the upstream
/// crates' objects into the archive. This will slurp in all of the native libraries of upstream
/// dependencies as well.
///
/// Additionally, there's no way for us to link dynamic libraries, so we warn about all dynamic
/// library dependencies that they're not linked in.
///
/// There's no need to include metadata in a static archive, so ensure to not link in the metadata
/// object file (and also don't prepare the archive with a metadata file).
fn link_staticlib(
    sess: &Session,
    archive_builder_builder: &dyn ArchiveBuilderBuilder,
    codegen_results: &CodegenResults,
    metadata: &EncodedMetadata,
    out_filename: &Path,
    tempdir: &MaybeTempDir,
) {
    info!("preparing staticlib to {:?}", out_filename);
    let mut ab = link_rlib(
        sess,
        archive_builder_builder,
        codegen_results,
        metadata,
        RlibFlavor::StaticlibBase,
        tempdir,
    );
    let mut all_native_libs = vec![];

    let res = each_linked_rlib(
        &codegen_results.crate_info,
        Some(CrateType::StaticLib),
        &mut |cnum, path| {
            let lto = are_upstream_rust_objects_already_included(sess)
                && !ignored_for_lto(sess, &codegen_results.crate_info, cnum);

            let native_libs = codegen_results.crate_info.native_libraries[&cnum].iter();
            let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, lib));
            let relevant_libs: FxIndexSet<_> = relevant.filter_map(|lib| lib.filename).collect();

            let bundled_libs: FxIndexSet<_> = native_libs.filter_map(|lib| lib.filename).collect();
            ab.add_archive(
                path,
                Box::new(move |fname: &str| {
                    // Ignore metadata files, no matter the name.
                    if fname == METADATA_FILENAME {
                        return true;
                    }

                    // Don't include Rust objects if LTO is enabled
                    if lto && looks_like_rust_object_file(fname) {
                        return true;
                    }

                    // Skip objects for bundled libs.
                    if bundled_libs.contains(&Symbol::intern(fname)) {
                        return true;
                    }

                    false
                }),
            )
            .unwrap();

            archive_builder_builder
                .extract_bundled_libs(path, tempdir.as_ref(), &relevant_libs)
                .unwrap_or_else(|e| sess.dcx().emit_fatal(e));

            for filename in relevant_libs.iter() {
                let joined = tempdir.as_ref().join(filename.as_str());
                let path = joined.as_path();
                ab.add_archive(path, Box::new(|_| false)).unwrap();
            }

            all_native_libs
                .extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
        },
    );
    if let Err(e) = res {
        sess.dcx().emit_fatal(e);
    }

    ab.build(out_filename);

    let crates = codegen_results.crate_info.used_crates.iter();

    let fmts = codegen_results
        .crate_info
        .dependency_formats
        .get(&CrateType::StaticLib)
        .expect("no dependency formats for staticlib");

    let mut all_rust_dylibs = vec![];
    for &cnum in crates {
        let Some(Linkage::Dynamic) = fmts.get(cnum) else {
            continue;
        };
        let crate_name = codegen_results.crate_info.crate_name[&cnum];
        let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum];
        if let Some(path) = &used_crate_source.dylib {
            all_rust_dylibs.push(&**path);
        } else if used_crate_source.rmeta.is_some() {
            sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name });
        } else {
            sess.dcx().emit_fatal(errors::LinkRlibError::NotFound { crate_name });
        }
    }

    all_native_libs.extend_from_slice(&codegen_results.crate_info.used_libraries);

    for print in &sess.opts.prints {
        if print.kind == PrintKind::NativeStaticLibs {
            print_native_static_libs(sess, &print.out, &all_native_libs, &all_rust_dylibs);
        }
    }
}

/// Use `thorin` (rust implementation of a dwarf packaging utility) to link DWARF objects into a
/// DWARF package.
fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out_filename: &Path) {
    let mut dwp_out_filename = executable_out_filename.to_path_buf().into_os_string();
    dwp_out_filename.push(".dwp");
    debug!(?dwp_out_filename, ?executable_out_filename);

    #[derive(Default)]
    struct ThorinSession<Relocations> {
        arena_data: TypedArena<Vec<u8>>,
        arena_mmap: TypedArena<Mmap>,
        arena_relocations: TypedArena<Relocations>,
    }

    impl<Relocations> ThorinSession<Relocations> {
        fn alloc_mmap(&self, data: Mmap) -> &Mmap {
            &*self.arena_mmap.alloc(data)
        }
    }

    impl<Relocations> thorin::Session<Relocations> for ThorinSession<Relocations> {
        fn alloc_data(&self, data: Vec<u8>) -> &[u8] {
            &*self.arena_data.alloc(data)
        }

        fn alloc_relocation(&self, data: Relocations) -> &Relocations {
            &*self.arena_relocations.alloc(data)
        }

        fn read_input(&self, path: &Path) -> std::io::Result<&[u8]> {
            let file = File::open(&path)?;
            let mmap = (unsafe { Mmap::map(file) })?;
            Ok(self.alloc_mmap(mmap))
        }
    }

    match sess.time("run_thorin", || -> Result<(), thorin::Error> {
        let thorin_sess = ThorinSession::default();
        let mut package = thorin::DwarfPackage::new(&thorin_sess);

        // Input objs contain .o/.dwo files from the current crate.
        match sess.opts.unstable_opts.split_dwarf_kind {
            SplitDwarfKind::Single => {
                for input_obj in cg_results.modules.iter().filter_map(|m| m.object.as_ref()) {
                    package.add_input_object(input_obj)?;
                }
            }
            SplitDwarfKind::Split => {
                for input_obj in cg_results.modules.iter().filter_map(|m| m.dwarf_object.as_ref()) {
                    package.add_input_object(input_obj)?;
                }
            }
        }

        // Input rlibs contain .o/.dwo files from dependencies.
        let input_rlibs = cg_results
            .crate_info
            .used_crate_source
            .items()
            .filter_map(|(_, csource)| csource.rlib.as_ref())
            .into_sorted_stable_ord();

        for input_rlib in input_rlibs {
            debug!(?input_rlib);
            package.add_input_object(input_rlib)?;
        }

        // Failing to read the referenced objects is expected for dependencies where the path in the
        // executable will have been cleaned by Cargo, but the referenced objects will be contained
        // within rlibs provided as inputs.
        //
        // If paths have been remapped, then .o/.dwo files from the current crate also won't be
        // found, but are provided explicitly above.
        //
        // Adding an executable is primarily done to make `thorin` check that all the referenced
        // dwarf objects are found in the end.
        package.add_executable(
            executable_out_filename,
            thorin::MissingReferencedObjectBehaviour::Skip,
        )?;

        let output_stream = BufWriter::new(
            OpenOptions::new()
                .read(true)
                .write(true)
                .create(true)
                .truncate(true)
                .open(dwp_out_filename)?,
        );
        let mut output_stream = thorin::object::write::StreamingBuffer::new(output_stream);
        package.finish()?.emit(&mut output_stream)?;
        output_stream.result()?;
        output_stream.into_inner().flush()?;

        Ok(())
    }) {
        Ok(()) => {}
        Err(e) => sess.dcx().emit_fatal(errors::ThorinErrorWrapper(e)),
    }
}

#[derive(LintDiagnostic)]
#[diag("{$inner}")]
/// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just
/// end up with inconsistent languages within the same diagnostic.
struct LinkerOutput {
    inner: String,
}

/// Create a dynamic library or executable.
///
/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
/// files as well.
fn link_natively(
    sess: &Session,
    archive_builder_builder: &dyn ArchiveBuilderBuilder,
    crate_type: CrateType,
    out_filename: &Path,
    codegen_results: &CodegenResults,
    metadata: &EncodedMetadata,
    tmpdir: &Path,
    codegen_backend: &'static str,
) {
    info!("preparing {:?} to {:?}", crate_type, out_filename);
    let (linker_path, flavor) = linker_and_flavor(sess);
    let self_contained_components = self_contained_components(sess, crate_type, &linker_path);

    // On AIX, we ship all libraries as .a big_af archive
    // the expected format is lib<name>.a(libname.so) for the actual
    // dynamic library. So we link to a temporary .so file to be archived
    // at the final out_filename location
    let should_archive = crate_type != CrateType::Executable && sess.target.is_like_aix;
    let archive_member =
        should_archive.then(|| tmpdir.join(out_filename.file_name().unwrap()).with_extension("so"));
    let temp_filename = archive_member.as_deref().unwrap_or(out_filename);

    let mut cmd = linker_with_args(
        &linker_path,
        flavor,
        sess,
        archive_builder_builder,
        crate_type,
        tmpdir,
        temp_filename,
        codegen_results,
        metadata,
        self_contained_components,
        codegen_backend,
    );

    linker::disable_localization(&mut cmd);

    for (k, v) in sess.target.link_env.as_ref() {
        cmd.env(k.as_ref(), v.as_ref());
    }
    for k in sess.target.link_env_remove.as_ref() {
        cmd.env_remove(k.as_ref());
    }

    for print in &sess.opts.prints {
        if print.kind == PrintKind::LinkArgs {
            let content = format!("{cmd:?}\n");
            print.out.overwrite(&content, sess);
        }
    }

    // May have not found libraries in the right formats.
    sess.dcx().abort_if_errors();

    // Invoke the system linker
    info!("{cmd:?}");
    let unknown_arg_regex =
        Regex::new(r"(unknown|unrecognized) (command line )?(option|argument)").unwrap();
    let mut prog;
    loop {
        prog = sess.time("run_linker", || exec_linker(sess, &cmd, out_filename, flavor, tmpdir));
        let Ok(ref output) = prog else {
            break;
        };
        if output.status.success() {
            break;
        }
        let mut out = output.stderr.clone();
        out.extend(&output.stdout);
        let out = String::from_utf8_lossy(&out);

        // Check to see if the link failed with an error message that indicates it
        // doesn't recognize the -no-pie option. If so, re-perform the link step
        // without it. This is safe because if the linker doesn't support -no-pie
        // then it should not default to linking executables as pie. Different
        // versions of gcc seem to use different quotes in the error message so
        // don't check for them.
        if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
            && unknown_arg_regex.is_match(&out)
            && out.contains("-no-pie")
            && cmd.get_args().iter().any(|e| e == "-no-pie")
        {
            info!("linker output: {:?}", out);
            warn!("Linker does not support -no-pie command line option. Retrying without.");
            for arg in cmd.take_args() {
                if arg != "-no-pie" {
                    cmd.arg(arg);
                }
            }
            info!("{cmd:?}");
            continue;
        }

        // Check if linking failed with an error message that indicates the driver didn't recognize
        // the `-fuse-ld=lld` option. If so, re-perform the link step without it. This avoids having
        // to spawn multiple instances on the happy path to do version checking, and ensures things
        // keep working on the tier 1 baseline of GLIBC 2.17+. That is generally understood as GCCs
        // circa RHEL/CentOS 7, 4.5 or so, whereas lld support was added in GCC 9.
        if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, Lld::Yes))
            && unknown_arg_regex.is_match(&out)
            && out.contains("-fuse-ld=lld")
            && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-fuse-ld=lld")
        {
            info!("linker output: {:?}", out);
            info!("The linker driver does not support `-fuse-ld=lld`. Retrying without it.");
            for arg in cmd.take_args() {
                if arg.to_string_lossy() != "-fuse-ld=lld" {
                    cmd.arg(arg);
                }
            }
            info!("{cmd:?}");
            continue;
        }

        // Detect '-static-pie' used with an older version of gcc or clang not supporting it.
        // Fallback from '-static-pie' to '-static' in that case.
        if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
            && unknown_arg_regex.is_match(&out)
            && (out.contains("-static-pie") || out.contains("--no-dynamic-linker"))
            && cmd.get_args().iter().any(|e| e == "-static-pie")
        {
            info!("linker output: {:?}", out);
            warn!(
                "Linker does not support -static-pie command line option. Retrying with -static instead."
            );
            // Mirror `add_(pre,post)_link_objects` to replace CRT objects.
            let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled();
            let opts = &sess.target;
            let pre_objects = if self_contained_crt_objects {
                &opts.pre_link_objects_self_contained
            } else {
                &opts.pre_link_objects
            };
            let post_objects = if self_contained_crt_objects {
                &opts.post_link_objects_self_contained
            } else {
                &opts.post_link_objects
            };
            let get_objects = |objects: &CrtObjects, kind| {
                objects
                    .get(&kind)
                    .iter()
                    .copied()
                    .flatten()
                    .map(|obj| {
                        get_object_file_path(sess, obj, self_contained_crt_objects).into_os_string()
                    })
                    .collect::<Vec<_>>()
            };
            let pre_objects_static_pie = get_objects(pre_objects, LinkOutputKind::StaticPicExe);
            let post_objects_static_pie = get_objects(post_objects, LinkOutputKind::StaticPicExe);
            let mut pre_objects_static = get_objects(pre_objects, LinkOutputKind::StaticNoPicExe);
            let mut post_objects_static = get_objects(post_objects, LinkOutputKind::StaticNoPicExe);
            // Assume that we know insertion positions for the replacement arguments from replaced
            // arguments, which is true for all supported targets.
            assert!(pre_objects_static.is_empty() || !pre_objects_static_pie.is_empty());
            assert!(post_objects_static.is_empty() || !post_objects_static_pie.is_empty());
            for arg in cmd.take_args() {
                if arg == "-static-pie" {
                    // Replace the output kind.
                    cmd.arg("-static");
                } else if pre_objects_static_pie.contains(&arg) {
                    // Replace the pre-link objects (replace the first and remove the rest).
                    cmd.args(mem::take(&mut pre_objects_static));
                } else if post_objects_static_pie.contains(&arg) {
                    // Replace the post-link objects (replace the first and remove the rest).
                    cmd.args(mem::take(&mut post_objects_static));
                } else {
                    cmd.arg(arg);
                }
            }
            info!("{cmd:?}");
            continue;
        }

        break;
    }

    match prog {
        Ok(prog) => {
            let is_msvc_link_exe = sess.target.is_like_msvc
                && flavor == LinkerFlavor::Msvc(Lld::No)
                // Match exactly "link.exe"
                && linker_path.to_str() == Some("link.exe");

            if !prog.status.success() {
                let mut output = prog.stderr.clone();
                output.extend_from_slice(&prog.stdout);
                let escaped_output = escape_linker_output(&output, flavor);
                let err = errors::LinkingFailed {
                    linker_path: &linker_path,
                    exit_status: prog.status,
                    command: cmd,
                    escaped_output,
                    verbose: sess.opts.verbose,
                    sysroot_dir: sess.opts.sysroot.path().to_owned(),
                };
                sess.dcx().emit_err(err);
                // If MSVC's `link.exe` was expected but the return code
                // is not a Microsoft LNK error then suggest a way to fix or
                // install the Visual Studio build tools.
                if let Some(code) = prog.status.code() {
                    // All Microsoft `link.exe` linking ror codes are
                    // four digit numbers in the range 1000 to 9999 inclusive
                    if is_msvc_link_exe && (code < 1000 || code > 9999) {
                        let is_vs_installed = find_msvc_tools::find_vs_version().is_ok();
                        let has_linker =
                            find_msvc_tools::find_tool(sess.target.arch.desc(), "link.exe")
                                .is_some();

                        sess.dcx().emit_note(errors::LinkExeUnexpectedError);

                        // STATUS_STACK_BUFFER_OVERRUN is also used for fast abnormal program termination, e.g. abort().
                        // Emit a special diagnostic to let people know that this most likely doesn't indicate a stack buffer overrun.
                        const STATUS_STACK_BUFFER_OVERRUN: i32 = 0xc0000409u32 as _;
                        if code == STATUS_STACK_BUFFER_OVERRUN {
                            sess.dcx().emit_note(errors::LinkExeStatusStackBufferOverrun);
                        }

                        if is_vs_installed && has_linker {
                            // the linker is broken
                            sess.dcx().emit_note(errors::RepairVSBuildTools);
                            sess.dcx().emit_note(errors::MissingCppBuildToolComponent);
                        } else if is_vs_installed {
                            // the linker is not installed
                            sess.dcx().emit_note(errors::SelectCppBuildToolWorkload);
                        } else {
                            // visual studio is not installed
                            sess.dcx().emit_note(errors::VisualStudioNotInstalled);
                        }
                    }
                }

                sess.dcx().abort_if_errors();
            }

            let stderr = escape_string(&prog.stderr);
            let mut stdout = escape_string(&prog.stdout);
            info!("linker stderr:\n{}", &stderr);
            info!("linker stdout:\n{}", &stdout);

            // Hide some progress messages from link.exe that we don't care about.
            // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146
            if is_msvc_link_exe {
                if let Ok(str) = str::from_utf8(&prog.stdout) {
                    let mut output = String::with_capacity(str.len());
                    for line in stdout.lines() {
                        if line.starts_with("   Creating library")
                            || line.starts_with("Generating code")
                            || line.starts_with("Finished generating code")
                        {
                            continue;
                        }
                        output += line;
                        output += "\r\n"
                    }
                    stdout = escape_string(output.trim().as_bytes())
                }
            }

            let level = codegen_results.crate_info.lint_levels.linker_messages;
            let lint = |msg| {
                lint_level(sess, LINKER_MESSAGES, level, None, |diag| {
                    LinkerOutput { inner: msg }.decorate_lint(diag)
                })
            };

            if !prog.stderr.is_empty() {
                // We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
                let stderr = stderr
                    .strip_prefix("warning: ")
                    .unwrap_or(&stderr)
                    .replace(": warning: ", ": ");
                lint(format!("linker stderr: {stderr}"));
            }
            if !stdout.is_empty() {
                lint(format!("linker stdout: {}", stdout))
            }
        }
        Err(e) => {
            let linker_not_found = e.kind() == io::ErrorKind::NotFound;

            let err = if linker_not_found {
                sess.dcx().emit_err(errors::LinkerNotFound { linker_path, error: e })
            } else {
                sess.dcx().emit_err(errors::UnableToExeLinker {
                    linker_path,
                    error: e,
                    command_formatted: format!("{cmd:?}"),
                })
            };

            if sess.target.is_like_msvc && linker_not_found {
                sess.dcx().emit_note(errors::MsvcMissingLinker);
                sess.dcx().emit_note(errors::CheckInstalledVisualStudio);
                sess.dcx().emit_note(errors::InsufficientVSCodeProduct);
            }
            err.raise_fatal();
        }
    }

    match sess.split_debuginfo() {
        // If split debug information is disabled or located in individual files
        // there's nothing to do here.
        SplitDebuginfo::Off | SplitDebuginfo::Unpacked => {}

        // If packed split-debuginfo is requested, but the final compilation
        // doesn't actually have any debug information, then we skip this step.
        SplitDebuginfo::Packed if sess.opts.debuginfo == DebugInfo::None => {}

        // On macOS the external `dsymutil` tool is used to create the packed
        // debug information. Note that this will read debug information from
        // the objects on the filesystem which we'll clean up later.
        SplitDebuginfo::Packed if sess.target.is_like_darwin => {
            let prog = Command::new("dsymutil").arg(out_filename).output();
            match prog {
                Ok(prog) => {
                    if !prog.status.success() {
                        let mut output = prog.stderr.clone();
                        output.extend_from_slice(&prog.stdout);
                        sess.dcx().emit_warn(errors::ProcessingDymutilFailed {
                            status: prog.status,
                            output: escape_string(&output),
                        });
                    }
                }
                Err(error) => sess.dcx().emit_fatal(errors::UnableToRunDsymutil { error }),
            }
        }

        // On MSVC packed debug information is produced by the linker itself so
        // there's no need to do anything else here.
        SplitDebuginfo::Packed if sess.target.is_like_windows => {}

        // ... and otherwise we're processing a `*.dwp` packed dwarf file.
        //
        // We cannot rely on the .o paths in the executable because they may have been
        // remapped by --remap-path-prefix and therefore invalid, so we need to provide
        // the .o/.dwo paths explicitly.
        SplitDebuginfo::Packed => link_dwarf_object(sess, codegen_results, out_filename),
    }

    let strip = sess.opts.cg.strip;

    if sess.target.is_like_darwin {
        let stripcmd = "rust-objcopy";
        match (strip, crate_type) {
            (Strip::Debuginfo, _) => {
                strip_with_external_utility(sess, stripcmd, out_filename, &["--strip-debug"])
            }

            // Per the manpage, --discard-all is the maximum safe strip level for dynamic libraries. (#93988)
            (
                Strip::Symbols,
                CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro | CrateType::Sdylib,
            ) => strip_with_external_utility(sess, stripcmd, out_filename, &["--discard-all"]),
            (Strip::Symbols, _) => {
                strip_with_external_utility(sess, stripcmd, out_filename, &["--strip-all"])
            }
            (Strip::None, _) => {}
        }
    }

    if sess.target.is_like_solaris {
        // Many illumos systems will have both the native 'strip' utility and
        // the GNU one. Use the native version explicitly and do not rely on
        // what's in the path.
        //
        // If cross-compiling and there is not a native version, then use
        // `llvm-strip` and hope.
        let stripcmd = if !sess.host.is_like_solaris { "rust-objcopy" } else { "/usr/bin/strip" };
        match strip {
            // Always preserve the symbol table (-x).
            Strip::Debuginfo => strip_with_external_utility(sess, stripcmd, out_filename, &["-x"]),
            // Strip::Symbols is handled via the --strip-all linker option.
            Strip::Symbols => {}
            Strip::None => {}
        }
    }

    if sess.target.is_like_aix {
        // `llvm-strip` doesn't work for AIX - their strip must be used.
        if !sess.host.is_like_aix {
            sess.dcx().emit_warn(errors::AixStripNotUsed);
        }
        let stripcmd = "/usr/bin/strip";
        match strip {
            Strip::Debuginfo => {
                // FIXME: AIX's strip utility only offers option to strip line number information.
                strip_with_external_utility(sess, stripcmd, temp_filename, &["-X32_64", "-l"])
            }
            Strip::Symbols => {
                // Must be noted this option might remove symbol __aix_rust_metadata and thus removes .info section which contains metadata.
                strip_with_external_utility(sess, stripcmd, temp_filename, &["-X32_64", "-r"])
            }
            Strip::None => {}
        }
    }

    if should_archive {
        let mut ab = archive_builder_builder.new_archive_builder(sess);
        ab.add_file(temp_filename);
        ab.build(out_filename);
    }
}

fn strip_with_external_utility(sess: &Session, util: &str, out_filename: &Path, options: &[&str]) {
    let mut cmd = Command::new(util);
    cmd.args(options);

    let mut new_path = sess.get_tools_search_paths(false);
    if let Some(path) = env::var_os("PATH") {
        new_path.extend(env::split_paths(&path));
    }
    cmd.env("PATH", env::join_paths(new_path).unwrap());

    let prog = cmd.arg(out_filename).output();
    match prog {
        Ok(prog) => {
            if !prog.status.success() {
                let mut output = prog.stderr.clone();
                output.extend_from_slice(&prog.stdout);
                sess.dcx().emit_warn(errors::StrippingDebugInfoFailed {
                    util,
                    status: prog.status,
                    output: escape_string(&output),
                });
            }
        }
        Err(error) => sess.dcx().emit_fatal(errors::UnableToRun { util, error }),
    }
}

fn escape_string(s: &[u8]) -> String {
    match str::from_utf8(s) {
        Ok(s) => s.to_owned(),
        Err(_) => format!("Non-UTF-8 output: {}", s.escape_ascii()),
    }
}

#[cfg(not(windows))]
fn escape_linker_output(s: &[u8], _flavour: LinkerFlavor) -> String {
    escape_string(s)
}

/// If the output of the msvc linker is not UTF-8 and the host is Windows,
/// then try to convert the string from the OEM encoding.
#[cfg(windows)]
fn escape_linker_output(s: &[u8], flavour: LinkerFlavor) -> String {
    // This only applies to the actual MSVC linker.
    if flavour != LinkerFlavor::Msvc(Lld::No) {
        return escape_string(s);
    }
    match str::from_utf8(s) {
        Ok(s) => return s.to_owned(),
        Err(_) => match win::locale_byte_str_to_string(s, win::oem_code_page()) {
            Some(s) => s,
            // The string is not UTF-8 and isn't valid for the OEM code page
            None => format!("Non-UTF-8 output: {}", s.escape_ascii()),
        },
    }
}

/// Wrappers around the Windows API.
#[cfg(windows)]
mod win {
    use windows::Win32::Globalization::{
        CP_OEMCP, GetLocaleInfoEx, LOCALE_IUSEUTF8LEGACYOEMCP, LOCALE_NAME_SYSTEM_DEFAULT,
        LOCALE_RETURN_NUMBER, MB_ERR_INVALID_CHARS, MultiByteToWideChar,
    };

    /// Get the Windows system OEM code page. This is most notably the code page
    /// used for link.exe's output.
    pub(super) fn oem_code_page() -> u32 {
        unsafe {
            let mut cp: u32 = 0;
            // We're using the `LOCALE_RETURN_NUMBER` flag to return a u32.
            // But the API requires us to pass the data as though it's a [u16] string.
            let len = size_of::<u32>() / size_of::<u16>();
            let data = std::slice::from_raw_parts_mut(&mut cp as *mut u32 as *mut u16, len);
            let len_written = GetLocaleInfoEx(
                LOCALE_NAME_SYSTEM_DEFAULT,
                LOCALE_IUSEUTF8LEGACYOEMCP | LOCALE_RETURN_NUMBER,
                Some(data),
            );
            if len_written as usize == len { cp } else { CP_OEMCP }
        }
    }
    /// Try to convert a multi-byte string to a UTF-8 string using the given code page
    /// The string does not need to be null terminated.
    ///
    /// This is implemented as a wrapper around `MultiByteToWideChar`.
    /// See <https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar>
    ///
    /// It will fail if the multi-byte string is longer than `i32::MAX` or if it contains
    /// any invalid bytes for the expected encoding.
    pub(super) fn locale_byte_str_to_string(s: &[u8], code_page: u32) -> Option<String> {
        // `MultiByteToWideChar` requires a length to be a "positive integer".
        if s.len() > isize::MAX as usize {
            return None;
        }
        // Error if the string is not valid for the expected code page.
        let flags = MB_ERR_INVALID_CHARS;
        // Call MultiByteToWideChar twice.
        // First to calculate the length then to convert the string.
        let mut len = unsafe { MultiByteToWideChar(code_page, flags, s, None) };
        if len > 0 {
            let mut utf16 = vec![0; len as usize];
            len = unsafe { MultiByteToWideChar(code_page, flags, s, Some(&mut utf16)) };
            if len > 0 {
                return utf16.get(..len as usize).map(String::from_utf16_lossy);
            }
        }
        None
    }
}

fn add_sanitizer_libraries(
    sess: &Session,
    flavor: LinkerFlavor,
    crate_type: CrateType,
    linker: &mut dyn Linker,
) {
    if sess.target.is_like_android {
        // Sanitizer runtime libraries are provided dynamically on Android
        // targets.
        return;
    }

    if sess.opts.unstable_opts.external_clangrt {
        // Linking against in-tree sanitizer runtimes is disabled via
        // `-Z external-clangrt`
        return;
    }

    if matches!(crate_type, CrateType::Rlib | CrateType::StaticLib) {
        return;
    }

    // On macOS and Windows using MSVC the runtimes are distributed as dylibs
    // which should be linked to both executables and dynamic libraries.
    // Everywhere else the runtimes are currently distributed as static
    // libraries which should be linked to executables only.
    if matches!(
        crate_type,
        CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro | CrateType::Sdylib
    ) && !(sess.target.is_like_darwin || sess.target.is_like_msvc)
    {
        return;
    }

    let sanitizer = sess.sanitizers();
    if sanitizer.contains(SanitizerSet::ADDRESS) {
        link_sanitizer_runtime(sess, flavor, linker, "asan");
    }
    if sanitizer.contains(SanitizerSet::DATAFLOW) {
        link_sanitizer_runtime(sess, flavor, linker, "dfsan");
    }
    if sanitizer.contains(SanitizerSet::LEAK)
        && !sanitizer.contains(SanitizerSet::ADDRESS)
        && !sanitizer.contains(SanitizerSet::HWADDRESS)
    {
        link_sanitizer_runtime(sess, flavor, linker, "lsan");
    }
    if sanitizer.contains(SanitizerSet::MEMORY) {
        link_sanitizer_runtime(sess, flavor, linker, "msan");
    }
    if sanitizer.contains(SanitizerSet::THREAD) {
        link_sanitizer_runtime(sess, flavor, linker, "tsan");
    }
    if sanitizer.contains(SanitizerSet::HWADDRESS) {
        link_sanitizer_runtime(sess, flavor, linker, "hwasan");
    }
    if sanitizer.contains(SanitizerSet::SAFESTACK) {
        link_sanitizer_runtime(sess, flavor, linker, "safestack");
    }
    if sanitizer.contains(SanitizerSet::REALTIME) {
        link_sanitizer_runtime(sess, flavor, linker, "rtsan");
    }
}

fn link_sanitizer_runtime(
    sess: &Session,
    flavor: LinkerFlavor,
    linker: &mut dyn Linker,
    name: &str,
) {
    fn find_sanitizer_runtime(sess: &Session, filename: &str) -> PathBuf {
        let path = sess.target_tlib_path.dir.join(filename);
        if path.exists() {
            sess.target_tlib_path.dir.clone()
        } else {
            filesearch::make_target_lib_path(
                &sess.opts.sysroot.default,
                sess.opts.target_triple.tuple(),
            )
        }
    }

    let channel =
        option_env!("CFG_RELEASE_CHANNEL").map(|channel| format!("-{channel}")).unwrap_or_default();

    if sess.target.is_like_darwin {
        // On Apple platforms, the sanitizer is always built as a dylib, and
        // LLVM will link to `@rpath/*.dylib`, so we need to specify an
        // rpath to the library as well (the rpath should be absolute, see
        // PR #41352 for details).
        let filename = format!("rustc{channel}_rt.{name}");
        let path = find_sanitizer_runtime(sess, &filename);
        let rpath = path.to_str().expect("non-utf8 component in path");
        linker.link_args(&["-rpath", rpath]);
        linker.link_dylib_by_name(&filename, false, true);
    } else if sess.target.is_like_msvc && flavor == LinkerFlavor::Msvc(Lld::No) && name == "asan" {
        // MSVC provides the `/INFERASANLIBS` argument to automatically find the
        // compatible ASAN library.
        linker.link_arg("/INFERASANLIBS");
    } else {
        let filename = format!("librustc{channel}_rt.{name}.a");
        let path = find_sanitizer_runtime(sess, &filename).join(&filename);
        linker.link_staticlib_by_path(&path, true);
    }
}

/// Returns a boolean indicating whether the specified crate should be ignored
/// during LTO.
///
/// Crates ignored during LTO are not lumped together in the "massive object
/// file" that we create and are linked in their normal rlib states. See
/// comments below for what crates do not participate in LTO.
///
/// It's unusual for a crate to not participate in LTO. Typically only
/// compiler-specific and unstable crates have a reason to not participate in
/// LTO.
pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
    // If our target enables builtin function lowering in LLVM then the
    // crates providing these functions don't participate in LTO (e.g.
    // no_builtins or compiler builtins crates).
    !sess.target.no_builtins
        && (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum))
}

/// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
    fn infer_from(
        sess: &Session,
        linker: Option<PathBuf>,
        flavor: Option<LinkerFlavor>,
        features: LinkerFeaturesCli,
    ) -> Option<(PathBuf, LinkerFlavor)> {
        let flavor = flavor.map(|flavor| adjust_flavor_to_features(flavor, features));
        match (linker, flavor) {
            (Some(linker), Some(flavor)) => Some((linker, flavor)),
            // only the linker flavor is known; use the default linker for the selected flavor
            (None, Some(flavor)) => Some((
                PathBuf::from(match flavor {
                    LinkerFlavor::Gnu(Cc::Yes, _)
                    | LinkerFlavor::Darwin(Cc::Yes, _)
                    | LinkerFlavor::WasmLld(Cc::Yes)
                    | LinkerFlavor::Unix(Cc::Yes) => {
                        if cfg!(any(target_os = "solaris", target_os = "illumos")) {
                            // On historical Solaris systems, "cc" may have
                            // been Sun Studio, which is not flag-compatible
                            // with "gcc". This history casts a long shadow,
                            // and many modern illumos distributions today
                            // ship GCC as "gcc" without also making it
                            // available as "cc".
                            "gcc"
                        } else {
                            "cc"
                        }
                    }
                    LinkerFlavor::Gnu(_, Lld::Yes)
                    | LinkerFlavor::Darwin(_, Lld::Yes)
                    | LinkerFlavor::WasmLld(..)
                    | LinkerFlavor::Msvc(Lld::Yes) => "lld",
                    LinkerFlavor::Gnu(..) | LinkerFlavor::Darwin(..) | LinkerFlavor::Unix(..) => {
                        "ld"
                    }
                    LinkerFlavor::Msvc(..) => "link.exe",
                    LinkerFlavor::EmCc => {
                        if cfg!(windows) {
                            "emcc.bat"
                        } else {
                            "emcc"
                        }
                    }
                    LinkerFlavor::Bpf => "bpf-linker",
                    LinkerFlavor::Llbc => "llvm-bitcode-linker",
                    LinkerFlavor::Ptx => "rust-ptx-linker",
                }),
                flavor,
            )),
            (Some(linker), None) => {
                let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| {
                    sess.dcx().emit_fatal(errors::LinkerFileStem);
                });
                let flavor = sess.target.linker_flavor.with_linker_hints(stem);
                let flavor = adjust_flavor_to_features(flavor, features);
                Some((linker, flavor))
            }
            (None, None) => None,
        }
    }

    // While linker flavors and linker features are isomorphic (and thus targets don't need to
    // define features separately), we use the flavor as the root piece of data and have the
    // linker-features CLI flag influence *that*, so that downstream code does not have to check for
    // both yet.
    fn adjust_flavor_to_features(
        flavor: LinkerFlavor,
        features: LinkerFeaturesCli,
    ) -> LinkerFlavor {
        // Note: a linker feature cannot be both enabled and disabled on the CLI.
        if features.enabled.contains(LinkerFeatures::LLD) {
            flavor.with_lld_enabled()
        } else if features.disabled.contains(LinkerFeatures::LLD) {
            flavor.with_lld_disabled()
        } else {
            flavor
        }
    }

    let features = sess.opts.cg.linker_features;

    // linker and linker flavor specified via command line have precedence over what the target
    // specification specifies
    let linker_flavor = match sess.opts.cg.linker_flavor {
        // The linker flavors that are non-target specific can be directly translated to LinkerFlavor
        Some(LinkerFlavorCli::Llbc) => Some(LinkerFlavor::Llbc),
        Some(LinkerFlavorCli::Ptx) => Some(LinkerFlavor::Ptx),
        // The linker flavors that corresponds to targets needs logic that keeps the base LinkerFlavor
        linker_flavor => {
            linker_flavor.map(|flavor| sess.target.linker_flavor.with_cli_hints(flavor))
        }
    };
    if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor, features) {
        return ret;
    }

    if let Some(ret) = infer_from(
        sess,
        sess.target.linker.as_deref().map(PathBuf::from),
        Some(sess.target.linker_flavor),
        features,
    ) {
        return ret;
    }

    bug!("Not enough information provided to determine how to invoke the linker");
}

/// Returns a pair of boolean indicating whether we should preserve the object and
/// dwarf object files on the filesystem for their debug information. This is often
/// useful with split-dwarf like schemes.
fn preserve_objects_for_their_debuginfo(sess: &Session) -> (bool, bool) {
    // If the objects don't have debuginfo there's nothing to preserve.
    if sess.opts.debuginfo == config::DebugInfo::None {
        return (false, false);
    }

    match (sess.split_debuginfo(), sess.opts.unstable_opts.split_dwarf_kind) {
        // If there is no split debuginfo then do not preserve objects.
        (SplitDebuginfo::Off, _) => (false, false),
        // If there is packed split debuginfo, then the debuginfo in the objects
        // has been packaged and the objects can be deleted.
        (SplitDebuginfo::Packed, _) => (false, false),
        // If there is unpacked split debuginfo and the current target can not use
        // split dwarf, then keep objects.
        (SplitDebuginfo::Unpacked, _) if !sess.target_can_use_split_dwarf() => (true, false),
        // If there is unpacked split debuginfo and the target can use split dwarf, then
        // keep the object containing that debuginfo (whether that is an object file or
        // dwarf object file depends on the split dwarf kind).
        (SplitDebuginfo::Unpacked, SplitDwarfKind::Single) => (true, false),
        (SplitDebuginfo::Unpacked, SplitDwarfKind::Split) => (false, true),
    }
}

#[derive(PartialEq)]
enum RlibFlavor {
    Normal,
    StaticlibBase,
}

fn print_native_static_libs(
    sess: &Session,
    out: &OutFileName,
    all_native_libs: &[NativeLib],
    all_rust_dylibs: &[&Path],
) {
    let mut lib_args: Vec<_> = all_native_libs
        .iter()
        .filter(|l| relevant_lib(sess, l))
        .filter_map(|lib| {
            let name = lib.name;
            match lib.kind {
                NativeLibKind::Static { bundle: Some(false), .. }
                | NativeLibKind::Dylib { .. }
                | NativeLibKind::Unspecified => {
                    let verbatim = lib.verbatim;
                    if sess.target.is_like_msvc {
                        let (prefix, suffix) = sess.staticlib_components(verbatim);
                        Some(format!("{prefix}{name}{suffix}"))
                    } else if sess.target.linker_flavor.is_gnu() {
                        Some(format!("-l{}{}", if verbatim { ":" } else { "" }, name))
                    } else {
                        Some(format!("-l{name}"))
                    }
                }
                NativeLibKind::Framework { .. } => {
                    // ld-only syntax, since there are no frameworks in MSVC
                    Some(format!("-framework {name}"))
                }
                // These are included, no need to print them
                NativeLibKind::Static { bundle: None | Some(true), .. }
                | NativeLibKind::LinkArg
                | NativeLibKind::WasmImportModule
                | NativeLibKind::RawDylib { .. } => None,
            }
        })
        // deduplication of consecutive repeated libraries, see rust-lang/rust#113209
        .dedup()
        .collect();
    for path in all_rust_dylibs {
        // FIXME deduplicate with add_dynamic_crate

        // Just need to tell the linker about where the library lives and
        // what its name is
        let parent = path.parent();
        if let Some(dir) = parent {
            let dir = fix_windows_verbatim_for_gcc(dir);
            if sess.target.is_like_msvc {
                let mut arg = String::from("/LIBPATH:");
                arg.push_str(&dir.display().to_string());
                lib_args.push(arg);
            } else {
                lib_args.push("-L".to_owned());
                lib_args.push(dir.display().to_string());
            }
        }
        let stem = path.file_stem().unwrap().to_str().unwrap();
        // Convert library file-stem into a cc -l argument.
        let lib = if let Some(lib) = stem.strip_prefix("lib")
            && !sess.target.is_like_windows
        {
            lib
        } else {
            stem
        };
        let path = parent.unwrap_or_else(|| Path::new(""));
        if sess.target.is_like_msvc {
            // When producing a dll, the MSVC linker may not actually emit a
            // `foo.lib` file if the dll doesn't actually export any symbols, so we
            // check to see if the file is there and just omit linking to it if it's
            // not present.
            let name = format!("{lib}.dll.lib");
            if path.join(&name).exists() {
                lib_args.push(name);
            }
        } else {
            lib_args.push(format!("-l{lib}"));
        }
    }

    match out {
        OutFileName::Real(path) => {
            out.overwrite(&lib_args.join(" "), sess);
            sess.dcx().emit_note(errors::StaticLibraryNativeArtifactsToFile { path });
        }
        OutFileName::Stdout => {
            sess.dcx().emit_note(errors::StaticLibraryNativeArtifacts);
            // Prefix for greppability
            // Note: This must not be translated as tools are allowed to depend on this exact string.
            sess.dcx().note(format!("native-static-libs: {}", lib_args.join(" ")));
        }
    }
}

fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf {
    let file_path = sess.target_tlib_path.dir.join(name);
    if file_path.exists() {
        return file_path;
    }
    // Special directory with objects used only in self-contained linkage mode
    if self_contained {
        let file_path = sess.target_tlib_path.dir.join("self-contained").join(name);
        if file_path.exists() {
            return file_path;
        }
    }
    for search_path in sess.target_filesearch().search_paths(PathKind::Native) {
        let file_path = search_path.dir.join(name);
        if file_path.exists() {
            return file_path;
        }
    }
    PathBuf::from(name)
}

fn exec_linker(
    sess: &Session,
    cmd: &Command,
    out_filename: &Path,
    flavor: LinkerFlavor,
    tmpdir: &Path,
) -> io::Result<Output> {
    // When attempting to spawn the linker we run a risk of blowing out the
    // size limits for spawning a new process with respect to the arguments
    // we pass on the command line.
    //
    // Here we attempt to handle errors from the OS saying "your list of
    // arguments is too big" by reinvoking the linker again with an `@`-file
    // that contains all the arguments (aka 'response' files).
    // The theory is that this is then accepted on all linkers and the linker
    // will read all its options out of there instead of looking at the command line.
    if !cmd.very_likely_to_exceed_some_spawn_limit() {
        match cmd.command().stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() {
            Ok(child) => {
                let output = child.wait_with_output();
                flush_linked_file(&output, out_filename)?;
                return output;
            }
            Err(ref e) if command_line_too_big(e) => {
                info!("command line to linker was too big: {}", e);
            }
            Err(e) => return Err(e),
        }
    }

    info!("falling back to passing arguments to linker via an @-file");
    let mut cmd2 = cmd.clone();
    let mut args = String::new();
    for arg in cmd2.take_args() {
        args.push_str(
            &Escape {
                arg: arg.to_str().unwrap(),
                // Windows-style escaping for @-files is used by
                // - all linkers targeting MSVC-like targets, including LLD
                // - all LLD flavors running on Windows hosts
                // С/С++ compilers use Posix-style escaping (except clang-cl, which we do not use).
                is_like_msvc: sess.target.is_like_msvc
                    || (cfg!(windows) && flavor.uses_lld() && !flavor.uses_cc()),
            }
            .to_string(),
        );
        args.push('\n');
    }
    let file = tmpdir.join("linker-arguments");
    let bytes = if sess.target.is_like_msvc {
        let mut out = Vec::with_capacity((1 + args.len()) * 2);
        // start the stream with a UTF-16 BOM
        for c in std::iter::once(0xFEFF).chain(args.encode_utf16()) {
            // encode in little endian
            out.push(c as u8);
            out.push((c >> 8) as u8);
        }
        out
    } else {
        args.into_bytes()
    };
    fs::write(&file, &bytes)?;
    cmd2.arg(format!("@{}", file.display()));
    info!("invoking linker {:?}", cmd2);
    let output = cmd2.output();
    flush_linked_file(&output, out_filename)?;
    return output;

    #[cfg(not(windows))]
    fn flush_linked_file(_: &io::Result<Output>, _: &Path) -> io::Result<()> {
        Ok(())
    }

    #[cfg(windows)]
    fn flush_linked_file(
        command_output: &io::Result<Output>,
        out_filename: &Path,
    ) -> io::Result<()> {
        // On Windows, under high I/O load, output buffers are sometimes not flushed,
        // even long after process exit, causing nasty, non-reproducible output bugs.
        //
        // File::sync_all() calls FlushFileBuffers() down the line, which solves the problem.
        //
        // А full writeup of the original Chrome bug can be found at
        // randomascii.wordpress.com/2018/02/25/compiler-bug-linker-bug-windows-kernel-bug/amp

        if let &Ok(ref out) = command_output {
            if out.status.success() {
                if let Ok(of) = fs::OpenOptions::new().write(true).open(out_filename) {
                    of.sync_all()?;
                }
            }
        }

        Ok(())
    }

    #[cfg(unix)]
    fn command_line_too_big(err: &io::Error) -> bool {
        err.raw_os_error() == Some(::libc::E2BIG)
    }

    #[cfg(windows)]
    fn command_line_too_big(err: &io::Error) -> bool {
        const ERROR_FILENAME_EXCED_RANGE: i32 = 206;
        err.raw_os_error() == Some(ERROR_FILENAME_EXCED_RANGE)
    }

    #[cfg(not(any(unix, windows)))]
    fn command_line_too_big(_: &io::Error) -> bool {
        false
    }

    struct Escape<'a> {
        arg: &'a str,
        is_like_msvc: bool,
    }

    impl<'a> fmt::Display for Escape<'a> {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            if self.is_like_msvc {
                // This is "documented" at
                // https://docs.microsoft.com/en-us/cpp/build/reference/at-specify-a-linker-response-file
                //
                // Unfortunately there's not a great specification of the
                // syntax I could find online (at least) but some local
                // testing showed that this seemed sufficient-ish to catch
                // at least a few edge cases.
                write!(f, "\"")?;
                for c in self.arg.chars() {
                    match c {
                        '"' => write!(f, "\\{c}")?,
                        c => write!(f, "{c}")?,
                    }
                }
                write!(f, "\"")?;
            } else {
                // This is documented at https://linux.die.net/man/1/ld, namely:
                //
                // > Options in file are separated by whitespace. A whitespace
                // > character may be included in an option by surrounding the
                // > entire option in either single or double quotes. Any
                // > character (including a backslash) may be included by
                // > prefixing the character to be included with a backslash.
                //
                // We put an argument on each line, so all we need to do is
                // ensure the line is interpreted as one whole argument.
                for c in self.arg.chars() {
                    match c {
                        '\\' | ' ' => write!(f, "\\{c}")?,
                        c => write!(f, "{c}")?,
                    }
                }
            }
            Ok(())
        }
    }
}

fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
    let kind = match (crate_type, sess.crt_static(Some(crate_type)), sess.relocation_model()) {
        (CrateType::Executable, _, _) if sess.is_wasi_reactor() => LinkOutputKind::WasiReactorExe,
        (CrateType::Executable, false, RelocModel::Pic | RelocModel::Pie) => {
            LinkOutputKind::DynamicPicExe
        }
        (CrateType::Executable, false, _) => LinkOutputKind::DynamicNoPicExe,
        (CrateType::Executable, true, RelocModel::Pic | RelocModel::Pie) => {
            LinkOutputKind::StaticPicExe
        }
        (CrateType::Executable, true, _) => LinkOutputKind::StaticNoPicExe,
        (_, true, _) => LinkOutputKind::StaticDylib,
        (_, false, _) => LinkOutputKind::DynamicDylib,
    };

    // Adjust the output kind to target capabilities.
    let opts = &sess.target;
    let pic_exe_supported = opts.position_independent_executables;
    let static_pic_exe_supported = opts.static_position_independent_executables;
    let static_dylib_supported = opts.crt_static_allows_dylibs;
    match kind {
        LinkOutputKind::DynamicPicExe if !pic_exe_supported => LinkOutputKind::DynamicNoPicExe,
        LinkOutputKind::StaticPicExe if !static_pic_exe_supported => LinkOutputKind::StaticNoPicExe,
        LinkOutputKind::StaticDylib if !static_dylib_supported => LinkOutputKind::DynamicDylib,
        _ => kind,
    }
}

// Returns true if linker is located within sysroot
fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
    let linker_with_extension = if cfg!(windows) && linker.extension().is_none() {
        linker.with_extension("exe")
    } else {
        linker.to_path_buf()
    };
    for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
        let full_path = dir.join(&linker_with_extension);
        // If linker comes from sysroot assume self-contained mode
        if full_path.is_file() && !full_path.starts_with(sess.opts.sysroot.path()) {
            return false;
        }
    }
    true
}

/// Various toolchain components used during linking are used from rustc distribution
/// instead of being found somewhere on the host system.
/// We only provide such support for a very limited number of targets.
fn self_contained_components(
    sess: &Session,
    crate_type: CrateType,
    linker: &Path,
) -> LinkSelfContainedComponents {
    // Turn the backwards compatible bool values for `self_contained` into fully inferred
    // `LinkSelfContainedComponents`.
    let self_contained =
        if let Some(self_contained) = sess.opts.cg.link_self_contained.explicitly_set {
            // Emit an error if the user requested self-contained mode on the CLI but the target
            // explicitly refuses it.
            if sess.target.link_self_contained.is_disabled() {
                sess.dcx().emit_err(errors::UnsupportedLinkSelfContained);
            }
            self_contained
        } else {
            match sess.target.link_self_contained {
                LinkSelfContainedDefault::False => false,
                LinkSelfContainedDefault::True => true,

                LinkSelfContainedDefault::WithComponents(components) => {
                    // For target specs with explicitly enabled components, we can return them
                    // directly.
                    return components;
                }

                // FIXME: Find a better heuristic for "native musl toolchain is available",
                // based on host and linker path, for example.
                // (https://github.com/rust-lang/rust/pull/71769#issuecomment-626330237).
                LinkSelfContainedDefault::InferredForMusl => sess.crt_static(Some(crate_type)),
                LinkSelfContainedDefault::InferredForMingw => {
                    sess.host == sess.target
                        && sess.target.abi != Abi::Uwp
                        && detect_self_contained_mingw(sess, linker)
                }
            }
        };
    if self_contained {
        LinkSelfContainedComponents::all()
    } else {
        LinkSelfContainedComponents::empty()
    }
}

/// Add pre-link object files defined by the target spec.
fn add_pre_link_objects(
    cmd: &mut dyn Linker,
    sess: &Session,
    flavor: LinkerFlavor,
    link_output_kind: LinkOutputKind,
    self_contained: bool,
) {
    // FIXME: we are currently missing some infra here (per-linker-flavor CRT objects),
    // so Fuchsia has to be special-cased.
    let opts = &sess.target;
    let empty = Default::default();
    let objects = if self_contained {
        &opts.pre_link_objects_self_contained
    } else if !(sess.target.os == Os::Fuchsia && matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))) {
        &opts.pre_link_objects
    } else {
        &empty
    };
    for obj in objects.get(&link_output_kind).iter().copied().flatten() {
        cmd.add_object(&get_object_file_path(sess, obj, self_contained));
    }
}

/// Add post-link object files defined by the target spec.
fn add_post_link_objects(
    cmd: &mut dyn Linker,
    sess: &Session,
    link_output_kind: LinkOutputKind,
    self_contained: bool,
) {
    let objects = if self_contained {
        &sess.target.post_link_objects_self_contained
    } else {
        &sess.target.post_link_objects
    };
    for obj in objects.get(&link_output_kind).iter().copied().flatten() {
        cmd.add_object(&get_object_file_path(sess, obj, self_contained));
    }
}

/// Add arbitrary "pre-link" args defined by the target spec or from command line.
/// FIXME: Determine where exactly these args need to be inserted.
fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
    if let Some(args) = sess.target.pre_link_args.get(&flavor) {
        cmd.verbatim_args(args.iter().map(Deref::deref));
    }

    cmd.verbatim_args(&sess.opts.unstable_opts.pre_link_args);
}

/// Add a link script embedded in the target, if applicable.
fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_type: CrateType) {
    match (crate_type, &sess.target.link_script) {
        (CrateType::Cdylib | CrateType::Executable, Some(script)) => {
            if !sess.target.linker_flavor.is_gnu() {
                sess.dcx().emit_fatal(errors::LinkScriptUnavailable);
            }

            let file_name = ["rustc", &sess.target.llvm_target, "linkfile.ld"].join("-");

            let path = tmpdir.join(file_name);
            if let Err(error) = fs::write(&path, script.as_ref()) {
                sess.dcx().emit_fatal(errors::LinkScriptWriteFailure { path, error });
            }

            cmd.link_arg("--script").link_arg(path);
        }
        _ => {}
    }
}

/// Add arbitrary "user defined" args defined from command line.
/// FIXME: Determine where exactly these args need to be inserted.
fn add_user_defined_link_args(cmd: &mut dyn Linker, sess: &Session) {
    cmd.verbatim_args(&sess.opts.cg.link_args);
}

/// Add arbitrary "late link" args defined by the target spec.
/// FIXME: Determine where exactly these args need to be inserted.
fn add_late_link_args(
    cmd: &mut dyn Linker,
    sess: &Session,
    flavor: LinkerFlavor,
    crate_type: CrateType,
    codegen_results: &CodegenResults,
) {
    let any_dynamic_crate = crate_type == CrateType::Dylib
        || crate_type == CrateType::Sdylib
        || codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| {
            *ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic)
        });
    if any_dynamic_crate {
        if let Some(args) = sess.target.late_link_args_dynamic.get(&flavor) {
            cmd.verbatim_args(args.iter().map(Deref::deref));
        }
    } else if let Some(args) = sess.target.late_link_args_static.get(&flavor) {
        cmd.verbatim_args(args.iter().map(Deref::deref));
    }
    if let Some(args) = sess.target.late_link_args.get(&flavor) {
        cmd.verbatim_args(args.iter().map(Deref::deref));
    }
}

/// Add arbitrary "post-link" args defined by the target spec.
/// FIXME: Determine where exactly these args need to be inserted.
fn add_post_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
    if let Some(args) = sess.target.post_link_args.get(&flavor) {
        cmd.verbatim_args(args.iter().map(Deref::deref));
    }
}

/// Add a synthetic object file that contains reference to all symbols that we want to expose to
/// the linker.
///
/// Background: we implement rlibs as static library (archives). Linkers treat archives
/// differently from object files: all object files participate in linking, while archives will
/// only participate in linking if they can satisfy at least one undefined reference (version
/// scripts doesn't count). This causes `#[no_mangle]` or `#[used]` items to be ignored by the
/// linker, and since they never participate in the linking, using `KEEP` in the linker scripts
/// can't keep them either. This causes #47384.
///
/// To keep them around, we could use `--whole-archive`, `-force_load` and equivalents to force rlib
/// to participate in linking like object files, but this proves to be expensive (#93791). Therefore
/// we instead just introduce an undefined reference to them. This could be done by `-u` command
/// line option to the linker or `EXTERN(...)` in linker scripts, however they does not only
/// introduce an undefined reference, but also make them the GC roots, preventing `--gc-sections`
/// from removing them, and this is especially problematic for embedded programming where every
/// byte counts.
///
/// This method creates a synthetic object file, which contains undefined references to all symbols
/// that are necessary for the linking. They are only present in symbol table but not actually
/// used in any sections, so the linker will therefore pick relevant rlibs for linking, but
/// unused `#[no_mangle]` or `#[used(compiler)]` can still be discard by GC sections.
///
/// There's a few internal crates in the standard library (aka libcore and
/// libstd) which actually have a circular dependence upon one another. This
/// currently arises through "weak lang items" where libcore requires things
/// like `rust_begin_unwind` but libstd ends up defining it. To get this
/// circular dependence to work correctly we declare some of these things
/// in this synthetic object.
fn add_linked_symbol_object(
    cmd: &mut dyn Linker,
    sess: &Session,
    tmpdir: &Path,
    symbols: &[(String, SymbolExportKind)],
) {
    if symbols.is_empty() {
        return;
    }

    let Some(mut file) = super::metadata::create_object_file(sess) else {
        return;
    };

    if file.format() == object::BinaryFormat::Coff {
        // NOTE(nbdd0121): MSVC will hang if the input object file contains no sections,
        // so add an empty section.
        file.add_section(Vec::new(), ".text".into(), object::SectionKind::Text);

        // We handle the name decoration of COFF targets in `symbol_export.rs`, so disable the
        // default mangler in `object` crate.
        file.set_mangling(object::write::Mangling::None);
    }

    if file.format() == object::BinaryFormat::MachO {
        // Divide up the sections into sub-sections via symbols for dead code stripping.
        // Without this flag, unused `#[no_mangle]` or `#[used(compiler)]` cannot be
        // discard on MachO targets.
        file.set_subsections_via_symbols();
    }

    // ld64 requires a relocation to load undefined symbols, see below.
    // Not strictly needed if linking with lld, but might as well do it there too.
    let ld64_section_helper = if file.format() == object::BinaryFormat::MachO {
        Some(file.add_section(
            file.segment_name(object::write::StandardSegment::Data).to_vec(),
            "__data".into(),
            object::SectionKind::Data,
        ))
    } else {
        None
    };

    for (sym, kind) in symbols.iter() {
        let symbol = file.add_symbol(object::write::Symbol {
            name: sym.clone().into(),
            value: 0,
            size: 0,
            kind: match kind {
                SymbolExportKind::Text => object::SymbolKind::Text,
                SymbolExportKind::Data => object::SymbolKind::Data,
                SymbolExportKind::Tls => object::SymbolKind::Tls,
            },
            scope: object::SymbolScope::Unknown,
            weak: false,
            section: object::write::SymbolSection::Undefined,
            flags: object::SymbolFlags::None,
        });

        // The linker shipped with Apple's Xcode, ld64, works a bit differently from other linkers.
        //
        // Code-wise, the relevant parts of ld64 are roughly:
        // 1. Find the `ArchiveLoadMode` based on commandline options, default to `parseObjects`.
        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/Options.cpp#L924-L932
        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/Options.h#L55
        //
        // 2. Read the archive table of contents (__.SYMDEF file).
        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/archive_file.cpp#L294-L325
        //
        // 3. Begin linking by loading "atoms" from input files.
        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/doc/design/linker.html
        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/InputFiles.cpp#L1349
        //
        //   a. Directly specified object files (`.o`) are parsed immediately.
        //      https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/macho_relocatable_file.cpp#L4611-L4627
        //
        //     - Undefined symbols are not atoms (`n_value > 0` denotes a common symbol).
        //       https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/macho_relocatable_file.cpp#L2455-L2468
        //       https://maskray.me/blog/2022-02-06-all-about-common-symbols
        //
        //     - Relocations/fixups are atoms.
        //       https://github.com/apple-oss-distributions/ld64/blob/ce6341ae966b3451aa54eeb049f2be865afbd578/src/ld/parsers/macho_relocatable_file.cpp#L2088-L2114
        //
        //   b. Archives are not parsed yet.
        //      https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/archive_file.cpp#L467-L577
        //
        // 4. When a symbol is needed by an atom, parse the object file that contains the symbol.
        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/InputFiles.cpp#L1417-L1491
        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/archive_file.cpp#L579-L597
        //
        // All of the steps above are fairly similar to other linkers, except that **it completely
        // ignores undefined symbols**.
        //
        // So to make this trick work on ld64, we need to do something else to load the relevant
        // object files. We do this by inserting a relocation (fixup) for each symbol.
        if let Some(section) = ld64_section_helper {
            apple::add_data_and_relocation(&mut file, section, symbol, &sess.target, *kind)
                .expect("failed adding relocation");
        }
    }

    let path = tmpdir.join("symbols.o");
    let result = std::fs::write(&path, file.write().unwrap());
    if let Err(error) = result {
        sess.dcx().emit_fatal(errors::FailedToWrite { path, error });
    }
    cmd.add_object(&path);
}

/// Add object files containing code from the current crate.
fn add_local_crate_regular_objects(cmd: &mut dyn Linker, codegen_results: &CodegenResults) {
    for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
        cmd.add_object(obj);
    }
}

/// Add object files for allocator code linked once for the whole crate tree.
fn add_local_crate_allocator_objects(
    cmd: &mut dyn Linker,
    codegen_results: &CodegenResults,
    crate_type: CrateType,
) {
    if needs_allocator_shim_for_linking(&codegen_results.crate_info.dependency_formats, crate_type)
    {
        if let Some(obj) = codegen_results.allocator_module.as_ref().and_then(|m| m.object.as_ref())
        {
            cmd.add_object(obj);
        }
    }
}

/// Add object files containing metadata for the current crate.
fn add_local_crate_metadata_objects(
    cmd: &mut dyn Linker,
    sess: &Session,
    archive_builder_builder: &dyn ArchiveBuilderBuilder,
    crate_type: CrateType,
    tmpdir: &Path,
    codegen_results: &CodegenResults,
    metadata: &EncodedMetadata,
) {
    // When linking a dynamic library, we put the metadata into a section of the
    // executable. This metadata is in a separate object file from the main
    // object file, so we create and link it in here.
    if matches!(crate_type, CrateType::Dylib | CrateType::ProcMacro) {
        let data = archive_builder_builder.create_dylib_metadata_wrapper(
            sess,
            &metadata,
            &codegen_results.crate_info.metadata_symbol,
        );
        let obj = emit_wrapper_file(sess, &data, tmpdir, "rmeta.o");

        cmd.add_object(&obj);
    }
}

/// Add sysroot and other globally set directories to the directory search list.
fn add_library_search_dirs(
    cmd: &mut dyn Linker,
    sess: &Session,
    self_contained_components: LinkSelfContainedComponents,
    apple_sdk_root: Option<&Path>,
) {
    if !sess.opts.unstable_opts.link_native_libraries {
        return;
    }

    let fallback = Some(NativeLibSearchFallback { self_contained_components, apple_sdk_root });
    let _ = walk_native_lib_search_dirs(sess, fallback, |dir, is_framework| {
        if is_framework {
            cmd.framework_path(dir);
        } else {
            cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
        }
        ControlFlow::<()>::Continue(())
    });
}

/// Add options making relocation sections in the produced ELF files read-only
/// and suppressing lazy binding.
fn add_relro_args(cmd: &mut dyn Linker, sess: &Session) {
    match sess.opts.cg.relro_level.unwrap_or(sess.target.relro_level) {
        RelroLevel::Full => cmd.full_relro(),
        RelroLevel::Partial => cmd.partial_relro(),
        RelroLevel::Off => cmd.no_relro(),
        RelroLevel::None => {}
    }
}

/// Add library search paths used at runtime by dynamic linkers.
fn add_rpath_args(
    cmd: &mut dyn Linker,
    sess: &Session,
    codegen_results: &CodegenResults,
    out_filename: &Path,
) {
    if !sess.target.has_rpath {
        return;
    }

    // FIXME (#2397): At some point we want to rpath our guesses as to
    // where extern libraries might live, based on the
    // add_lib_search_paths
    if sess.opts.cg.rpath {
        let libs = codegen_results
            .crate_info
            .used_crates
            .iter()
            .filter_map(|cnum| codegen_results.crate_info.used_crate_source[cnum].dylib.as_deref())
            .collect::<Vec<_>>();
        let rpath_config = RPathConfig {
            libs: &*libs,
            out_filename: out_filename.to_path_buf(),
            is_like_darwin: sess.target.is_like_darwin,
            linker_is_gnu: sess.target.linker_flavor.is_gnu(),
        };
        cmd.link_args(&rpath::get_rpath_linker_args(&rpath_config));
    }
}

fn add_c_staticlib_symbols(
    sess: &Session,
    lib: &NativeLib,
    out: &mut Vec<(String, SymbolExportKind)>,
) -> io::Result<()> {
    let file_path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess);

    let archive_map = unsafe { Mmap::map(File::open(&file_path)?)? };

    let archive = object::read::archive::ArchiveFile::parse(&*archive_map)
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;

    for member in archive.members() {
        let member = member.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;

        let data = member
            .data(&*archive_map)
            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;

        // clang LTO: raw LLVM bitcode
        if data.starts_with(b"BC\xc0\xde") {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "LLVM bitcode object in C static library (LTO not supported)",
            ));
        }

        let object = object::File::parse(&*data)
            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;

        // gcc / clang ELF / Mach-O LTO
        if object.sections().any(|s| {
            s.name().map(|n| n.starts_with(".gnu.lto_") || n == ".llvm.lto").unwrap_or(false)
        }) {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "LTO object in C static library is not supported",
            ));
        }

        for symbol in object.symbols() {
            if symbol.scope() != object::SymbolScope::Dynamic {
                continue;
            }

            let name = match symbol.name() {
                Ok(n) => n,
                Err(_) => continue,
            };

            let export_kind = match symbol.kind() {
                object::SymbolKind::Text => SymbolExportKind::Text,
                object::SymbolKind::Data => SymbolExportKind::Data,
                _ => continue,
            };

            // FIXME:The symbol mangle rules are slightly different in Windows(32-bit) and Apple.
            // Need to be resolved.
            out.push((name.to_string(), export_kind));
        }
    }

    Ok(())
}

/// Produce the linker command line containing linker path and arguments.
///
/// When comments in the function say "order-(in)dependent" they mean order-dependence between
/// options and libraries/object files. For example `--whole-archive` (order-dependent) applies
/// to specific libraries passed after it, and `-o` (output file, order-independent) applies
/// to the linking process as a whole.
/// Order-independent options may still override each other in order-dependent fashion,
/// e.g `--foo=yes --foo=no` may be equivalent to `--foo=no`.
fn linker_with_args(
    path: &Path,
    flavor: LinkerFlavor,
    sess: &Session,
    archive_builder_builder: &dyn ArchiveBuilderBuilder,
    crate_type: CrateType,
    tmpdir: &Path,
    out_filename: &Path,
    codegen_results: &CodegenResults,
    metadata: &EncodedMetadata,
    self_contained_components: LinkSelfContainedComponents,
    codegen_backend: &'static str,
) -> Command {
    let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled();
    let cmd = &mut *super::linker::get_linker(
        sess,
        path,
        flavor,
        self_contained_components.are_any_components_enabled(),
        &codegen_results.crate_info.target_cpu,
        codegen_backend,
    );
    let link_output_kind = link_output_kind(sess, crate_type);

    let mut export_symbols = codegen_results.crate_info.exported_symbols[&crate_type].clone();

    if crate_type == CrateType::Cdylib {
        let mut seen = FxHashSet::default();

        for lib in &codegen_results.crate_info.used_libraries {
            if let NativeLibKind::Static { export_symbols: Some(true), .. } = lib.kind
                && seen.insert((lib.name, lib.verbatim))
            {
                if let Err(err) = add_c_staticlib_symbols(&sess, lib, &mut export_symbols) {
                    sess.dcx().fatal(format!(
                        "failed to process C static library `{}`: {}",
                        lib.name, err
                    ));
                }
            }
        }
    }

    // ------------ Early order-dependent options ------------

    // If we're building something like a dynamic library then some platforms
    // need to make sure that all symbols are exported correctly from the
    // dynamic library.
    // Must be passed before any libraries to prevent the symbols to export from being thrown away,
    // at least on some platforms (e.g. windows-gnu).
    cmd.export_symbols(tmpdir, crate_type, &export_symbols);

    // Can be used for adding custom CRT objects or overriding order-dependent options above.
    // FIXME: In practice built-in target specs use this for arbitrary order-independent options,
    // introduce a target spec option for order-independent linker options and migrate built-in
    // specs to it.
    add_pre_link_args(cmd, sess, flavor);

    // ------------ Object code and libraries, order-dependent ------------

    // Pre-link CRT objects.
    add_pre_link_objects(cmd, sess, flavor, link_output_kind, self_contained_crt_objects);

    add_linked_symbol_object(
        cmd,
        sess,
        tmpdir,
        &codegen_results.crate_info.linked_symbols[&crate_type],
    );

    // Sanitizer libraries.
    add_sanitizer_libraries(sess, flavor, crate_type, cmd);

    // Object code from the current crate.
    // Take careful note of the ordering of the arguments we pass to the linker
    // here. Linkers will assume that things on the left depend on things to the
    // right. Things on the right cannot depend on things on the left. This is
    // all formally implemented in terms of resolving symbols (libs on the right
    // resolve unknown symbols of libs on the left, but not vice versa).
    //
    // For this reason, we have organized the arguments we pass to the linker as
    // such:
    //
    // 1. The local object that LLVM just generated
    // 2. Local native libraries
    // 3. Upstream rust libraries
    // 4. Upstream native libraries
    //
    // The rationale behind this ordering is that those items lower down in the
    // list can't depend on items higher up in the list. For example nothing can
    // depend on what we just generated (e.g., that'd be a circular dependency).
    // Upstream rust libraries are not supposed to depend on our local native
    // libraries as that would violate the structure of the DAG, in that
    // scenario they are required to link to them as well in a shared fashion.
    //
    // Note that upstream rust libraries may contain native dependencies as
    // well, but they also can't depend on what we just started to add to the
    // link line. And finally upstream native libraries can't depend on anything
    // in this DAG so far because they can only depend on other native libraries
    // and such dependencies are also required to be specified.
    add_local_crate_regular_objects(cmd, codegen_results);
    add_local_crate_metadata_objects(
        cmd,
        sess,
        archive_builder_builder,
        crate_type,
        tmpdir,
        codegen_results,
        metadata,
    );
    add_local_crate_allocator_objects(cmd, codegen_results, crate_type);

    // Avoid linking to dynamic libraries unless they satisfy some undefined symbols
    // at the point at which they are specified on the command line.
    // Must be passed before any (dynamic) libraries to have effect on them.
    // On Solaris-like systems, `-z ignore` acts as both `--as-needed` and `--gc-sections`
    // so it will ignore unreferenced ELF sections from relocatable objects.
    // For that reason, we put this flag after metadata objects as they would otherwise be removed.
    // FIXME: Support more fine-grained dead code removal on Solaris/illumos
    // and move this option back to the top.
    cmd.add_as_needed();

    // Local native libraries of all kinds.
    add_local_native_libraries(
        cmd,
        sess,
        archive_builder_builder,
        codegen_results,
        tmpdir,
        link_output_kind,
    );

    // Upstream rust crates and their non-dynamic native libraries.
    add_upstream_rust_crates(
        cmd,
        sess,
        archive_builder_builder,
        codegen_results,
        crate_type,
        tmpdir,
        link_output_kind,
    );

    // Dynamic native libraries from upstream crates.
    add_upstream_native_libraries(
        cmd,
        sess,
        archive_builder_builder,
        codegen_results,
        tmpdir,
        link_output_kind,
    );

    // Raw-dylibs from all crates.
    let raw_dylib_dir = tmpdir.join("raw-dylibs");
    if sess.target.binary_format == BinaryFormat::Elf {
        // On ELF we can't pass the raw-dylibs stubs to the linker as a path,
        // instead we need to pass them via -l. To find the stub, we need to add
        // the directory of the stub to the linker search path.
        // We make an extra directory for this to avoid polluting the search path.
        if let Err(error) = fs::create_dir(&raw_dylib_dir) {
            sess.dcx().emit_fatal(errors::CreateTempDir { error })
        }
        cmd.include_path(&raw_dylib_dir);
    }

    // Link with the import library generated for any raw-dylib functions.
    if sess.target.is_like_windows {
        for output_path in raw_dylib::create_raw_dylib_dll_import_libs(
            sess,
            archive_builder_builder,
            codegen_results.crate_info.used_libraries.iter(),
            tmpdir,
            true,
        ) {
            cmd.add_object(&output_path);
        }
    } else {
        for (link_path, as_needed) in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
            sess,
            codegen_results.crate_info.used_libraries.iter(),
            &raw_dylib_dir,
        ) {
            // Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
            cmd.link_dylib_by_name(&link_path, true, as_needed);
        }
    }
    // As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
    // they are used within inlined functions or instantiated generic functions. We do this *after*
    // handling the raw-dylib symbols in the current crate to make sure that those are chosen first
    // by the linker.
    let dependency_linkage = codegen_results
        .crate_info
        .dependency_formats
        .get(&crate_type)
        .expect("failed to find crate type in dependency format list");

    // We sort the libraries below
    #[allow(rustc::potential_query_instability)]
    let mut native_libraries_from_nonstatics = codegen_results
        .crate_info
        .native_libraries
        .iter()
        .filter_map(|(&cnum, libraries)| {
            if sess.target.is_like_windows {
                (dependency_linkage[cnum] != Linkage::Static).then_some(libraries)
            } else {
                Some(libraries)
            }
        })
        .flatten()
        .collect::<Vec<_>>();
    native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str()));

    if sess.target.is_like_windows {
        for output_path in raw_dylib::create_raw_dylib_dll_import_libs(
            sess,
            archive_builder_builder,
            native_libraries_from_nonstatics,
            tmpdir,
            false,
        ) {
            cmd.add_object(&output_path);
        }
    } else {
        for (link_path, as_needed) in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
            sess,
            native_libraries_from_nonstatics,
            &raw_dylib_dir,
        ) {
            // Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
            cmd.link_dylib_by_name(&link_path, true, as_needed);
        }
    }

    // Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
    // command line shorter, reset it to default here before adding more libraries.
    cmd.reset_per_library_state();

    // FIXME: Built-in target specs occasionally use this for linking system libraries,
    // eliminate all such uses by migrating them to `#[link]` attributes in `lib(std,c,unwind)`
    // and remove the option.
    add_late_link_args(cmd, sess, flavor, crate_type, codegen_results);

    // ------------ Arbitrary order-independent options ------------

    // Add order-independent options determined by rustc from its compiler options,
    // target properties and source code.
    add_order_independent_options(
        cmd,
        sess,
        link_output_kind,
        self_contained_components,
        flavor,
        crate_type,
        codegen_results,
        out_filename,
        tmpdir,
    );

    // Can be used for arbitrary order-independent options.
    // In practice may also be occasionally used for linking native libraries.
    // Passed after compiler-generated options to support manual overriding when necessary.
    add_user_defined_link_args(cmd, sess);

    // ------------ Builtin configurable linker scripts ------------
    // The user's link args should be able to overwrite symbols in the compiler's
    // linker script that were weakly defined (i.e. defined with `PROVIDE()`). For this
    // to work correctly, the user needs to be able to specify linker arguments like
    // `--defsym` and `--script` *before* any builtin linker scripts are evaluated.
    add_link_script(cmd, sess, tmpdir, crate_type);

    // ------------ Object code and libraries, order-dependent ------------

    // Post-link CRT objects.
    add_post_link_objects(cmd, sess, link_output_kind, self_contained_crt_objects);

    // ------------ Late order-dependent options ------------

    // Doesn't really make sense.
    // FIXME: In practice built-in target specs use this for arbitrary order-independent options.
    // Introduce a target spec option for order-independent linker options, migrate built-in specs
    // to it and remove the option. Currently the last holdout is wasm32-unknown-emscripten.
    add_post_link_args(cmd, sess, flavor);

    cmd.take_cmd()
}

fn add_order_independent_options(
    cmd: &mut dyn Linker,
    sess: &Session,
    link_output_kind: LinkOutputKind,
    self_contained_components: LinkSelfContainedComponents,
    flavor: LinkerFlavor,
    crate_type: CrateType,
    codegen_results: &CodegenResults,
    out_filename: &Path,
    tmpdir: &Path,
) {
    // Take care of the flavors and CLI options requesting the `lld` linker.
    add_lld_args(cmd, sess, flavor, self_contained_components);

    add_apple_link_args(cmd, sess, flavor);

    let apple_sdk_root = add_apple_sdk(cmd, sess, flavor);

    if sess.target.os == Os::Fuchsia
        && crate_type == CrateType::Executable
        && !matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
    {
        let prefix = if sess.sanitizers().contains(SanitizerSet::ADDRESS) { "asan/" } else { "" };
        cmd.link_arg(format!("--dynamic-linker={prefix}ld.so.1"));
    }

    if sess.target.eh_frame_header {
        cmd.add_eh_frame_header();
    }

    // Make the binary compatible with data execution prevention schemes.
    cmd.add_no_exec();

    if self_contained_components.is_crt_objects_enabled() {
        cmd.no_crt_objects();
    }

    if sess.target.os == Os::Emscripten {
        cmd.cc_arg(if sess.opts.unstable_opts.emscripten_wasm_eh {
            "-fwasm-exceptions"
        } else if sess.panic_strategy().unwinds() {
            "-sDISABLE_EXCEPTION_CATCHING=0"
        } else {
            "-sDISABLE_EXCEPTION_CATCHING=1"
        });
    }

    if flavor == LinkerFlavor::Llbc {
        cmd.link_args(&[
            "--target",
            &versioned_llvm_target(sess),
            "--target-cpu",
            &codegen_results.crate_info.target_cpu,
        ]);
        if codegen_results.crate_info.target_features.len() > 0 {
            cmd.link_arg(&format!(
                "--target-feature={}",
                &codegen_results.crate_info.target_features.join(",")
            ));
        }
    } else if flavor == LinkerFlavor::Ptx {
        cmd.link_args(&["--fallback-arch", &codegen_results.crate_info.target_cpu]);
    } else if flavor == LinkerFlavor::Bpf {
        cmd.link_args(&["--cpu", &codegen_results.crate_info.target_cpu]);
        if let Some(feat) = [sess.opts.cg.target_feature.as_str(), &sess.target.options.features]
            .into_iter()
            .find(|feat| !feat.is_empty())
        {
            cmd.link_args(&["--cpu-features", feat]);
        }
    }

    cmd.linker_plugin_lto();

    add_library_search_dirs(cmd, sess, self_contained_components, apple_sdk_root.as_deref());

    cmd.output_filename(out_filename);

    if crate_type == CrateType::Executable
        && sess.target.is_like_windows
        && let Some(s) = &codegen_results.crate_info.windows_subsystem
    {
        cmd.windows_subsystem(*s);
    }

    // Try to strip as much out of the generated object by removing unused
    // sections if possible. See more comments in linker.rs
    if !sess.link_dead_code() {
        // If PGO is enabled sometimes gc_sections will remove the profile data section
        // as it appears to be unused. This can then cause the PGO profile file to lose
        // some functions. If we are generating a profile we shouldn't strip those metadata
        // sections to ensure we have all the data for PGO.
        let keep_metadata =
            crate_type == CrateType::Dylib || sess.opts.cg.profile_generate.enabled();
        cmd.gc_sections(keep_metadata);
    }

    cmd.set_output_kind(link_output_kind, crate_type, out_filename);

    add_relro_args(cmd, sess);

    // Pass optimization flags down to the linker.
    cmd.optimize();

    // Gather the set of NatVis files, if any, and write them out to a temp directory.
    let natvis_visualizers = collect_natvis_visualizers(
        tmpdir,
        sess,
        &codegen_results.crate_info.local_crate_name,
        &codegen_results.crate_info.natvis_debugger_visualizers,
    );

    // Pass debuginfo, NatVis debugger visualizers and strip flags down to the linker.
    cmd.debuginfo(sess.opts.cg.strip, &natvis_visualizers);

    // We want to prevent the compiler from accidentally leaking in any system libraries,
    // so by default we tell linkers not to link to any default libraries.
    if !sess.opts.cg.default_linker_libraries && sess.target.no_default_libraries {
        cmd.no_default_libraries();
    }

    if sess.opts.cg.profile_generate.enabled() || sess.instrument_coverage() {
        cmd.pgo_gen();
    }

    if sess.opts.cg.control_flow_guard != CFGuard::Disabled {
        cmd.control_flow_guard();
    }

    // OBJECT-FILES-NO, AUDIT-ORDER
    if sess.opts.unstable_opts.ehcont_guard {
        cmd.ehcont_guard();
    }

    add_rpath_args(cmd, sess, codegen_results, out_filename);
}

// Write the NatVis debugger visualizer files for each crate to the temp directory and gather the file paths.
fn collect_natvis_visualizers(
    tmpdir: &Path,
    sess: &Session,
    crate_name: &Symbol,
    natvis_debugger_visualizers: &BTreeSet<DebuggerVisualizerFile>,
) -> Vec<PathBuf> {
    let mut visualizer_paths = Vec::with_capacity(natvis_debugger_visualizers.len());

    for (index, visualizer) in natvis_debugger_visualizers.iter().enumerate() {
        let visualizer_out_file = tmpdir.join(format!("{}-{}.natvis", crate_name.as_str(), index));

        match fs::write(&visualizer_out_file, &visualizer.src) {
            Ok(()) => {
                visualizer_paths.push(visualizer_out_file);
            }
            Err(error) => {
                sess.dcx().emit_warn(errors::UnableToWriteDebuggerVisualizer {
                    path: visualizer_out_file,
                    error,
                });
            }
        };
    }
    visualizer_paths
}

fn add_native_libs_from_crate(
    cmd: &mut dyn Linker,
    sess: &Session,
    archive_builder_builder: &dyn ArchiveBuilderBuilder,
    codegen_results: &CodegenResults,
    tmpdir: &Path,
    bundled_libs: &FxIndexSet<Symbol>,
    cnum: CrateNum,
    link_static: bool,
    link_dynamic: bool,
    link_output_kind: LinkOutputKind,
) {
    if !sess.opts.unstable_opts.link_native_libraries {
        // If `-Zlink-native-libraries=false` is set, then the assumption is that an
        // external build system already has the native dependencies defined, and it
        // will provide them to the linker itself.
        return;
    }

    if link_static && cnum != LOCAL_CRATE && !bundled_libs.is_empty() {
        // If rlib contains native libs as archives, unpack them to tmpdir.
        let rlib = codegen_results.crate_info.used_crate_source[&cnum].rlib.as_ref().unwrap();
        archive_builder_builder
            .extract_bundled_libs(rlib, tmpdir, bundled_libs)
            .unwrap_or_else(|e| sess.dcx().emit_fatal(e));
    }

    let native_libs = match cnum {
        LOCAL_CRATE => &codegen_results.crate_info.used_libraries,
        _ => &codegen_results.crate_info.native_libraries[&cnum],
    };

    let mut last = (None, NativeLibKind::Unspecified, false);
    for lib in native_libs {
        if !relevant_lib(sess, lib) {
            continue;
        }

        // Skip if this library is the same as the last.
        last = if (Some(lib.name), lib.kind, lib.verbatim) == last {
            continue;
        } else {
            (Some(lib.name), lib.kind, lib.verbatim)
        };

        let name = lib.name.as_str();
        let verbatim = lib.verbatim;
        match lib.kind {
            NativeLibKind::Static { bundle, whole_archive, .. } => {
                if link_static {
                    let bundle = bundle.unwrap_or(true);
                    let whole_archive = whole_archive == Some(true);
                    if bundle && cnum != LOCAL_CRATE {
                        if let Some(filename) = lib.filename {
                            // If rlib contains native libs as archives, they are unpacked to tmpdir.
                            let path = tmpdir.join(filename.as_str());
                            cmd.link_staticlib_by_path(&path, whole_archive);
                        }
                    } else {
                        cmd.link_staticlib_by_name(name, verbatim, whole_archive);
                    }
                }
            }
            NativeLibKind::Dylib { as_needed } => {
                if link_dynamic {
                    cmd.link_dylib_by_name(name, verbatim, as_needed.unwrap_or(true))
                }
            }
            NativeLibKind::Unspecified => {
                // If we are generating a static binary, prefer static library when the
                // link kind is unspecified.
                if !link_output_kind.can_link_dylib() && !sess.target.crt_static_allows_dylibs {
                    if link_static {
                        cmd.link_staticlib_by_name(name, verbatim, false);
                    }
                } else if link_dynamic {
                    cmd.link_dylib_by_name(name, verbatim, true);
                }
            }
            NativeLibKind::Framework { as_needed } => {
                if link_dynamic {
                    cmd.link_framework_by_name(name, verbatim, as_needed.unwrap_or(true))
                }
            }
            NativeLibKind::RawDylib { as_needed: _ } => {
                // Handled separately in `linker_with_args`.
            }
            NativeLibKind::WasmImportModule => {}
            NativeLibKind::LinkArg => {
                if link_static {
                    if verbatim {
                        cmd.verbatim_arg(name);
                    } else {
                        cmd.link_arg(name);
                    }
                }
            }
        }
    }
}

fn add_local_native_libraries(
    cmd: &mut dyn Linker,
    sess: &Session,
    archive_builder_builder: &dyn ArchiveBuilderBuilder,
    codegen_results: &CodegenResults,
    tmpdir: &Path,
    link_output_kind: LinkOutputKind,
) {
    // All static and dynamic native library dependencies are linked to the local crate.
    let link_static = true;
    let link_dynamic = true;
    add_native_libs_from_crate(
        cmd,
        sess,
        archive_builder_builder,
        codegen_results,
        tmpdir,
        &Default::default(),
        LOCAL_CRATE,
        link_static,
        link_dynamic,
        link_output_kind,
    );
}

fn add_upstream_rust_crates(
    cmd: &mut dyn Linker,
    sess: &Session,
    archive_builder_builder: &dyn ArchiveBuilderBuilder,
    codegen_results: &CodegenResults,
    crate_type: CrateType,
    tmpdir: &Path,
    link_output_kind: LinkOutputKind,
) {
    // All of the heavy lifting has previously been accomplished by the
    // dependency_format module of the compiler. This is just crawling the
    // output of that module, adding crates as necessary.
    //
    // Linking to a rlib involves just passing it to the linker (the linker
    // will slurp up the object files inside), and linking to a dynamic library
    // involves just passing the right -l flag.
    let data = codegen_results
        .crate_info
        .dependency_formats
        .get(&crate_type)
        .expect("failed to find crate type in dependency format list");

    if sess.target.is_like_aix {
        // Unlike ELF linkers, AIX doesn't feature `DT_SONAME` to override
        // the dependency name when outputting a shared library. Thus, `ld` will
        // use the full path to shared libraries as the dependency if passed it
        // by default unless `noipath` is passed.
        // https://www.ibm.com/docs/en/aix/7.3?topic=l-ld-command.
        cmd.link_or_cc_arg("-bnoipath");
    }

    for &cnum in &codegen_results.crate_info.used_crates {
        // We may not pass all crates through to the linker. Some crates may appear statically in
        // an existing dylib, meaning we'll pick up all the symbols from the dylib.
        // We must always link crates `compiler_builtins` and `profiler_builtins` statically.
        // Even if they were already included into a dylib
        // (e.g. `libstd` when `-C prefer-dynamic` is used).
        let linkage = data[cnum];
        let link_static_crate = linkage == Linkage::Static
            || linkage == Linkage::IncludedFromDylib
                && (codegen_results.crate_info.compiler_builtins == Some(cnum)
                    || codegen_results.crate_info.profiler_runtime == Some(cnum));

        let mut bundled_libs = Default::default();
        match linkage {
            Linkage::Static | Linkage::IncludedFromDylib | Linkage::NotLinked => {
                if link_static_crate {
                    bundled_libs = codegen_results.crate_info.native_libraries[&cnum]
                        .iter()
                        .filter_map(|lib| lib.filename)
                        .collect();
                    add_static_crate(
                        cmd,
                        sess,
                        archive_builder_builder,
                        codegen_results,
                        tmpdir,
                        cnum,
                        &bundled_libs,
                    );
                }
            }
            Linkage::Dynamic => {
                let src = &codegen_results.crate_info.used_crate_source[&cnum];
                add_dynamic_crate(cmd, sess, src.dylib.as_ref().unwrap());
            }
        }

        // Static libraries are linked for a subset of linked upstream crates.
        // 1. If the upstream crate is a directly linked rlib then we must link the native library
        // because the rlib is just an archive.
        // 2. If the upstream crate is a dylib or a rlib linked through dylib, then we do not link
        // the native library because it is already linked into the dylib, and even if
        // inline/const/generic functions from the dylib can refer to symbols from the native
        // library, those symbols should be exported and available from the dylib anyway.
        // 3. Libraries bundled into `(compiler,profiler)_builtins` are special, see above.
        let link_static = link_static_crate;
        // Dynamic libraries are not linked here, see the FIXME in `add_upstream_native_libraries`.
        let link_dynamic = false;
        add_native_libs_from_crate(
            cmd,
            sess,
            archive_builder_builder,
            codegen_results,
            tmpdir,
            &bundled_libs,
            cnum,
            link_static,
            link_dynamic,
            link_output_kind,
        );
    }
}

fn add_upstream_native_libraries(
    cmd: &mut dyn Linker,
    sess: &Session,
    archive_builder_builder: &dyn ArchiveBuilderBuilder,
    codegen_results: &CodegenResults,
    tmpdir: &Path,
    link_output_kind: LinkOutputKind,
) {
    for &cnum in &codegen_results.crate_info.used_crates {
        // Static libraries are not linked here, they are linked in `add_upstream_rust_crates`.
        // FIXME: Merge this function to `add_upstream_rust_crates` so that all native libraries
        // are linked together with their respective upstream crates, and in their originally
        // specified order. This is slightly breaking due to our use of `--as-needed` (see crater
        // results in https://github.com/rust-lang/rust/pull/102832#issuecomment-1279772306).
        let link_static = false;
        // Dynamic libraries are linked for all linked upstream crates.
        // 1. If the upstream crate is a directly linked rlib then we must link the native library
        // because the rlib is just an archive.
        // 2. If the upstream crate is a dylib or a rlib linked through dylib, then we have to link
        // the native library too because inline/const/generic functions from the dylib can refer
        // to symbols from the native library, so the native library providing those symbols should
        // be available when linking our final binary.
        let link_dynamic = true;
        add_native_libs_from_crate(
            cmd,
            sess,
            archive_builder_builder,
            codegen_results,
            tmpdir,
            &Default::default(),
            cnum,
            link_static,
            link_dynamic,
            link_output_kind,
        );
    }
}

// Rehome lib paths (which exclude the library file name) that point into the sysroot lib directory
// to be relative to the sysroot directory, which may be a relative path specified by the user.
//
// If the sysroot is a relative path, and the sysroot libs are specified as an absolute path, the
// linker command line can be non-deterministic due to the paths including the current working
// directory. The linker command line needs to be deterministic since it appears inside the PDB
// file generated by the MSVC linker. See https://github.com/rust-lang/rust/issues/112586.
//
// The returned path will always have `fix_windows_verbatim_for_gcc()` applied to it.
fn rehome_sysroot_lib_dir(sess: &Session, lib_dir: &Path) -> PathBuf {
    let sysroot_lib_path = &sess.target_tlib_path.dir;
    let canonical_sysroot_lib_path =
        { try_canonicalize(sysroot_lib_path).unwrap_or_else(|_| sysroot_lib_path.clone()) };

    let canonical_lib_dir = try_canonicalize(lib_dir).unwrap_or_else(|_| lib_dir.to_path_buf());
    if canonical_lib_dir == canonical_sysroot_lib_path {
        // This path already had `fix_windows_verbatim_for_gcc()` applied if needed.
        sysroot_lib_path.clone()
    } else {
        fix_windows_verbatim_for_gcc(lib_dir)
    }
}

fn rehome_lib_path(sess: &Session, path: &Path) -> PathBuf {
    if let Some(dir) = path.parent() {
        let file_name = path.file_name().expect("library path has no file name component");
        rehome_sysroot_lib_dir(sess, dir).join(file_name)
    } else {
        fix_windows_verbatim_for_gcc(path)
    }
}

// Adds the static "rlib" versions of all crates to the command line.
// There's a bit of magic which happens here specifically related to LTO,
// namely that we remove upstream object files.
//
// When performing LTO, almost(*) all of the bytecode from the upstream
// libraries has already been included in our object file output. As a
// result we need to remove the object files in the upstream libraries so
// the linker doesn't try to include them twice (or whine about duplicate
// symbols). We must continue to include the rest of the rlib, however, as
// it may contain static native libraries which must be linked in.
//
// (*) Crates marked with `#![no_builtins]` don't participate in LTO and
// their bytecode wasn't included. The object files in those libraries must
// still be passed to the linker.
//
// Note, however, that if we're not doing LTO we can just pass the rlib
// blindly to the linker (fast) because it's fine if it's not actually
// included as we're at the end of the dependency chain.
fn add_static_crate(
    cmd: &mut dyn Linker,
    sess: &Session,
    archive_builder_builder: &dyn ArchiveBuilderBuilder,
    codegen_results: &CodegenResults,
    tmpdir: &Path,
    cnum: CrateNum,
    bundled_lib_file_names: &FxIndexSet<Symbol>,
) {
    let src = &codegen_results.crate_info.used_crate_source[&cnum];
    let cratepath = src.rlib.as_ref().unwrap();

    let mut link_upstream =
        |path: &Path| cmd.link_staticlib_by_path(&rehome_lib_path(sess, path), false);

    if !are_upstream_rust_objects_already_included(sess)
        || ignored_for_lto(sess, &codegen_results.crate_info, cnum)
    {
        link_upstream(cratepath);
        return;
    }

    let dst = tmpdir.join(cratepath.file_name().unwrap());
    let name = cratepath.file_name().unwrap().to_str().unwrap();
    let name = &name[3..name.len() - 5]; // chop off lib/.rlib
    let bundled_lib_file_names = bundled_lib_file_names.clone();

    sess.prof.generic_activity_with_arg("link_altering_rlib", name).run(|| {
        let canonical_name = name.replace('-', "_");
        let upstream_rust_objects_already_included =
            are_upstream_rust_objects_already_included(sess);
        let is_builtins =
            sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum);

        let mut archive = archive_builder_builder.new_archive_builder(sess);
        if let Err(error) = archive.add_archive(
            cratepath,
            Box::new(move |f| {
                if f == METADATA_FILENAME {
                    return true;
                }

                let canonical = f.replace('-', "_");

                let is_rust_object =
                    canonical.starts_with(&canonical_name) && looks_like_rust_object_file(f);

                // If we're performing LTO and this is a rust-generated object
                // file, then we don't need the object file as it's part of the
                // LTO module. Note that `#![no_builtins]` is excluded from LTO,
                // though, so we let that object file slide.
                if upstream_rust_objects_already_included && is_rust_object && is_builtins {
                    return true;
                }

                // We skip native libraries because:
                // 1. This native libraries won't be used from the generated rlib,
                //    so we can throw them away to avoid the copying work.
                // 2. We can't allow it to be a single remaining entry in archive
                //    as some linkers may complain on that.
                if bundled_lib_file_names.contains(&Symbol::intern(f)) {
                    return true;
                }

                false
            }),
        ) {
            sess.dcx()
                .emit_fatal(errors::RlibArchiveBuildFailure { path: cratepath.clone(), error });
        }
        if archive.build(&dst) {
            link_upstream(&dst);
        }
    });
}

// Same thing as above, but for dynamic crates instead of static crates.
fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
    cmd.link_dylib_by_path(&rehome_lib_path(sess, cratepath), true);
}

fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
    match lib.cfg {
        Some(ref cfg) => eval_config_entry(sess, cfg).as_bool(),
        None => true,
    }
}

pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool {
    match sess.lto() {
        config::Lto::Fat => true,
        config::Lto::Thin => {
            // If we defer LTO to the linker, we haven't run LTO ourselves, so
            // any upstream object files have not been copied yet.
            !sess.opts.cg.linker_plugin_lto.enabled()
        }
        config::Lto::No | config::Lto::ThinLocal => false,
    }
}

/// We need to communicate five things to the linker on Apple/Darwin targets:
/// - The architecture.
/// - The operating system (and that it's an Apple platform).
/// - The environment.
/// - The deployment target.
/// - The SDK version.
fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
    if !sess.target.is_like_darwin {
        return;
    }
    let LinkerFlavor::Darwin(cc, _) = flavor else {
        return;
    };

    // `sess.target.arch` (`target_arch`) is not detailed enough.
    let llvm_arch = sess.target.llvm_target.split_once('-').expect("LLVM target must have arch").0;
    let target_os = &sess.target.os;
    let target_env = &sess.target.env;

    // The architecture name to forward to the linker.
    //
    // Supported architecture names can be found in the source:
    // https://github.com/apple-oss-distributions/ld64/blob/ld64-951.9/src/abstraction/MachOFileAbstraction.hpp#L578-L648
    //
    // Intentionally verbose to ensure that the list always matches correctly
    // with the list in the source above.
    let ld64_arch = match llvm_arch {
        "armv7k" => "armv7k",
        "armv7s" => "armv7s",
        "arm64" => "arm64",
        "arm64e" => "arm64e",
        "arm64_32" => "arm64_32",
        // ld64 doesn't understand i686, so fall back to i386 instead.
        //
        // Same story when linking with cc, since that ends up invoking ld64.
        "i386" | "i686" => "i386",
        "x86_64" => "x86_64",
        "x86_64h" => "x86_64h",
        _ => bug!("unsupported architecture in Apple target: {}", sess.target.llvm_target),
    };

    if cc == Cc::No {
        // From the man page for ld64 (`man ld`):
        // > The linker accepts universal (multiple-architecture) input files,
        // > but always creates a "thin" (single-architecture), standard
        // > Mach-O output file. The architecture for the output file is
        // > specified using the -arch option.
        //
        // The linker has heuristics to determine the desired architecture,
        // but to be safe, and to avoid a warning, we set the architecture
        // explicitly.
        cmd.link_args(&["-arch", ld64_arch]);

        // Man page says that ld64 supports the following platform names:
        // > - macos
        // > - ios
        // > - tvos
        // > - watchos
        // > - bridgeos
        // > - visionos
        // > - xros
        // > - mac-catalyst
        // > - ios-simulator
        // > - tvos-simulator
        // > - watchos-simulator
        // > - visionos-simulator
        // > - xros-simulator
        // > - driverkit
        let platform_name = match (target_os, target_env) {
            (os, Env::Unspecified) => os.desc(),
            (Os::IOs, Env::MacAbi) => "mac-catalyst",
            (Os::IOs, Env::Sim) => "ios-simulator",
            (Os::TvOs, Env::Sim) => "tvos-simulator",
            (Os::WatchOs, Env::Sim) => "watchos-simulator",
            (Os::VisionOs, Env::Sim) => "visionos-simulator",
            _ => bug!("invalid OS/env combination for Apple target: {target_os}, {target_env}"),
        };

        let min_version = sess.apple_deployment_target().fmt_full().to_string();

        // The SDK version is used at runtime when compiling with a newer SDK / version of Xcode:
        // - By dyld to give extra warnings and errors, see e.g.:
        //   <https://github.com/apple-oss-distributions/dyld/blob/dyld-1165.3/common/MachOFile.cpp#L3029>
        //   <https://github.com/apple-oss-distributions/dyld/blob/dyld-1165.3/common/MachOFile.cpp#L3738-L3857>
        // - By system frameworks to change certain behaviour. For example, the default value of
        //   `-[NSView wantsBestResolutionOpenGLSurface]` is `YES` when the SDK version is >= 10.15.
        //   <https://developer.apple.com/documentation/appkit/nsview/1414938-wantsbestresolutionopenglsurface?language=objc>
        //
        // We do not currently know the actual SDK version though, so we have a few options:
        // 1. Use the minimum version supported by rustc.
        // 2. Use the same as the deployment target.
        // 3. Use an arbitrary recent version.
        // 4. Omit the version.
        //
        // The first option is too low / too conservative, and means that users will not get the
        // same behaviour from a binary compiled with rustc as with one compiled by clang.
        //
        // The second option is similarly conservative, and also wrong since if the user specified a
        // higher deployment target than the SDK they're compiling/linking with, the runtime might
        // make invalid assumptions about the capabilities of the binary.
        //
        // The third option requires that `rustc` is periodically kept up to date with Apple's SDK
        // version, and is also wrong for similar reasons as above.
        //
        // The fourth option is bad because while `ld`, `otool`, `vtool` and such understand it to
        // mean "absent" or `n/a`, dyld doesn't actually understand it, and will end up interpreting
        // it as 0.0, which is again too low/conservative.
        //
        // Currently, we lie about the SDK version, and choose the second option.
        //
        // FIXME(madsmtm): Parse the SDK version from the SDK root instead.
        // <https://github.com/rust-lang/rust/issues/129432>
        let sdk_version = &*min_version;

        // From the man page for ld64 (`man ld`):
        // > This is set to indicate the platform, oldest supported version of
        // > that platform that output is to be used on, and the SDK that the
        // > output was built against.
        //
        // Like with `-arch`, the linker can figure out the platform versions
        // itself from the binaries being linked, but to be safe, we specify
        // the desired versions here explicitly.
        cmd.link_args(&["-platform_version", platform_name, &*min_version, sdk_version]);
    } else {
        // cc == Cc::Yes
        //
        // We'd _like_ to use `-target` everywhere, since that can uniquely
        // communicate all the required details except for the SDK version
        // (which is read by Clang itself from the SDKROOT), but that doesn't
        // work on GCC, and since we don't know whether the `cc` compiler is
        // Clang, GCC, or something else, we fall back to other options that
        // also work on GCC when compiling for macOS.
        //
        // Targets other than macOS are ill-supported by GCC (it doesn't even
        // support e.g. `-miphoneos-version-min`), so in those cases we can
        // fairly safely use `-target`. See also the following, where it is
        // made explicit that the recommendation by LLVM developers is to use
        // `-target`: <https://github.com/llvm/llvm-project/issues/88271>
        if *target_os == Os::MacOs {
            // `-arch` communicates the architecture.
            //
            // CC forwards the `-arch` to the linker, so we use the same value
            // here intentionally.
            cmd.cc_args(&["-arch", ld64_arch]);

            // The presence of `-mmacosx-version-min` makes CC default to
            // macOS, and it sets the deployment target.
            let version = sess.apple_deployment_target().fmt_full();
            // Intentionally pass this as a single argument, Clang doesn't
            // seem to like it otherwise.
            cmd.cc_arg(&format!("-mmacosx-version-min={version}"));

            // macOS has no environment, so with these two, we've told CC the
            // four desired parameters.
            //
            // We avoid `-m32`/`-m64`, as this is already encoded by `-arch`.
        } else {
            cmd.cc_args(&["-target", &versioned_llvm_target(sess)]);
        }
    }
}

fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option<PathBuf> {
    if !sess.target.is_like_darwin {
        return None;
    }
    let LinkerFlavor::Darwin(cc, _) = flavor else {
        return None;
    };

    // The default compiler driver on macOS is at `/usr/bin/cc`. This is a trampoline binary that
    // effectively invokes `xcrun cc` internally to look up both the compiler binary and the SDK
    // root from the current Xcode installation. When cross-compiling, when `rustc` is invoked
    // inside Xcode, or when invoking the linker directly, this default logic is unsuitable, so
    // instead we invoke `xcrun` manually.
    //
    // (Note that this doesn't mean we get a duplicate lookup here - passing `SDKROOT` below will
    // cause the trampoline binary to skip looking up the SDK itself).
    let sdkroot = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?;

    if cc == Cc::Yes {
        // There are a few options to pass the SDK root when linking with a C/C++ compiler:
        // - The `--sysroot` flag.
        // - The `-isysroot` flag.
        // - The `SDKROOT` environment variable.
        //
        // `--sysroot` isn't actually enough to get Clang to treat it as a platform SDK, you need
        // to specify `-isysroot`. This is admittedly a bit strange, as on most targets `-isysroot`
        // only applies to include header files, but on Apple targets it also applies to libraries
        // and frameworks.
        //
        // This leaves the choice between `-isysroot` and `SDKROOT`. Both are supported by Clang and
        // GCC, though they may not be supported by all compiler drivers. We choose `SDKROOT`,
        // primarily because that is the same interface that is used when invoking the tool under
        // `xcrun -sdk macosx $tool`.
        //
        // In that sense, if a given compiler driver does not support `SDKROOT`, the blame is fairly
        // clearly in the tool in question, since they also don't support being run under `xcrun`.
        //
        // Additionally, `SDKROOT` is an environment variable and thus optional. It also has lower
        // precedence than `-isysroot`, so a custom compiler driver that does not support it and
        // instead figures out the SDK on their own can easily do so by using `-isysroot`.
        //
        // (This in particular affects Clang built with the `DEFAULT_SYSROOT` CMake flag, such as
        // the one provided by some versions of Homebrew's `llvm` package. Those will end up
        // ignoring the value we set here, and instead use their built-in sysroot).
        cmd.cmd().env("SDKROOT", &sdkroot);
    } else {
        // When invoking the linker directly, we use the `-syslibroot` parameter. `SDKROOT` is not
        // read by the linker, so it's really the only option.
        //
        // This is also what Clang does.
        cmd.link_arg("-syslibroot");
        cmd.link_arg(&sdkroot);
    }

    Some(sdkroot)
}

fn get_apple_sdk_root(sess: &Session) -> Option<PathBuf> {
    if let Ok(sdkroot) = env::var("SDKROOT") {
        let p = PathBuf::from(&sdkroot);

        // Ignore invalid SDKs, similar to what clang does:
        // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.6/clang/lib/Driver/ToolChains/Darwin.cpp#L2212-L2229
        //
        // NOTE: Things are complicated here by the fact that `rustc` can be run by Cargo to compile
        // build scripts and proc-macros for the host, and thus we need to ignore SDKROOT if it's
        // clearly set for the wrong platform.
        //
        // FIXME(madsmtm): Make this more robust (maybe read `SDKSettings.json` like Clang does?).
        match &*apple::sdk_name(&sess.target).to_lowercase() {
            "appletvos"
                if sdkroot.contains("TVSimulator.platform")
                    || sdkroot.contains("MacOSX.platform") => {}
            "appletvsimulator"
                if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => {}
            "iphoneos"
                if sdkroot.contains("iPhoneSimulator.platform")
                    || sdkroot.contains("MacOSX.platform") => {}
            "iphonesimulator"
                if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => {
            }
            "macosx"
                if sdkroot.contains("iPhoneOS.platform")
                    || sdkroot.contains("iPhoneSimulator.platform")
                    || sdkroot.contains("AppleTVOS.platform")
                    || sdkroot.contains("AppleTVSimulator.platform")
                    || sdkroot.contains("WatchOS.platform")
                    || sdkroot.contains("WatchSimulator.platform")
                    || sdkroot.contains("XROS.platform")
                    || sdkroot.contains("XRSimulator.platform") => {}
            "watchos"
                if sdkroot.contains("WatchSimulator.platform")
                    || sdkroot.contains("MacOSX.platform") => {}
            "watchsimulator"
                if sdkroot.contains("WatchOS.platform") || sdkroot.contains("MacOSX.platform") => {}
            "xros"
                if sdkroot.contains("XRSimulator.platform")
                    || sdkroot.contains("MacOSX.platform") => {}
            "xrsimulator"
                if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {}
            // Ignore `SDKROOT` if it's not a valid path.
            _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
            _ => return Some(p),
        }
    }

    apple::get_sdk_root(sess)
}

/// When using the linker flavors opting in to `lld`, add the necessary paths and arguments to
/// invoke it:
/// - when the self-contained linker flag is active: the build of `lld` distributed with rustc,
/// - or any `lld` available to `cc`.
fn add_lld_args(
    cmd: &mut dyn Linker,
    sess: &Session,
    flavor: LinkerFlavor,
    self_contained_components: LinkSelfContainedComponents,
) {
    debug!(
        "add_lld_args requested, flavor: '{:?}', target self-contained components: {:?}",
        flavor, self_contained_components,
    );

    // If the flavor doesn't use a C/C++ compiler to invoke the linker, or doesn't opt in to `lld`,
    // we don't need to do anything.
    if !(flavor.uses_cc() && flavor.uses_lld()) {
        return;
    }

    // 1. Implement the "self-contained" part of this feature by adding rustc distribution
    // directories to the tool's search path, depending on a mix between what users can specify on
    // the CLI, and what the target spec enables (as it can't disable components):
    // - if the self-contained linker is enabled on the CLI or by the target spec,
    // - and if the self-contained linker is not disabled on the CLI.
    let self_contained_cli = sess.opts.cg.link_self_contained.is_linker_enabled();
    let self_contained_target = self_contained_components.is_linker_enabled();

    let self_contained_linker = self_contained_cli || self_contained_target;
    if self_contained_linker && !sess.opts.cg.link_self_contained.is_linker_disabled() {
        let mut linker_path_exists = false;
        for path in sess.get_tools_search_paths(false) {
            let linker_path = path.join("gcc-ld");
            linker_path_exists |= linker_path.exists();
            cmd.cc_arg({
                let mut arg = OsString::from("-B");
                arg.push(linker_path);
                arg
            });
        }
        if !linker_path_exists {
            // As a sanity check, we emit an error if none of these paths exist: we want
            // self-contained linking and have no linker.
            sess.dcx().emit_fatal(errors::SelfContainedLinkerMissing);
        }
    }

    // 2. Implement the "linker flavor" part of this feature by asking `cc` to use some kind of
    // `lld` as the linker.
    //
    // Note that wasm targets skip this step since the only option there anyway
    // is to use LLD but the `wasm32-wasip2` target relies on a wrapper around
    // this, `wasm-component-ld`, which is overridden if this option is passed.
    if !sess.target.is_like_wasm {
        cmd.cc_arg("-fuse-ld=lld");
    }

    if !flavor.is_gnu() {
        // Tell clang to use a non-default LLD flavor.
        // Gcc doesn't understand the target option, but we currently assume
        // that gcc is not used for Apple and Wasm targets (#97402).
        //
        // Note that we don't want to do that by default on macOS: e.g. passing a
        // 10.7 target to LLVM works, but not to recent versions of clang/macOS, as
        // shown in issue #101653 and the discussion in PR #101792.
        //
        // It could be required in some cases of cross-compiling with
        // LLD, but this is generally unspecified, and we don't know
        // which specific versions of clang, macOS SDK, host and target OS
        // combinations impact us here.
        //
        // So we do a simple first-approximation until we know more of what the
        // Apple targets require (and which would be handled prior to hitting this
        // LLD codepath anyway), but the expectation is that until then
        // this should be manually passed if needed. We specify the target when
        // targeting a different linker flavor on macOS, and that's also always
        // the case when targeting WASM.
        if sess.target.linker_flavor != sess.host.linker_flavor {
            cmd.cc_arg(format!("--target={}", versioned_llvm_target(sess)));
        }
    }
}

// gold has been deprecated with binutils 2.44
// and is known to behave incorrectly around Rust programs.
// There have been reports of being unable to bootstrap with gold:
// https://github.com/rust-lang/rust/issues/139425
// Additionally, gold miscompiles SHF_GNU_RETAIN sections, which are
// emitted with `#[used(linker)]`.
fn warn_if_linked_with_gold(sess: &Session, path: &Path) -> Result<(), Box<dyn std::error::Error>> {
    use object::read::elf::{FileHeader, SectionHeader};
    use object::read::{ReadCache, ReadRef, Result};
    use object::{Endianness, elf};

    fn elf_has_gold_version_note<'a>(
        elf: &impl FileHeader,
        data: impl ReadRef<'a>,
    ) -> Result<bool> {
        let endian = elf.endian()?;

        let section =
            elf.sections(endian, data)?.section_by_name(endian, b".note.gnu.gold-version");
        if let Some((_, section)) = section
            && let Some(mut notes) = section.notes(endian, data)?
        {
            return Ok(notes.any(|note| {
                note.is_ok_and(|note| note.n_type(endian) == elf::NT_GNU_GOLD_VERSION)
            }));
        }

        Ok(false)
    }

    let data = ReadCache::new(BufReader::new(File::open(path)?));

    let was_linked_with_gold = if sess.target.pointer_width == 64 {
        let elf = elf::FileHeader64::<Endianness>::parse(&data)?;
        elf_has_gold_version_note(elf, &data)?
    } else if sess.target.pointer_width == 32 {
        let elf = elf::FileHeader32::<Endianness>::parse(&data)?;
        elf_has_gold_version_note(elf, &data)?
    } else {
        return Ok(());
    };

    if was_linked_with_gold {
        let mut warn =
            sess.dcx().struct_warn("the gold linker is deprecated and has known bugs with Rust");
        warn.help("consider using LLD or ld from GNU binutils instead");
        warn.emit();
    }
    Ok(())
}
