Cargo: Add a way to define relative paths in rustc-link-search

Created on 7 Mar 2019  ·  3Comments  ·  Source: rust-lang/cargo

Describe the problem you are trying to solve

I'm writing a project that uses zmq and zmq-sys which need to be cross-compiled for arm-unknown-linux-gnueabi.

zmq-sys doesn't compile libzmq on its own but we can specify the lib and include directories by using LIBZMQ_LIB_DIR and LIBZMQ_INCLUDE_DIR. However zmq's build.rs requires zmq-sys, which means I also need a compiled binary for x86_64-unknown-linux-gnu target too. So I can not just use the environment variables of zmq-sys since LIBZMQ_LIB_DIR will point to a wrong directory.

I did the following workaround:

[target.arm-unknown-linux-gnueabi]
linker = "arm-none-linux-gnueabi-gcc"

[target.arm-unknown-linux-gnueabi.zmq]
rustc-link-search = ["native=/home/user/zmq-example/vendor/libzmq/lib/arm"]
rustc-link-lib = ["static=zmq", "dylib=stdc++"]

[target.x86_64-unknown-linux-gnu.zmq]
rustc-link-search = ["native=/home/user/zmq-example/vendor/libzmq/lib/x86_64"]
rustc-link-lib = ["static=zmq", "dylib=stdc++"]

The problem with the above workaround is that all developers need to have the same absolute path to the compiled binaries.

Describe the solution you'd like

I would like to have a way to define a relative path in rustc-link-search.

Another solution could be a way to define a environment variables per target.

C-feature-request

Most helpful comment

So I have a workaround for this problem. I am cross-compiling DBus and have the same problem as you: I have to point the rustc-link-search to some place inside my repository, relative to the root of the repository, not relative to where Cargo extracted the package.

In short, you have to use a build.rs build script to set rustc-link-search.

This is my Cargo config file:

[build]
target = "armv7-unknown-linux-gnueabihf"

[target.armv7-unknown-linux-gnueabihf.dbus]
rustc-link-search = [
    # Provided by the build script.
]

rustc-link-lib = [
    "dbus-1",
    "gcrypt",
    "gpg-error",
    "lz4",
    "lzma",
    "pcre",
    "selinux",
    "systemd",
]

And this is my build.rs build script:

use std::env::var;

fn main() {
    let manifest_dir = var("CARGO_MANIFEST_DIR").unwrap();
    println!("cargo:rustc-link-search={}/libraries/lib/arm-linux-gnueabihf", manifest_dir);
    println!("cargo:rustc-link-search={}/libraries/usr/lib/arm-linux-gnueabihf", manifest_dir);
}

The CARGO_MANIFEST_DIR environment variable points to the crate with the build script, and I placed the external libraries into a libraries folder there. After doing this the build works again, no more hard-coded absolute paths.

Furthermore in your case you would also have to read the TARGET environment variable and set the paths according to it.

All 3 comments

I'm a little confused about the request for relative paths. The paths should support being relative to the package root. Is that not working for you?

You are correct, so let me rephrase: Is there a way to provide paths that are relative to my project's root (/home/user/zmq-example) instead of zmq-sys package's root (/home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/zmq-sys-0.9.0).

I don't want to have absolute paths of my project's root in .cargo/config since it restricts other developers.

So I have a workaround for this problem. I am cross-compiling DBus and have the same problem as you: I have to point the rustc-link-search to some place inside my repository, relative to the root of the repository, not relative to where Cargo extracted the package.

In short, you have to use a build.rs build script to set rustc-link-search.

This is my Cargo config file:

[build]
target = "armv7-unknown-linux-gnueabihf"

[target.armv7-unknown-linux-gnueabihf.dbus]
rustc-link-search = [
    # Provided by the build script.
]

rustc-link-lib = [
    "dbus-1",
    "gcrypt",
    "gpg-error",
    "lz4",
    "lzma",
    "pcre",
    "selinux",
    "systemd",
]

And this is my build.rs build script:

use std::env::var;

fn main() {
    let manifest_dir = var("CARGO_MANIFEST_DIR").unwrap();
    println!("cargo:rustc-link-search={}/libraries/lib/arm-linux-gnueabihf", manifest_dir);
    println!("cargo:rustc-link-search={}/libraries/usr/lib/arm-linux-gnueabihf", manifest_dir);
}

The CARGO_MANIFEST_DIR environment variable points to the crate with the build script, and I placed the external libraries into a libraries folder there. After doing this the build works again, no more hard-coded absolute paths.

Furthermore in your case you would also have to read the TARGET environment variable and set the paths according to it.

Was this page helpful?
0 / 5 - 0 ratings