添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
朝气蓬勃的茶叶  ·  Central Repository: ...·  5 月前    · 
温暖的凉面  ·  一次get web ...·  6 月前    · 
俊秀的遥控器  ·  Exception has been ...·  9 月前    · 

构建时工具

本节介绍在编译箱子源代码之前,运行的“构建时”工具或代码。通常,构建时代码,位于 build.rs 文件,通常称为“构建脚本”。常见的用例,包括:Rust 代码生成,和捆绑的 C/C++/ASM 代码的编译。查看 crates.io 的 主分支文档 ,了解更多信息。

编译,并静态链接到捆绑的 C 库

为了适应项目,需要附加 C、C++ 或 ASM 的场景, cc 箱子,提供了一个简单的 API,用于将捆绑的 C/C++/ASM 代码编译成静态库( .a ),这样就可以静态链接到 rustc .

下面的示例,包含一些绑定的 C 代码( src/hello.c ),会用在 Rust 上。在编译 rust 源代码之前,“构建”文件( build.rs )可通过 Cargo.toml 指定运行。若使用 cc 箱子,一个静态库文件将被生成(在这情况下,就是 libhello.a ,若想知道更多,请看 compile 文档 )然后,在 Rust 中想使用该库,可以通过在 extern 块中,定义外部函数签名。

由于绑定的 C 非常简单,因此只需要将一个源文件,传递给 cc::Build 。 对于更复杂的构建需求, cc::Build 为指定的 include 的路径,和额外的编译器 flag 标志们,提供了一整套构建器方法。

Cargo.toml

[package]
build = "build.rs"
[build-dependencies]
cc = "1"
[dependencies]
error-chain = "0.11"

build.rs

extern crate cc;
fn main() {
    cc::Build::new()
        .file("src/hello.c")
        .compile("hello");   // outputs `libhello.a`

src/hello.c

#include <stdio.h>
void hello() {
    printf("Hello from C!\n");
void greet(const char* name) {
    printf("Hello, %s!\n", name);

src/main.rs

# #[macro_use] extern crate error_chain;
use std::ffi::CString;
use std::os::raw::c_char;
# error_chain! {
#     foreign_links {
#         NulError(::std::ffi::NulError);
#         Io(::std::io::Error);
#     }
# fn prompt(s: &str) -> Result<String> {
#     use std::io::Write;
#     print!("{}", s);
#     std::io::stdout().flush()?;
#     let mut input = String::new();
#     std::io::stdin().read_line(&mut input)?;
#     Ok(input.trim().to_string())
extern {
    fn hello();
    fn greet(name: *const c_char);
fn run() -> Result<()> {
    unsafe { hello() }
    let name = prompt("What's your name? ")?;
    let c_name = CString::new(name)?;
    unsafe { greet(c_name.as_ptr()) }
    Ok(())
# quick_main!(run);

编译,并静态链接到捆绑的 C++库

链接捆绑的 C++库,非常类似于链接捆绑的 C 库。编译和静态链接捆绑的 C++库的两个核心区别,是通过构建器方法cpp(true)指定 C++编译器。通过在我们的 C++源文件的顶部,添加extern "C"部分,防止 C++编译器的名称篡改。

Cargo.toml

[package]
build = "build.rs"
[build-dependencies]
cc = "1"

build.rs

extern crate cc;
fn main() {
    cc::Build::new()
        .cpp(true)
        .file("src/foo.cpp")
        .compile("foo");

src/foo.cpp

extern "C" {
    int multiply(int x, int y);
int multiply(int x, int y) {
    return x*y;

src/main.rs

extern {
    fn multiply(x : i32, y : i32) -> i32;
fn main(){
    unsafe {
        println!("{}", multiply(5,7));

带自定义设置,编译 C 库

使用cc::Build::define自定义构建,捆绑的 C 代码很简单。 该方法采用Option值,因此可以创建如下定义:#define APP_NAME "foo",以及#define WELCOME(传递 None作为一个缺乏值的定义)。这个例子构建了一个动态定义集的捆绑 C 文件,而定义集在build.rs中,并会在运行使,打印欢迎使用 foo-版本 1.0.2“。Cargo 会设置一些环境变量,这对于某些自定义设置可能很有用。

Cargo.toml

[package]
version = "1.0.2"
build = "build.rs"
[build-dependencies]
cc = "1"

build.rs

extern crate cc;
fn main() {
    cc::Build::new()
        .define("APP_NAME", "\"foo\"")
        .define("VERSION", format!("\"{}\"", env!("CARGO_PKG_VERSION")).as_str())
        .define("WELCOME", None)
        .file("src/foo.c")
        .compile("foo");

src/foo.c

#include <stdio.h>
void print_app_info() {
#ifdef WELCOME
    printf("Welcome to ");
#endif
    printf("%s - version %s\n", APP_NAME, VERSION);

src/main.rs

extern {
    fn print_app_info();
fn main(){
    unsafe {
        print_app_info();