Add a way to set arbitrary rpaths.
vext01 opened this issue Β· 31 comments
Hi,
Consider this minimal example project:
https://github.com/vext01/rust_link_test
The project has a dependency written in C which is built by the build.rs
.
For the examples or tests to work, the shared object for the C code needs to be in the linker path:
Running target/debug/deps/link_test-8d72230c7bcf790a
/home/vext01/research/link_test/target/debug/deps/link_test-8d72230c7bcf790a: error while loading shared libraries: libcstuff.so: cannot open shared object file: No such file or directory
If I set LD_LIBRARY_PATH
to c_lib
then everything works. The standard way to work around having to set the LD_LIBRARY_PATH
is to encode an rpath into the consuming binary (in this case the example or test binary).
Whilst the example be fixed using, e.g.:
#![link_args="-Wl,-rpath /home/vext01/research/link_test/c_lib"]
At the top of the file, the same doesn't appear to be true of tests.
Another thing that bothers me about using link_args
is that it assumes that the path is known, but typically that's a detail that only the build script will know.
Cargo build scripts already have cargo:rustc-link-lib
which allows this kind of thing to add linkage to a given library:
println!("cargo:rustc-link-lib=cstuff");
Why not have a more general interface whereby arbitrary linker flags can be passed?
Hope this make sense.
Does RUSTFLAGS
or cargo rustc
help for this use case?
Hi Alex.
I'm looking at the --help
messages for these commands wondering which flags you mean. I can't see one that would allow my to pass a linker flag.
Even if there were, it would be useful if we could control this stuff in build.rs
, rather than having the user have to specify in their env.
Any thoughts on this Alex?
Ah sorry, but RUSTFLAGS
is an environment variable that Cargo uses to pass to rustc invocations, and cargo rustc
is a way to pass custom flags to the final invocation. Currently build scripts can't embed rpaths because they can't pass along arbitrary flags to rustc.
Currently rustc itself basically doesn't have great support for this unfortunately, the story around passing linker flags and such hasn't been fully fleshed out there.
Thanks Alex.
I'm aware of RUSTFLAGS
but I don't think it helps in this scenario.
Indeed, linkage options are a little limited and somewhat inconsistent in Rust.
I notice that #[link_args]
is always deemed an "unused attribute" also. I tend to think that #[link_args]
would be unnecessary if build.rs
were able to set arbitrary linker flags, and this would also solve this issue. I suppose this would require a flag to be added to rustc
also.
Just to elaborate on this, I think software authors should be able to specify their own link flags in build.rs
without having to ask their downstream users to set environment variables.
I've been thinking about this again. I think the best thing we could do is allow -C
codegen arguments to appear in the Cargo rustc-flags=...
directive.
This should be inheritable, like rustc-link-search
is, so that consumers of a Rust library which builds (e.g.) C shared objects in a non-standard location need do nothing extra. The Rust library providing the extra libs should be able to have:
println!("rustc-flags='-C link-arg=-Wl,-rpath=...'");
or similar in build.rs
.
Being able to set a custom rpath is also important when bundling a binary as a Mac OS X app with embedded frameworks -- in this case, you need to encode an rpath of e.g. @executable_path/../Frameworks
into the binary. It would be really nice to have a way of doing that from a build.rs
script.
I'm having the exact same issue. In order to get this to work I have to do this in a .cargo/config
[target.x86_64-apple-darwin]
rustflags = ["-C", "link-arg=-Wl,-rpath,/some/path/here"]
Problem is that I either want:
/some/path
to be an environment variable or- Be able to pass it from
build.rs
But none of these works for me. In my case I would be fine with .cargo/config
supporting to expand environment variables but of course passing it directly from build.rs
would be ideal.
edit:
Now that I think about it. Maybe #![link_args="-Wl,-rpath /home/vext01/research/link_test/c_lib"]
is usable in my case. I could have build.rs
generate a file that includes that line where I have expanded the variable myself. This would be a work-around for sure but hopefully it will be helpful in my case but some better support would be nice without this of course :)
I'm willing to work on this if we can find an inoffesive way for the user to pass down the flags.
What did people think of:
println!("rustc-flags='-C link-arg=-Wl,-rpath=...'");
In build.rs?
@vext01 this is exactly what we're looking for as well (customizing the rpath
dynamically when building in a development environment).
CMake could set the rpath of an executable to any location defined by a variable and reset the rpath of an executable to any other locations when running cmake install
, which is very convenient for development and production
Hope cargo could implement something similar, or at least support using some variables to set the content of link-arg
Is this issue working now? I do not want to set LD_LIBRARY_PATH
or add extra command or set the environment.
Hitting this problem as well. For us it's pretty common to build dynamic libraries (it is often the case with Linux-like-embedded, openwrt, buildroot etc) and link other binaries to them. I also thought of copying the library into the path where tests, Rust binaries are, but there's no way of finding out all paths. There's a better way of doing this currently? Thanks!
Ditto. I'm thinking setting the rpath to $ORIGIN would help, if your build.rs
knows where build tests/executables will land, and can copy the built library to the same directory. Don't know how to exactly accomplish this though, especially for downstream consumers of your library. this effects all platforms, including windows
(on windows, you can sort of get around it by copying the dll to the crate root, as long as you're issuing your cargo run
commands from there. Maybe this will work on linux if you LD_LIBRARY_PATH=.)
I've finally found a way to add an rpath in a build script.
If you invoke nightly cargo with -Z extra-link-arg
, then you can use cargo:rustc-link-arg
in your build script.
Using that you can do stuff like:
println!("cargo:rustc-link-arg=-Wl,-rpath={}", lib_dir);
This seems to work, and you could load lib_dir
from the environment if you so wished (so I think this helps @emoon above).
I suspect the reason we've all missed this is because -Z extra-link-arg
is missing from-Z help
.
What's slightly annoying is that you have to remember to manually type -Z extra-link-arg
when invoking cargo. You can't re-alias cargo build
in .cargo/config
to add it automatically, as you are not allowed to shadow built-in targets.
The best I've come up with so far is a cargo wrapper like this:
#!/bin/sh
cargo -Z extra-link-arg $*
Then run ./cargo.sh
instead of cargo
.
I also looked at making cargo's cargo:rustc-flags
accept arbitrary arguments, but it looks hard. Cargo passes different arguments to different crate types and at different stages of the build, so arbitrary flaggage isn't going to fit well, I don't think.
I see there is another issue relating to arbitrary flags already.
Some of the "don't want to set LD_LIBRARY_PATH
" use cases can be covered by
// build.rs
// make cargo run and cargo test work without setting LD_LIBRARY_PATH
println!("cargo:rustc-env=LD_LIBRARY_PATH={}", p.display());
Not sure why this works or was ever intended to work, but it does make things bearable for me.
Regardless, I would like to see this feature happen as well because it might make my use case a little easier.
My use case:
- I have an existing C project that has a bunch of internal libraries and a C based CLI.
- I am implementing a new binary in Rust that should link against the project's internal C libraries, i.e., those C libraries are in the builddir but not installed on the system.
- We want to enable in-tree development to be seamless:
-
cargo run
andcargo test
should just work- above trick makes this work
- rust-gdb target/debug/deps/sometestbinary-1234656425 should just work
- I think setting
rpath
would do it, but just for test binaries.
- I think setting
- Predefined linker flags should be inherited from the build system (autotools in that case) -
- Right now we generate a
.cargo/config.toml
with[target....] rustflags = $generated
before we invokecargo build
from the autotools-generated Makefile. Had to really bend over backwards to get this to fly and it's a dirty hack. - I don't think the scope of this issue is sufficient for this use case. We'd need to set arbitrary linker flags and that proposal seems to have been abandoned.
- Right now we generate a
-
Notes:
- I think we'd need the build script be able to detect whether it builds a test so that it can
...-rpath={}...
only in that case. (After all we don't want the binaries we build for distribution to contain the build machine'srpath
.)
println!("cargo:rustc-env=LD_LIBRARY_PATH={}", p.display());
That'll work if you run your program via cargo, but not if you want your binary to be stand-alone.
We'd need to set arbitrary linker flags and that proposal seems to have been abandoned.
Agreed, and this is particularly acute for embedded applications, where folks often have to do linker gymnastics.
I need this quite often. Yes, .cargo/config
helps, but I think most would agree that it should be available in build.rs
too.
plus one on this, rpath is really the only way to neatly package up shared libs.
I've finally found a way to add an rpath in a build script.
If you invoke nightly cargo with
-Z extra-link-arg
, then you can usecargo:rustc-link-arg
in your build script.Using that you can do stuff like:
println!("cargo:rustc-link-arg=-Wl,-rpath={}", lib_dir);
This seems to work, and you could load
lib_dir
from the environment if you so wished (so I think this helps @emoon above).
@vext01 I'm trying to do something similar. I've found that this works for example if you build a binary directly out of a *-sys
crate. But if I use that crate from a different crate, it doesn't work. From what I can tell, the linker args are only included when building the *-sys
crate (which makes sense), but when that's built from the top-level crate, we're not building a dynamic object -- we're building an archive file. So we lose this information. Have you worked around this? Or are you doing something different?
Relatedly, if my last comment is correct, then I think that's a reason not to do this with generic linker flags, but to first-class the idea of rpaths instead. Say you have a crate A that depends on b-sys
(a binding crate for libb). The build for b-sys will often use pkg-config or something similar to locate the library. b-sys needs to expose metadata that says when building A, the resulting binaries should have have path P on their rpath. The solution with generic linker flags allows this to work for binaries built as part of b-sys
(like examples, tests, etc.) but not anything that uses b-sys
, unless I've misunderstood something.
I'm having the exact same problem. A build script for OpenCV uses libclang, which on macOS lives where ever you installed Xcode. So the chain of opencv build.rs -> clang -> clang-sys doesn't work. clang-sys finds libclang.dylib just fine but has no way of propagating rpath back up to clang and OpenCV's build.rs. As a library maintainer, the idea that your library's environment variables requirement are propagated to all the library users sucks.
I would expect that setting rpath on the non-dylib targets causes it to be picked up by the target, and if the target is not a dylib/executable I'd expect it to go up another level until it's finds a dylib/executable the exact same way link libs do. I don't see a way of mimicking that with any flag wizardryβcargo has to be aware of rpaths for its targets and propagate accordingly.
I'd love to take a stab at this. I didn't understand from the Contributor's Guide what's the procedure for approving feature requests?
Is there a technical reason why this hasn't been addressed yet by the Cargo team? It's been 4 years now,
Really really missing this feature.
The unstable -l link-arg=arbitrary_linker_arguments
argument to rustc would be passed from cargo via cargo:rustc-link-lib
rather than cargo:rustc-link-arg
, so I think could resolve the issue with cargo:rustc-link-arg
not being transitively passed down to reverse dependencies.
However, looking into how C/C++ build systems work, I don't think Cargo build scripts should be setting rpaths. There are several distinct use cases for setting rpaths:
- When C/C++ executables depend on libraries built as shared libraries within the same project, CMake and Meson set rpaths while in the build directory so the executables are runnable without installing them (autotools does something similar but kludgier by replacing executables with shell scripts that set the LD_LIBRARY_PATH environment variable when running the actual executable). Then, in the installation process, the build system removes the rpaths it automatically added. This satisfies Linux distribution requirements that forbid rpaths.
- Sometimes C/C++ projects want to install shared libraries to unusual locations relative to the installation root, for example
$INSTALL_PREFIX/lib/project_specific_subdirectory
. In these cases, the build scripts need to set the rpath to a path relative to the executable's path, for example$ORIGIN/../lib/project_specific_subdirectory
. - Sometimes developers/users want to link to libraries installed in nonstandard paths. In order for the executables to be runnable in the build directory without installing them first, rpaths need to be set. A similar situation happens with NixOS, which installs every package to its own directory and relies on rpaths for installed system packages to be runnable.
I don't think use cases 1 & 2 are relevant for Rust because Rust dylibs aren't very useful without a stable ABI and Rust crates can't link to cdylib crates like normal Rust crates. If a Rust crate is built as a cdylib, that's probably the only artifact that's being distributed.
Please correct me if I'm misunderstanding, but I think most people commenting here are interested in use case 3, as I am.
Relatedly, if my last comment is correct, then I think that's a reason not to do this with generic linker flags, but to first-class the idea of rpaths instead. Say you have a crate A that depends on b-sys (a binding crate for libb). The build for b-sys will often use pkg-config or something similar to locate the library. b-sys needs to expose metadata that says when building A, the resulting binaries should have have path P on their rpath. The solution with generic linker flags allows this to work for binaries built as part of b-sys (like examples, tests, etc.) but not anything that uses b-sys, unless I've misunderstood something.
smklein, knewt, Be-ing, and LexouDuck reacted with thumbs up emoji
This seemed to me like a good idea at first, but the more I think about it, I don't think Cargo build scripts setting arbitrary rpaths would be a great solution. Cargo already has the information it needs to set rpaths; it was given via cargo:rustc-link-search
. Currently cargo sets LD_LIBRARY_PATH/DYLD_FALLBACK_LIBRARY_PATH/PATH for cargo run
and cargo test
, but only for paths within Cargo's target
directory. Cargo documentation explicitly states: "It is the responsibility of the user running Cargo to properly set the environment if additional libraries on the system are needed in the search path."
There are two problems with this:
- Setting those environment variables is a blunt instrument which can interfere with external executables run via std::process::Command, which by default inherits the current process's environment. This can lead to nasty surprises. rpaths do not have this problem.
- It makes dynamic libraries that aren't part of the OS impractical to use with Rust. On Linux, you can document how to install libraries from the system package manager, but that doesn't help on Windows or macOS.
Currently it seems the only practical way to use C/C++ libraries with Rust is to link statically, rely on Linux system package managers, or only link DLLs (Windows)/frameworks (macOS) which are parts of the OS that are guaranteed to be there.
To change this, I propose:
- The current paths which are set in LD_LIBRARY_PATH/DYLD_FALLBACK_LIBRARY_PATH automatically by cargo should be replaced by rpaths. Linux distros might not like this, so there might need to be a command line option to disable this.
cargo install
could remove these rpaths automatically like C/C++ build systems do when installing, but I'm not sure ifcargo install
is usable for Linux distro packages. - All paths passed via
cargo:rustc-link-search
would be set as rpaths automatically, unless they're a system path (/usr/lib
,/lib
, maybe more?). I don't think this should interfere with Linux distro packaging because they'll be linking to libraries in the system paths.
Unfortunately Windows does not have rpaths or anything directly analogous, so setting PATH is the best that could be done unless a feature is added to copy linked DLLs into the build directory and do this recursively for all those DLLs' dependencies.
Great response by @Be-ing - I wholeheartedly agree with the problems highlighted, and the solution proposal given.
To expand on one point:
Unfortunately Windows does not have rpaths or anything directly analogous, so setting PATH is the best that could be done unless a feature is added to copy linked DLLs into the build directory and do this recursively for all those DLLs' dependencies.
Indeed, and I would much rather recommend the latter of the two options, since the typical use-case/design-pattern for dynamic libraries on Windows is to have all the required .dll files in the same folder as the .exe which uses them - because the Windows dynamic linker will always look in .
first, before looking through the PATH environment variable. If the other solution is chosen (messing with the PATH environment variable on Windows), that would likely lead to many of the same nasty hard-to-find issues you mentioned previously in your reply.
Yes, copying the DLLs to the same directory as the executable would be ideal for Windows, but I think it would be harder to implement than using the PATH environment variable. I am baffled that neither Windows nor the MSVC toolchain provides a tool to get the DLLs linked to an executable and recursively all the DLLs those DLLs are linked to considering this is the way Microsoft designed Windows to handle DLLs. Such a tool does exist, but it's written in C# so that doesn't really help Cargo. :/ So if someone wants this feature in Cargo, I suggest starting by writing a Rust library which can recursively find all the DLLs linked to an executable.
The closest analogy to rpath that Windows has is setting a probing path (see Application Configuration Files). However, it's limited to nine paths and is relative to the application directory. Also Cargo does not support application configuration files at this time.
@Be-ing I think that might leave out several important use cases. (I apologize in advance if I've misunderstood something!)
The unstable
-l link-arg=arbitrary_linker_arguments
argument to rustc would be passed from cargo viacargo:rustc-link-lib
rather thancargo:rustc-link-arg
, so I think could resolve the issue withcargo:rustc-link-arg
not being transitively passed down to reverse dependencies.
Can you say more about this?
However, looking into how C/C++ build systems work, I don't think Cargo build scripts should be setting rpaths. There are several distinct use cases for setting rpaths:
1. When C/C++ executables depend on libraries built as shared libraries within the same project, CMake and Meson set rpaths _while in the build directory_ so the executables are runnable without installing them (autotools does something similar but kludgier by replacing executables with shell scripts that set the LD_LIBRARY_PATH environment variable when running the actual executable). Then, in the installation process, the build system removes the rpaths it automatically added. This satisfies [Linux distribution requirements that forbid rpaths](https://docs.fedoraproject.org/en-US/packaging-guidelines/#_beware_of_rpath). 2. Sometimes C/C++ projects want to install shared libraries to unusual locations relative to the installation root, for example `$INSTALL_PREFIX/lib/project_specific_subdirectory`. In these cases, the build scripts need to set the rpath to a path relative to the executable's path, for example `$ORIGIN/../lib/project_specific_subdirectory`. 3. Sometimes developers/users want to link to libraries installed in nonstandard paths. In order for the executables to be runnable in the build directory without installing them first, rpaths need to be set. A similar situation happens with NixOS, which installs every package to its own directory and relies on rpaths for installed system packages to be runnable.
I don't think use cases 1 & 2 are relevant for Rust because Rust dylibs aren't very useful without a stable ABI and Rust crates can't link to cdylib crates like normal Rust crates. If a Rust crate is built as a cdylib, that's probably the only artifact that's being distributed. Please correct me if I'm misunderstanding, but I think most people commenting here are interested in use case 3, as I am.
I think there are other use cases:
- I've got a Rust executable that links to a native shared library using a
*-sys
crate. I intend to ship the executable onto a system that already provides the native library in a known but non-default path (e.g.,/opt/$COMPANY/lib
). I want to be able to run the executable both in the build directory (e.g.,cargo run
) as well as on the production system. People often do this by delivering the native library in the same path on both the build system and production system and adding an rpath entry to the executable that specifies that path. But it's also desirable sometimes for the paths to be different: as a developer in this example I might have the library in$HOME/lib
. - I've got a Rust executable that links to a native shared library using a
*-sys
crate. I intend to ship a bundle that includes both the executable and the shared library. If I assemble the build directory the same way as the production bundle, then I can use one rpath entry (referencing$ORIGIN
) and the executable will work both in the build directory and in production. (There are tradeoffs here, though.) This is basically your use case 2. I'm not sure why you feel this isn't relevant for Rust. - I've got a Rust library crate C1 that links to a native shared library using a
*-sys
crate. I do not know who my consuming crates are. They may be other library crates or executable crates. I don't know how they want to link to the native shared library. Even my consuming crates that are themselves Rust library crates don't necessarily know where the native library will be at runtime. Only the top-level executable crate knows that. Maybe the author of that crate wants to assume it's in a default location (installed by the package manager, for example), or they want to put the library into a known, unbundled, non-default path (like my use case 1), or maybe they'll want to bundle the library (like my use case 2). That should be their choice. - Relatedly: I'm building a
*-sys
crate that provides Rust interfaces for a native library. While working on it, I might be fine assuming the library is in a default location. But I might like to allow the consuming executable to control where the library is found at build-time, whether it's linked statically or dynamically, and if dynamic, then where the library is found at runtime. The choices of build-time location may involve various discovery mechanisms (e.g.,pkg-config
) or an explicit override.
Cross-compilation is another use case that brings these issues into sharp relief. One might want to build a Rust crate against a set of headers and libraries for a target system that's wholly different than the build system. In this case, the build-time library search path is definitely different than the runtime one.
To me, the high order bit is that only the top-level executable builder necessarily knows where the native shared library should be found, both at build time and runtime. Admittedly, some people don't care and don't want to have to think about any of this. They want to be able to install libfoo with the system package manager and depend on foo-sys
and have that work. That's fine -- that can be made to work out of the box using default behavior while still allowing people with these other use cases to choose more precisely what they want.
Relatedly, if my last comment is correct, then I think that's a reason not to do this with generic linker flags, but to first-class the idea of rpaths instead. Say you have a crate A that depends on b-sys (a binding crate for libb). The build for b-sys will often use pkg-config or something similar to locate the library. b-sys needs to expose metadata that says when building A, the resulting binaries should have have path P on their rpath. The solution with generic linker flags allows this to work for binaries built as part of b-sys (like examples, tests, etc.) but not anything that uses b-sys, unless I've misunderstood something.
smklein, knewt, Be-ing, and LexouDuck reacted with thumbs up emojiThis seemed to me like a good idea at first, but the more I think about it, I don't think Cargo build scripts setting arbitrary rpaths would be a great solution. Cargo already has the information it needs to set rpaths; it was given via
cargo:rustc-link-search
. Currently cargo sets LD_LIBRARY_PATH/DYLD_FALLBACK_LIBRARY_PATH/PATH forcargo run
andcargo test
, but only for paths within Cargo'starget
directory. Cargo documentation explicitly states: "It is the responsibility of the user running Cargo to properly set the environment if additional libraries on the system are needed in the search path."There are two problems with this:
1. Setting those environment variables is a blunt instrument which can interfere with external executables run via std::process::Command, which [by default inherits the current process's environment](https://doc.rust-lang.org/std/process/struct.Command.html#method.new). This can lead to [nasty surprises](https://github.com/rust-lang/cargo/issues/2888#issuecomment-431049264). rpaths do not have this problem. 2. It makes dynamic libraries that aren't part of the OS impractical to use with Rust. On Linux, you can document how to install libraries from the system package manager, but that doesn't help on Windows or macOS.
Currently it seems the only practical way to use C/C++ libraries with Rust is to link statically, rely on Linux system package managers, or only link DLLs (Windows)/frameworks (macOS) which are parts of the OS that are guaranteed to be there.
To change this, I propose:
1. The current paths which are set in LD_LIBRARY_PATH/DYLD_FALLBACK_LIBRARY_PATH automatically by cargo should be replaced by rpaths. Linux distros might not like this, so there might need to be a command line option to disable this. `cargo install` could remove these rpaths automatically like C/C++ build systems do when installing, but I'm not sure if `cargo install` is usable for Linux distro packages.
To be clear, you mean that: when cargo run
and cargo test
currently set LD_LIBRARY_PATH and friends (based on their values when you ran cargo
), you're proposing instead that cargo
create rpath
entries in built executables that include whatever happened to be on LD_LIBRARY_PATH
when cargo
was run? That's a little implicit to me. LD_LIBRARY_PATH is by nature transient, applying only to the current shell and children that don't override it. It's a little surprising to bake that into built binaries. This seems almost certainly wrong when cross-compiling, since the build system may look nothing like the runtime system. It wouldn't help if cargo install
removes these because (as I understand it) that's not part of the process people use to build and package executables to deploy elsewhere.
2. All paths passed via `cargo:rustc-link-search` would be set as rpaths automatically, unless they're a system path (`/usr/lib`, `/lib`, maybe more?). I don't think this should interfere with Linux distro packaging because they'll be linking to libraries in the system paths.
I mentioned above why I think this has problems -- the runtime path is not the search path, and the *-sys
crate is not the ultimate decider of where the native shared library should be found at runtime. At most, it could inform the top-level crate where it found the library on the build system. (You could flip it around so that the top-level crate can tell the *-sys
crate where to find the library at runtime and then the *-sys
crate emits instructions that affect linking of the top-level crate, but it seems a lot more convoluted than just letting the top-level crate specify what it wants.)
I don't necessarily recommend the following but we've done this with some success:
- The
*-sys
crate we're using already has multiple discovery mechanisms, includingpkg-config
and an explicit override via environment variable. - We modified the
*-sys
crate to emit a piece of metadata saying where it found the library, using metadata key-value pairs. - Our top-level executable crates include a build script that reads this metadata and emits the corresponding
cargo:rustc-link-arg
instructions. (We abstracted this into its own crate that can go into the top-level crates' build-dependencies.) - These top-level executable crates (which mostly depend on the
*-sys
crate indirectly) have an extra explicit dependency on the*-sys
crate version*
, solely to be able to consume the metadata emitted by the*-sys
crate in their build scripts.
I mention this by way of example, not because I think Rust should first-class this approach. It's annoying in a few obvious ways. But it has the effect that the top-level builder can specify where to find the library and the right rpath entries get added. And we can still use the discovery mechanism built into the *-sys
crate. There are many ways Rust could make this easier, but it seems like being able to specify the desired rpath entries needs to be at least part of the answer.
What if the traditional LDFLAGS
were used, simply?
In MacPorts we work around this kind of problem by writing compiler and linker wrapper scripts that get injected into the path ahead of whatever would otherwise be used. Kludgy, but it's often the only way to make certain our choice of compiler and options are used...
Just a note that for build scripts rustc-link-search
doesn't help because paths outside the target directory are removed:
Cargo includes the following paths:
Search paths included from any build script with the rustc-link-search instruction. Paths outside of the target directory are removed. It is the responsibility of the user running Cargo to properly set the environment if additional libraries on the system are needed in the search path.
The base output directory, such as target/debug, and the βdepsβ directory. This is mostly for legacy support of rustc compiler plugins.
The rustc sysroot library path. This generally is not important to most users.