Skip to content

Native libraries for the local crate linked in the wrong order #28595

@alexcrichton

Description

@alexcrichton

There's currently a large comment in the compiler explaining how we link artifacts in this order:

  1. The local object file
  2. Rust dependencies
  3. Local native dependencies
  4. Upstream native dependencies

It also explicitly mentions why 2/3 are a little backwards.

Unfortunately, however, it looks like the ordering above causes link errors in otherwise correct situations. For example let's consider (code example at the end of this issue)

  • We have a dependency, B, which statically links the native library libB
  • We are linking a native dependency libA which depends on libB
  • We are also producing an executable.

The ordering of flags on the command line will be:

[ object file ]  [ B rlib + libB ] [ libA ]

The problem here is that libB is contained in B's rlib, so the ordering of the linker is incorrect, libA shows up after libB. This will cause a linker error if the object file doesn't otherwise reference symbols from B's rlib.

I think that the wording for why steps 2/3 above are swapped is far out of date by this point (with Cargo build scripts and modern methods to link native libraries), so it sounds to me like they should be swapped now. This may cause breakage, but it should always be fixable by restructuring the DAG to more accurately reflect the network of dependencies between C libraries and Rust crates.

# Cargo.toml
[package]
name = "a"
version = "0.1.0"
authors = ["Alex Crichton <[email protected]>"]
build = "build.rs"

[build-dependencies]
gcc = "0.3"
[dependencies]
b = { path = "b" }
// build.rs
extern crate gcc;

fn main() {
    gcc::compile_library("liba.a", &["src/lib.c"]);
}
// src/main.rs
extern crate b;

extern {
    fn a();
}

fn main() {
    unsafe { a(); }
}
// src/lib.c
extern void b(void);

void a(void) {
  b();
}
# b/Cargo.toml
[package]
name = "b"
version = "0.1.0"
authors = ["Alex Crichton <[email protected]>"]
build = "build.rs"

[build-dependencies]
gcc = "0.3"
// b/build.rs
extern crate gcc;

fn main() {
    gcc::compile_library("libb.a", &["src/lib.c"]);
}
// b/src/lib.c
void b() {}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-linkageArea: linking into static, shared libraries and binaries

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions