19

I'm using Rust, bindgen, and a build script to work on some FFI bindings to a library.

This library is built using OpenMP, so when linking against it, I'd normally pass the -fopenmp flag to the compiler.

How can I get this flag to be set by build.rs when the library is built by Cargo?

Currently, building using Cargo fails, with the failing command being something like:

cc -Wl,--as-needed -Wl,-z,noexecstack -m64 -l gomp -l stdc++
...skipping dozens of paths/files...
 -Wl,-Bdynamic -l dl -l rt -l pthread -l gcc_s -l c -l m -l rt -l pthread -l util

which fails with hundreds of undefined reference to 'GOMP_parallel_end' errors.

Rerunning the generated command above with the -fopenmp flag manually added succeeds.

I can specify the flag using RUSTFLAGS='-C link-args=-fopenmp' before compiling, but is there a way of specifying it from within build.rs?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Dave Challis
  • 3,525
  • 2
  • 37
  • 65
  • 1
    I don't understand, rustc is the rust compiler not a C compiler. use `rustc-flags` is pointless in your case. – Stargateur Jun 01 '18 at 11:42
  • You should use [`openmp-sys`](https://crates.io/crates/openmp-sys) – Stargateur Jun 01 '18 at 11:43
  • 1
    Yup, reading more closely, `rustc-flags` isn't what I want at all, was just looking for a way of adding flags to the `cc` command that gets called during the build. Will look into `openmp-sys` though, wasn't aware of that, thanks. – Dave Challis Jun 01 '18 at 11:45
  • the documentation of openmp-sys tell you how to do it `cc.flag(&env::var("DEP_OPENMP_FLAG").unwrap());` – Stargateur Jun 01 '18 at 11:46
  • Unfortunately I'm not building the C code with the `cc` crate (it's built using its own build scripts), so just need the flag to be present when linking agains the built libs (unless the `cc` crate can be used for that, will check). – Dave Challis Jun 01 '18 at 11:49

2 Answers2

28

This feature was added to Cargo and stabilized in Cargo 1.56.

Linker arguments can be specified in build.rs like so:

// Pass `-fopenmp` to the linker.
println!("cargo:rustc-link-arg=-fopenmp");
Jess Bowers
  • 2,846
  • 1
  • 22
  • 42
ecstaticm0rse
  • 1,436
  • 9
  • 17
24

You cannot could not. See the sibling answer from ecstaticm0rse for an updated answer.


Before then, you can use a Cargo configuration file.

.cargo/config

[build]
rustflags = ["-C", "link-args=-fsome-artisanal-option"]

Execution

$ cargo build --verbose
   Compiling example v0.1.0 (file:///private/tmp/example)
     Running `rustc ...blah blah blah... -C link-args=-fsome-artisanal-option`
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-m64" ...blah blah blah... "-fsome-artisanal-option"
  = note: clang: error: unknown argument: '-fsome-artisanal-option'

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 2
    Thanks, that gets me a bit closer. The reason I was trying to specify it in build.rs is that it needs to be conditional, as the library I'm linking against can be built both with/without openmp, which is detected in `build.rs`. Is the only option to write a `.cargo/config` at compile time from within my build.rs which contains different link args as necessary? – Dave Challis Jun 01 '18 at 18:07
  • 1
    @DaveChallis I don't even know if that would work. What's the harm in adding extra linker flags all the time though? They should just be ignored since none of the symbols are needed. – Shepmaster Jun 01 '18 at 18:40
  • 1
    true, there should be no harm in it, will go down that route for now. – Dave Challis Jun 01 '18 at 21:16