Description
Motivation / Requirements
This proposal attempts to provide a supported/official solution for the following requirements:
- Linking is not done by
rustc
. (For example, Chromium usesclang
tooling to link the final executable or dll binary. Such binary contains a mix of object files built byclang
+ ones built byrustc
.) - A custom global allocator can be provided. (For example, Chromium uses PartitionAlloc.)
Status Quo
As discussed in rust-lang/rust#73632 there is currently no official support for linking rlibs using a non-Rust linker. An officially supported way to generate __rust_alloc
is one missing piece of the puzzle here.
So far Chromium has been defining a weak __rust_alloc
, __rust_no_alloc_shim_is_unstable
(see rust-lang/rust#86844 by @bjorn3), etc. as a work around. This workaround stops working after rust-lang/rust#127173 which starts expecting __rust_alloc
to be mangled.
There seems to be some support for adding a flag to rustc
to generate allocator *.a file to pass to the linker - see this comment by @alexcrichton or this comment by @hlopko.
#[global_allocator]
and GlobalAllocator
can be used to provide a custom memory allocator to Rust code. OTOH, IIUC #[global_allocator]
only takes effect if the final linking is driven by rustc
(and one of the requirements here is that linking is not done by rustc
).
Proposal
The proposal here is to introduce a new -Zemit-code-for-final-artifact-to-link
flag for rustc
. When -Zemit-code-for-final-artifact-to-link
flag is passed to rustc
, then it will generate the same additional code as when linking the final binary: allocator-related definitions, maybe other definitions (e.g. for panic behavior). What exact code needs to be generated is a little ambiguous at this point - one way to clarify what this means is to require that this should generate sufficient definitions to ensure that linking by non-rustc
will succeed.
The requirements can then be met by:
- Defining a
#[global_allocator]
inglobal_allocator.rs
(instead of defining__rust_alloc
etc.) - Asking
rustc
to emit__rust_alloc
/__rdl_alloc
(or however these implementation details are named in the future) when buildingglobal_allocator.rlib
- something like:rustc --crate-type=rlib ./global_allocator.rs -Zemit-code-for-final-artifact-to-link
- Build other rlibs as usual (i.e. without
-Zemit-code-for-final-artifact-to-link
) - Using another linker (e.g. one that comes with
clang
) to linkglobal_allocator.rlib
and other rlibs into a final executable/binary.
Open questions
- What should the new command-line flag be called? Does
emit-code-for-final-artifact-to-link
sound ok? - I assume that for now we still want to introduce a new
-Z
flag, because the proposal from Policy change around adding new unstable flags #787 hasn’t yet been adopted. OTOH, if needed we can spell the new option as-Zunstable-options -Cemit-code-for-final-artifact-to-link
- Is it okay to ignore that
GlobalAllocator
doesn’t have an equivalent of__rust_alloc_error_handler
?
Alternatives considered
- Some people proposed
--crate-type=allocator-shim
. I think that it is preferable to keep--crate-type
as a separate, independent knob, because-Z emit-code-for-final-artifact-to-link
probably makes sense not only for--crate-type=rlib
but also for--crate-type=staticlib
. OTOH,-Z emit-code-for-final-artifact-to-link
probably doesn’t make much sense for--crate-type=proc-macro
and is already implied for--crate-type=bin
(not sure aboutcdylib
anddylib
). - Figure out a workaround for Chromium that doesn’t require changes to
rustc
. AFAIK no such workaround has been identified so far, but let me list some ideas that have been considered:- Replicate the new mangling scheme in Chromium’s
//build/rust/std/remap_alloc.cc
- e.g. instead of naming the function__rust_alloc
name it__rust_alloc_whatever_mangled_form_this_has
. IIUC Rust’s mangling scheme includes a hash of the toolchain version + command-line options, and therefore this idea won’t work. I think.
- Replicate the new mangling scheme in Chromium’s
Mentors or Reviewers
- Maybe @bjorn3? (Since they have kindly provided feedback or worked on related tasks in Formal support for linking rlibs using a non-Rust linker rust#73632, Support #[global_allocator] without the allocator shim rust#86844, and Mangle rustc_std_internal_symbols functions rust#127173)
/cc @chbaker0, @alanzhao1, @zmodem from Chromium
Process
The main points of the Major Change Process are as follows:
- File an issue describing the proposal.
- A compiler team member or contributor who is knowledgeable in the area can second by writing
@rustbot second
.- Finding a "second" suffices for internal changes. If however, you are proposing a new public-facing feature, such as a
-C flag
, then full team check-off is required. - Compiler team members can initiate a check-off via
@rfcbot fcp merge
on either the MCP or the PR.
- Finding a "second" suffices for internal changes. If however, you are proposing a new public-facing feature, such as a
- Once an MCP is seconded, the Final Comment Period begins. If no objections are raised after 10 days, the MCP is considered approved.
You can read more about Major Change Proposals on forge.