2016-11-27 1 views
3

J'essaye de relier un programme de rouille avec libsoundio. J'utilise Windows et un téléchargement binaire GCC est disponible. Je peux relier comme ça si je le mets dans le même dossier que mon projet:Comment spécifier le chemin de l'éditeur de liens dans Rust?

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

Mais je veux vraiment préciser #[link(name = "libsoundio")] ou même #[link(name = "soundio")], puis fournir un chemin de liaison ailleurs.

Où puis-je spécifier ce chemin?

J'ai essayé la suggestion rustc-link-search comme suit:

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

Et .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"] 

Mais il passe encore que "-l" "libsoundio" à gcc et échoue avec le même ld: cannot find -llibsoundio. Est-ce que je manque quelque chose de vraiment évident? Les docs semblent suggérer que cela devrait fonctionner.

Répondre

0

Avec rustc, utilisez -L et -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. 
... 

Remarque, avec -l vous devez jeter le préfixe lib et l'extension .a de votre bibliothèque statique: -lsoundio

+0

Peut-être que je manque quelque chose, mais cela ne semble pas fonctionner. Voir ma question éditer. – Timmmm

+0

Essayez de supprimer le préfixe "lib": '-l soundio' – Lud

+0

Aucun effet, c'est comme s'il n'utilisait même pas' .cargo/config'. Je suppose que c'est quelque chose à voir avec le bit '.libsoundio]' mais il ne semble pas y avoir de moyen pour que Cargo imprime sa config de construction donc il est difficile de déboguer! – Timmmm

6

Comme indiqué dans le documentation for a build script:

Toutes les lignes printe d stdout par un script de build [... starting] avec cargo: est interprété directement par Cargo [...] rustc-link-search indique que la valeur spécifiée doit être passée au compilateur sous la forme d'un flag -L.

Dans votre Cargo.toml:

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

Et votre build.rs:

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

Notez que votre script de compilation peut utiliser toute la puissance de la rouille et peut afficher différentes valeurs en fonction de la plate-forme cible (par exemple 32 et 64 bits).

Enfin, votre 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); 
} 

La preuve est dans le pudding:

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

Idéalement, vous allez créer un package soundio-sys, en utilisant the convention for *-sys packages. Cela a simplement un script de construction qui lie aux bibliothèques appropriées et expose les méthodes C. Il utilisera Cargo links key pour identifier de façon unique la bibliothèque native et empêcher les liaisons multiples. D'autres bibliothèques peuvent alors inclure cette nouvelle caisse et ne pas s'inquiéter de ces détails de liaison.

2

J'ai trouvé quelque chose qui fonctionne bien: vous pouvez spécifier links dans votre Cargo.toml:

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

Ceci indique que les liens du projet à libsoundio. Maintenant, vous pouvez spécifier le chemin de recherche et nom de la bibliothèque dans le fichier .cargo/config: (. Le préfixe : dit GCC d'utiliser le nom réel du fichier et de ne pas faire tout son idiot lib -prepending et magie l'extension)

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

Vous devez également créer un vide build.rs:

fn main() {} 

Ce fichier est exécuté jamais, parce que les valeurs .cargo/config priorité sur sa sortie, mais pour une reaso n Cargo l'exige toujours - chaque fois que vous utilisez links = vous devez avoir build =, même s'il n'est pas utilisé.

Enfin, dans main.rs:

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

Merci! Comment puis-je obtenir le nom de ma cible (j'utilise Mac et Linux). Devrais-je valider '.cargo/config' dans le contrôle de version ou devrait-il être différent pour chaque développeur? – Envek

+0

La cible est définie par rustup. Lancez 'rustup show'. (Ou vous pouvez remplacer la valeur par défaut avec quelque chose comme 'cargo - target blah'.)' .cargo/config' devrait être dans le contrôle de version. Cependant, la plupart des gens semblent utiliser un 'build.rs 'non vide pour faire cela, plutôt que' .cargo/config'. – Timmmm