如何在Rust中指定链接器路径?

时间:2016-11-27 19:36:59

标签: rust static-linking dynamic-linking rust-cargo

我正在尝试将Rust程序与libsoundio相关联。我正在使用Windows,并且可以使用GCC二进制下载。如果我把它放在与我的项目相同的文件夹中,我可以像这样链接它:

#[link(name = ":libsoundio-1.1.0/i686/libsoundio.a")]
#[link(name = "ole32")]
extern {
    fn soundio_version_string() -> *const c_char;
}

但我真的想指定#[link(name = "libsoundio")]甚至#[link(name = "soundio")],然后在其他地方提供链接器路径。

我可以在哪里指定该路径?

我尝试了rustc-link-search建议如下:

#[link(name = "libsoundio")]
#[link(name = "ole32")]
extern {
    fn soundio_version_string() -> *const c_char;
}

.cargo/config

[target.i686-pc-windows-gnu.libsoundio]
rustc-link-search = ["libsoundio-1.1.0/i686"]
rustc-link-lib = ["libsoundio.a"]

[target.x86_64-pc-windows-gnu.libsoundio]
rustc-link-search = ["libsoundio-1.1.0/x86_64"]
rustc-link-lib = ["libsoundio.a"]

但它仍然只会将"-l" "libsoundio"传递给gcc并失败并使用相同的ld: cannot find -llibsoundio。我错过了一些非常明显的东西吗文档似乎表明这应该有效。

4 个答案:

答案 0 :(得分:9)

documentation for a build script中所述:

  

由[{1}}构建脚本[...起始]打印到stdout的所有行都由Cargo [...] cargo:直接解释,表示应将指定的值传递给编译器作为rustc-link-search标志。

Cargo.toml

-L

您的 build.rs

[package]
name = "link-example"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]
build = "build.rs"

请注意,您的构建脚本可以使用Rust的所有功能,并且可以根据目标平台(例如32位和64位)输出不同的值。

最后,您的代码:

fn main() {
    println!(r"cargo:rustc-link-search=C:\Rust\linka\libsoundio-1.1.0\i686");
}

证据在布丁中:

extern crate libc;

use libc::c_char;
use std::ffi::CStr;

#[link(name = "soundio")]
extern {
    fn soundio_version_string() -> *const c_char;
}

fn main() {
    let v = unsafe { CStr::from_ptr(soundio_version_string()) };
    println!("{:?}", v);
}

理想情况下,您将使用the convention for *-sys packages创建$ cargo run Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs Running `target\debug\linka.exe` "1.0.3" 个包。它只是有一个构建脚本,链接到相应的库并公开C方法。它将使用Cargo links key来唯一标识本机库并防止多次链接。然后其他库可以包含这个新的包,而不用担心链接细节。

答案 1 :(得分:4)

我找到了一些正常的方法:您可以在links中指定Cargo.toml

[package]
links = "libsoundio"
build = "build.rs"

这指定项目链接到libsoundio。现在,您可以在.cargo/config文件中指定搜索路径和库名称:

[target.i686-pc-windows-gnu.libsoundio]
rustc-link-search = ["libsoundio-1.1.0/i686"]
rustc-link-lib = [":libsoundio.a"]

[target.x86_64-pc-windows-gnu.libsoundio]
rustc-link-search = ["libsoundio-1.1.0/x86_64"]
rustc-link-lib = [":libsoundio.a"]

:前缀告诉GCC使用实际文件名,而不是做所有愚蠢的lib - 前置和扩展魔术。)

您还需要创建一个空的build.rs

fn main() {}

此文件永远不会运行,因为.cargo/config中的值会覆盖其输出,但由于某种原因,Cargo仍然需要它 - 只要您使用links =,就必须拥有build =,即使它没有被使用。

最后在main.rs

#[link(name = "libsoundio")]
#[link(name = "ole32")]
extern {
    fn soundio_version_string() -> *const c_char;
}

答案 2 :(得分:1)

另一种可能的方式是setting the RUSTFLAGS,例如:

RUSTFLAGS='-L my/lib/location' cargo build # or cargo run

我不知道这是否是最有条理和推荐的方法,但是它适用于我的简单项目。

答案 3 :(得分:0)

使用rustc,使用-L-l

$ rustc --help
...
-L [KIND=]PATH      Add a directory to the library search path. The
                    optional KIND can be one of dependency, crate, native,
                    framework or all (the default).
-l [KIND=]NAME      Link the generated crate(s) to the specified native
                    library NAME. The optional KIND can be one of static,
                    dylib, or framework. If omitted, dylib is assumed.
...

注意,对于-l,您应该放弃静态库的前缀lib和扩展名.a-lsoundio