Repository: rust-lang/rust
File: src/bootstrap/src/core/build_steps/llvm.rs (Rust)

Code before:
                ));
            }
            return BuiltEnzyme { enzyme: dylib };
        }

        if !builder.config.dry_run() && !llvm_cmake_dir.is_dir() {
            builder.info(&format!(
                "WARNING: {} does not exist, Enzyme build will likely fail",
                llvm_cmake_dir.display()
            ));
        }

        trace!(?target, "(re)building enzyme artifacts");
        builder.info(&format!("Building Enzyme for {target}"));
        t!(stamp.remove());
        let _time = helpers::timeit(builder);
        t!(fs::create_dir_all(&out_dir));

        let mut cfg = cmake::Config::new(builder.src.join("src/tools/enzyme/enzyme/"));
        // Enzyme devs maintain upstream compatibility, but only fix deprecations when they are about
        // to turn into a hard error. As such, Enzyme generates various warnings which could make it
        // hard to spot more relevant issues.
        let mut cflags = CcFlags::default();
        cflags.push_all("-Wno-deprecated");
        let mut ldflags = LdFlags::default();
        ldflags.push_all("-fuse-ld=lld");
        configure_cmake(builder, target, &mut cfg, true, ldflags, cflags, &[]);

        // Re-use the same flags as llvm to control the level of debug information
        // generated by Enzyme.
        // FIXME(ZuseZ4): Find a nicer way to use Enzyme Debug builds.
        let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {
            (false, _) => "Debug",
            (true, false) => "Release",
            (true, true) => "RelWithDebInfo",
        };
        trace!(?profile);

        cfg.out_dir(&out_dir)
            .profile(profile)
            .env("LLVM_CONFIG_REAL", &host_llvm_config)
            .define("LLVM_ENABLE_ASSERTIONS", "ON")
            .define("ENZYME_EXTERNAL_SHARED_LIB", "ON")
            .define("ENZYME_BC_LOADER", "OFF")
            .define("LLVM_DIR", llvm_cmake_dir);

        cfg.build();

        // At this point, `out_dir` should contain the built libEnzyme-<LLVM-version>.<dylib-ext>
        // file.
        if !dylib.exists() {

Review comment (bug):
@Kobzol This is needed on the linux CI with the current setup.
The default is otherwise gnu-ld, which trips over  `/checkout/obj/build/x86_64-unknown-linux-gnu/llvm/lib/libLLVMSupport.a: error adding symbols: File format not recognized` , see here for the failure logs: https://github.com/rust-lang/rust/actions/runs/22168431338/job/64100800611

I don't really want to foce lld onto everyone building Enzyme, any thoughts on how to gate this best?

Code after:
                ));
            }
            return BuiltEnzyme { enzyme: dylib };
        }

        if !builder.config.dry_run() && !llvm_cmake_dir.is_dir() {
            builder.info(&format!(
                "WARNING: {} does not exist, Enzyme build will likely fail",
                llvm_cmake_dir.display()
            ));
        }

        trace!(?target, "(re)building enzyme artifacts");
        builder.info(&format!("Building Enzyme for {target}"));
        t!(stamp.remove());
        let _time = helpers::timeit(builder);
        t!(fs::create_dir_all(&out_dir));

        let mut cfg = cmake::Config::new(builder.src.join("src/tools/enzyme/enzyme/"));
        // Enzyme devs maintain upstream compatibility, but only fix deprecations when they are about
        // to turn into a hard error. As such, Enzyme generates various warnings which could make it
        // hard to spot more relevant issues.
        let mut cflags = CcFlags::default();
        cflags.push_all("-Wno-deprecated");

        // Logic copied from `configure_llvm`
        // ThinLTO is only available when building with LLVM, enabling LLD is required.
        // Apple's linker ld64 supports ThinLTO out of the box though, so don't use LLD on Darwin.
        let mut ldflags = LdFlags::default();
        if builder.config.llvm_thin_lto && !target.contains("apple") {
            ldflags.push_all("-fuse-ld=lld");
        }

        configure_cmake(builder, target, &mut cfg, true, ldflags, cflags, &[]);

        // Re-use the same flags as llvm to control the level of debug information
        // generated by Enzyme.
        // FIXME(ZuseZ4): Find a nicer way to use Enzyme Debug builds.
        let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {
            (false, _) => "Debug",
            (true, false) => "Release",
            (true, true) => "RelWithDebInfo",
        };
        trace!(?profile);

        cfg.out_dir(&out_dir)
            .profile(profile)
            .env("LLVM_CONFIG_REAL", &host_llvm_config)
            .define("LLVM_ENABLE_ASSERTIONS", "ON")
            .define("ENZYME_EXTERNAL_SHARED_LIB", "ON")
            .define("ENZYME_BC_LOADER", "OFF")