2016-11-27 2 views
3

Ich versuche, ein Rust-Programm mit zu verknüpfen. Ich benutze Windows und es ist ein GCC-Binärdownload verfügbar. Ich kann es so verknüpfen, wenn ich es in dem gleichen Ordner wie mein Projekt setzen:Wie gebe ich den Linker-Pfad in Rust an?

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

Aber ich will wirklich #[link(name = "libsoundio")] oder sogar #[link(name = "soundio")], spezifizieren und dann woanders einen Linker Weg geben.

Wo kann ich diesen Pfad angeben?

Ich versuchte, den rustc-link-search Vorschlag wie folgt:

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

Und in .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"] 

Aber es noch geht nur "-l" "libsoundio" zu gcc und schlägt mit dem gleichen ld: cannot find -llibsoundio. Fehle ich etwas wirklich offensichtlich? Die Dokumente scheinen darauf hinzuweisen, dass dies funktionieren sollte.

Antwort

0

Mit rustc verwenden -L und -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. 
... 

Hinweis, mit -l Sie das Präfix lib und die Erweiterung .a Ihrer statischen Bibliothek ablegen sollte: -lsoundio

+0

Vielleicht etwas, aber das fehlt mir scheint nicht zu funktionieren. Siehe meine Frage bearbeiten. – Timmmm

+0

Versuchen Sie, das Präfix "lib" zu entfernen: '-l soundio' – Lud

+0

Kein Effekt, es ist wie es ist nicht einmal mit der' .cargo/config'. Ich vermute, dass es etwas mit dem '.libsoundio'-Bit zu tun hat, aber es scheint keine Möglichkeit zu geben, Cargo dazu zu bringen, seine Build-Konfiguration zu drucken, so dass es schwer zu debuggen ist! – Timmmm

6

Wie in der documentation for a build script erklärte:

Alle Linien printe d to stout durch ein Build-Skript [... start] mit wird direkt von Cargo [...] interpretiert rustc-link-search zeigt an, dass der angegebene Wert als -L Flag an den Compiler übergeben werden soll.

In Ihrem Cargo.toml:

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

Und Ihre build.rs:

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

Beachten Sie, dass Ihr Build-Skript alle Macht von Rust verwenden können, und können Ausgabe unterschiedlicher Werte abhängig von der Zielplattform (z. B. 32- und 64-Bit).

Schließlich Code:

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

Der Beweis ist in den Pudding:

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

Idealerweise erstellen Sie ein soundio-sys Paket, mit the convention for *-sys packages. Das hat einfach ein Build-Skript, das mit den entsprechenden Bibliotheken verknüpft und die C-Methoden verfügbar macht. Es wird die Cargo links key verwenden, um die native Bibliothek eindeutig zu identifizieren und zu verhindern, dass sie mehrfach verlinkt wird. Andere Bibliotheken können dann diese neue Kiste einschließen und sich nicht um diese Verknüpfungsdetails kümmern.

2

fand ich etwas, das OK funktioniert:

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

Dies gibt an, dass das Projekt Links zu libsoundio: Sie links in Ihrem Cargo.toml angeben. Jetzt können Sie den Suchpfad und Bibliotheksnamen in der .cargo/config-Datei angeben: (. Der : Präfix GCC die tatsächlichen Dateinamen zu verwenden, sagt und nicht alle seine idiotische lib -prepending und Erweiterung Magie zu tun)

[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"] 

Sie müssen auch eine leere build.rs erstellen:

fn main() {} 

Diese Datei ausgeführt wird nie, weil die Werte in .cargo/config seinen Ausgang außer Kraft setzen, aber für einige reaso n Cargo benötigt es immer noch - jedes Mal, wenn Sie links = verwenden, müssen Sie build = haben, auch wenn es nicht verwendet wird.

schließlich in main.rs:

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

Danke! Wie kann ich einen Namen für mein Ziel bekommen (ich benutze Mac und Linux). Soll ich '.cargo/config' in die Versionskontrolle einbinden oder sollte es für jeden Entwickler anders sein? – Envek

+0

Das Ziel wird durch Rostup eingestellt. Run 'Rostaufführung'. (Oder Sie können den Standard mit etwas wie 'cargo --target blah' überschreiben.)' .cargo/config' sollte in Versionskontrolle sein. Die meisten Leute scheinen jedoch eine nicht leere "build.rs" zu verwenden, anstatt ".cargo/config". – Timmmm

Verwandte Themen