Skip to content

feat: add Build::create_archive and emit_link_directives - #1972

Merged
NobodyXu merged 3 commits into
rust-lang:mainfrom
waltuov:feat/archive-and-link-directives
Oct 3, 2026
Merged

NobodyXu merged 3 commits into
rust-lang:mainfrom
waltuov:feat/archive-and-link-directives

Conversation

@waltuov

@waltuov waltuov commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1818.

Motivation

compile compiles the objects, archives them and emits the cargo link lines. compile_intermediates only does the first step, so a build script that wants to change the objects or build its own archive has to redo the rest by hand, including the C++ stdlib, link modifiers and CUDA runtime handling. For example, rust-lang/rust#157914 builds compiler-rt's archive itself, and musl-math-sys in rust-lang/rust prints its link lines by hand.

What's added

As discussed in the issue:

  • Build::create_archive and Build::try_create_archive take a library name (same rules as compile) and the objects, create lib<name>.a in the output directory with the same archiver commands as compile, and return its path. Objects added with Build::object are included, CUDA device code is linked in, and MSVC targets also get <name>.lib, all as compile does.
  • emit_link_directives and try_emit_link_directives are free functions that take the Build and the path of a library named lib<name>.a (or <name>.lib on MSVC targets, the names rustc looks for) and emit the lines compile emits: the library with its link modifiers, its folder as search path, the C++ stdlib (still once per Build), the wasm and pauthtest sysroot libraries and the CUDA runtime.
let mut build = cc::Build::new();
build.file("foo.c");
let objects = build.compile_intermediates();
// Change the objects here.
let library = build.create_archive("foo", &objects);
cc::emit_link_directives(&build, &library);

Behavior of compile

compile now calls try_create_archive and try_emit_link_directives itself, and its commands and link lines are unchanged. It reads CC_FORCE_DISABLE once more, in try_create_archive, so it prints cargo:rerun-if-env-changed=CC_FORCE_DISABLE twice. Two odd inputs now fail in cc after archiving: compile("lib.a") and out_dir(""). Before, they emitted an empty library name or an empty search path, which rustc rejects, so only builds with cargo_metadata(false) see a difference.

Tests

  • New tests for the archiver commands and returned path (GNU and MSVC), argument errors, and CC_FORCE_DISABLE.
  • A subprocess test checks that compile and the three step path run the same commands and emit the same link lines on linux-gnu (static stdlib and link modifiers), pauthtest, CUDA (device link and cudart, with an nvcc shim) and MSVC.
  • Checked that compile output against main only gains that second CC_FORCE_DISABLE line, for linux-gnu (C, C++, static stdlib, link modifiers, Build::object), pauthtest, wasm32 (WASI and Linux), CUDA and MSVC, and for its error cases.

Tested on Windows with cargo test with and without parallel, clippy with -D warnings for the feature sets, rustdoc with -D warnings, and a check of the library with rustc 1.65. Linux and macOS hosts are covered by CI only.

`compile` compiles objects, archives them and emits the cargo link
lines. `compile_intermediates` covered only the first step. The new
`Build::create_archive` and the free function `emit_link_directives`
(with `try_` variants) cover the other two, and `compile` now calls
the same code, so its commands and output are unchanged.

@NobodyXu NobodyXu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Some feedback on the PR

Comment thread src/lib.rs Outdated
Comment thread src/lib.rs Outdated
Comment thread src/lib.rs

@NobodyXu NobodyXu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@NobodyXu
NobodyXu merged commit 53598f7 into rust-lang:main Oct 3, 2026
82 of 83 checks passed
@waltuov
waltuov deleted the feat/archive-and-link-directives branch October 4, 2026 17:36
@lockfile-maintenance lockfile-maintenance Bot mentioned this pull request Oct 9, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make it possible to recreate the results of compile via compile_intermediates

2 participants