web-dev-qa-db-ja.com

Rustでリンカーパスを指定するにはどうすればよいですか?

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_で失敗します。私は本当に明らかなものを見逃していますか?ドキュメントはこれがうまくいくことを示唆しているようです。

11
Timmmm

ビルドスクリプトのドキュメント で述べたように:

cargo:で始まるビルドスクリプト[...で始まる]によってstdoutに出力されるすべての行は、Cargo [...]によって直接解釈されます。rustc-link-searchは、指定された値が-Lフラグとしてコンパイラに渡されることを示します。

あなたのCargo.tomlで:

[package]
name = "link-example"
version = "0.1.0"
authors = ["An Devloper <[email protected]>"]
build = "build.rs"

そしてあなたのbuild.rs

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

ビルドスクリプトはRustのすべての機能を使用でき、ターゲットプラットフォーム(32ビットや64ビットなど)に応じて異なる値を出力できる)に注意してください。

最後に、コード:

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);
}

証拠はプリンにあります:

$ cargo run
    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target\debug\linka.exe`
"1.0.3"

理想的には、- soundio-sysパッケージの規約 を使用して*-sysパッケージを作成します。これには、適切なライブラリにリンクし、Cメソッドを公開するビルドスクリプトがあります。 Cargo links key を使用してネイティブライブラリを一意に識別し、複数回リンクされるのを防ぎます。他のライブラリはこの新しいクレートを含めることができ、それらのリンクの詳細について心配する必要はありません。

12
Shepmaster

正常に機能するものが見つかりました:Cargo.tomllinksを指定できます:

[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;
}
5
Timmmm

別の可能な方法は RUSTFLAGS の設定です:

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

これが最も体系的で推奨されるアプローチかどうかはわかりませんが、私の単純なプロジェクトではうまくいきました。

3
hbobenicio

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

0
Lud