010 Rust 網路程式設計,cargo 構建指令碼介紹

linghuyichong發表於2020-05-10

說明

此章節並不是只有Rust網路程式設計的內容,但是由於後續的例子有些依賴於此知識點,所以放在Rust網路程式設計系列中做簡單介紹。參考資料主要是官方文件《Cargo之書》。

介紹

在實際的專案中,有些包需要編譯第三方非Rust程式碼,例如 C庫;有些包需要連結到 C庫,當然這些庫既可以位於系統上,
也可以從原始碼構建。其它的需求則有可能是需要構建程式碼生成 。
在Cargo中,提供了構建指令碼,來滿足這些需求。

指定的build命令應執行的Rust檔案,將在包編譯其它內容之前,被編譯和呼叫,從而具備Rust程式碼所依賴的構建或生成的元件。Build通常被用來:

  • 構建一個捆綁的C庫;
  • 在主機系統上找到C庫;
  • 生成Rust模組;
  • 為crate執行所需的某平臺特定配置。

示例一

功能:生成程式碼(Rust模組)。

  • 修改Cargo.toml:

    [package]
    ...
    build = "build.rs
  • 在src同級目錄下新增build.rs:

    .
    ├── Cargo.toml
    ├── build.rs
    └── src
      └── main.rs
  • 編寫build.rs檔案,如下:

    use std::env;
    use std::fs::File;
    use std::io::Write;
    use std::path::Path;
    fn main() {
      let out_dir = env::var("OUT_DIR").unwrap();
      let dest_path = Path::new(&out_dir).join("hello.rs");
      let mut f = File::create(&dest_path).unwrap();
    
      f.write_all(b"
          pub fn message() -> &'static str {
              \"Hello, World!\"
          }
      ").unwrap();
    }
  • 編寫src/main.rs:

    include!(concat!(env!("OUT_DIR"), "/hello.rs"));
    fn main() {
      println!("{}", message());
    }
  • 編譯執行結果:

    Hello, world!

    示例二

    功能:編譯c程式碼,然後由Rust呼叫。

  • 修改Cargo.toml,新增如下:

    [package]
    # ---snip---
    build = "build.rs
    # ---snip---
    [build-dependencies]
    cc = "1.0
  • 新增build.rs,編寫如下:

    extern crate cc;
    fn main() {
      cc::Build::new()
          .file("src/hello.c")
          .compile("hello");
    }
  • 在src目錄下新增hello.c,編寫如下:

    #include <stdio.h>
    void hello() {
      printf("Hello, World!\n");
    }
  • 編寫src/main.rs如下:

    extern { fn hello(); }
    fn main() {
      unsafe { hello(); }
    }
  • 編譯執行:
    列印:

    Hello, World!
本作品採用《CC 協議》,轉載必須註明作者和本文連結
令狐一衝

相關文章