J'essaie de lier un programme Rust avec libsoundio . J'utilise Windows et un téléchargement binaire GCC est disponible. Je peux le lier comme ceci si je le mets dans le même dossier que mon projet:
#[link(name = ":libsoundio-1.1.0/i686/libsoundio.a")]
#[link(name = "ole32")]
extern {
fn soundio_version_string() -> *const c_char;
}
Mais je veux vraiment spécifier #[link(name = "libsoundio")]
ou même #[link(name = "soundio")]
, puis fournir un chemin de l'éditeur de liens 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 en .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 ne transmet toujours 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.
Comme indiqué dans la documentation d'un script de compilation :
Toutes les lignes imprimées sur stdout par un script de construction [... commençant] par
cargo:
sont interprétées directement par Cargo [...]rustc-link-search
indique que la valeur spécifiée doit être transmise au compilateur sous la forme d'un indicateur-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 génération peut utiliser toute la puissance de Rust et générer différentes valeurs en fonction de la plate-forme cible (32 et 64 bits, par exemple).
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 créerez un package soundio-sys
en utilisant la convention des packages *-sys
. Cela a simplement un script de construction qui lie aux bibliothèques appropriées et expose les méthodes C. Il utilisera la clé Cargo links
pour identifier de manière unique la bibliothèque native et empêcher la création de liens à plusieurs reprises. Les autres bibliothèques peuvent alors inclure cette nouvelle caisse sans se soucier des détails des liens.
J'ai trouvé quelque chose qui fonctionne bien: vous pouvez spécifier links
dans votre Cargo.toml
:
[package]
links = "libsoundio"
build = "build.rs"
Ceci spécifie que le projet est lié à libsoundio
. Vous pouvez maintenant spécifier le chemin de recherche et le nom de la bibliothèque dans le fichier .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"]
(Le préfixe :
indique à GCC d'utiliser le nom de fichier lui-même et de ne pas utiliser toute sa magie idiote lib
- prépending et extension.)
Vous devez également créer un build.rs
vide:
fn main() {}
Ce fichier n'est jamais exécuté, car les valeurs dans .cargo/config
remplacent sa sortie, mais pour une raison quelconque, Cargo en a toujours besoin - 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;
}
Une autre façon possible est de régler la RUSTFLAGS
like:
RUSTFLAGS='-L my/lib/location' cargo build # or cargo run
Je ne sais pas s'il s'agit de l'approche la plus organisée et la plus recommandée, mais cela a fonctionné pour mon projet simple.
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 supprimer le préfixe lib
et l’extension .a
de votre bibliothèque statique: -lsoundio