2016-11-27 10 views
3

Я пытаюсь связать программу Rust с libsoundio. Я использую Windows, и есть доступная бинарная загрузка GCC. Я могу связать это так, если я положил его в той же папке, как мой проект:Как указать путь компоновщика в Rust?

#[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" в НКУ и не с такой же ld: cannot find -llibsoundio. Я пропустил что-то действительно очевидное? Документы, похоже, предполагают, что это должно сработать.

ответ

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

+0

Может быть, я что-то кроме того, что не хватает, кажется, не работает. См. Мое редактирование вопроса. – Timmmm

+0

Попробуйте удалить префикс "lib": '-l soundio' – Lud

+0

Без эффекта, это похоже даже не на' .cargo/config'. Я подозреваю, что это как-то связано с '.libsoundio]' бит, но, похоже, нет способа заставить Cargo распечатать конфигурацию сборки, поэтому ее трудно отладить! – Timmmm

6

Как указано в documentation for a build script:

Все линии печати d to stdout скриптом сборки [... start] с cargo: интерпретируется непосредственно 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"); 
} 

Обратите внимание, что ваш сценарий сборки может использовать всю мощь ржавчины и может выводят разные значения в зависимости от целевой платформы (например, 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 пакет, используя the convention for *-sys packages. Это просто имеет скрипт сборки, который ссылается на соответствующие библиотеки и предоставляет методы C. Он будет использовать Cargo links key для уникальной идентификации собственной библиотеки и предотвращения связывания с ней несколько раз. Другие библиотеки могут затем включить этот новый ящик и не беспокоиться об этих деталях ссылок.

2

я нашел то, что работает нормально: вы можете указать links в вашем Cargo.toml:

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

Это указывает, что проект ссылки на libsoundio. Теперь вы можете указать путь поиска и имя библиотеки в .cargo/config файла: (. Приставка : говорит GCC использовать фактическое имя файла, а не делать всю свою идиотскую lib -prepending и расширение магии)

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

Кроме того, необходимо создать пустой build.rs:

fn main() {} 

Этот файл никогда не работать, потому что значения в .cargo/config переопределить его выход, но в течение некоторого reaso n Cargo все еще требует этого - в любое время, когда вы используете links =, вы должны иметь build =, даже если он не используется.

Наконец в main.rs:

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

Спасибо! Как я могу получить имя для своей цели (я использую Mac и Linux). Должен ли я переносить '.cargo/config' в управление версиями или он должен отличаться для каждого разработчика? – Envek

+0

Цель установлена ​​rustup. Запустите 'rustup show'. (Или вы можете переопределить значение по умолчанию с чем-то вроде «load -target blah».) '.cargo/config' должен находиться в управлении версиями. Однако большинство людей, похоже, используют непустые 'build.rs' для этого, а не' .cargo/config'. – Timmmm

 Смежные вопросы

  • Нет связанных вопросов^_^