Open
Description
Consider the following MNWE (minimal non-working example 😄):
~ $ mkdir mwe
~ $ cd mwe
~/mwe $ cargo new a
Created binary (application) `a` package
~/mwe $ cargo new --lib b
Created library `b` package
~/mwe $ cat <<EOF > b/src/lib.rs
> #[used]
> #[link_section = ".mysection"]
> static X: u32 = 0;
> EOF
~/mwe $ echo 'b = { path="../b" }' >> a/Cargo.toml
~/mwe $ cat <<EOF > a/src/main.rs
> extern crate b; // link the crate
>
> fn main() {}
> EOF
~/mwe $ cd a
~/mwe $ cat <<EOF > link.x
> ENTRY(main)
>
> SECTIONS {
> .mysection : ALIGN(8) {
> _START_ = .;
> KEEP(*(.mysection))
> _END_ = .;
> }
> }
>
> ASSERT(_END_ != _START_, "Section empty");
> EOF
~/mwe $ mkdir .cargo
~/mwe $ cat <<EOF > .cargo/config
> [build]
> rustflags = ["-C", "link-arg=-Tlink.x"]
> EOF
~/mwe/a $ cargo build
Compiling a v0.1.0 (/home/jfrimmel/mwe/a)
error: linking with `cc` failed: exit code: 1
|
= note: "cc" [long output omitted (libb-<hash>.rlib included)] -T../link.x"
= note: /usr/bin/ld: Section empty
The setup contains two crates: the binary a
and the dependent crate b
. A custom linker script is used in order to put the contents of .mysection
in a section with the same name. The assert statement makes the error visible: the static variable X
should be moved into that section, making the section 4 bytes in size, but the section is empty.
If the static X
is defined in crate a
, everything works fine:
~/mwe/a $ cat <<EOF > src/main.rs
#[used]
#[link_section = ".mysection"]
static X: u32 = 0;
fn main() {}
EOF
~/mwe/a $ cargo build
Compiling a v0.1.0 (/home/jfrimmel/mwe/a)
Finished dev [unoptimized + debuginfo] target(s) in 0.19s
So the behavior is different when the #[used] #[link_section] static
is placed in a dependency or in the currently build crate.
Am I doing something wrong (in which case it should be documented more clearly) or is there really a bug in the linker?