#cargo-build #build-script #simd #build-dependencies #bindings #bindings-generator #compile-time

build ispc

是Cargo构建脚本的构建时依赖项,用于编译和链接ISPC代码,并生成结果库的Rust绑定。这个crate是ispc_compile和ispc_rt crate的元crate,它们提供了构建ISPC代码和生成绑定的实际功能,并将这些绑定导入Rust中。

32个版本 (18个稳定版)

2.0.1 2023年12月16日
2.0.0 2022年11月7日
1.1.0 2022年6月29日
1.0.13 2022年3月12日
0.3.0 2016年7月15日

#115 in 构建实用工具

每月26次下载

MIT 许可证

105KB
1.5K SLoC

ispc-rs

Actions Status Latest version Documentation MIT

一个小型库,旨在作为Cargo的构建依赖项使用,以便轻松地将ISPC代码集成到Rust项目中。ispc-rs分为两个crate:编译时crate ispc_compile和运行时crate ispc_rt。这种分离允许库作者避免将不必要的依赖项推送到不计划修改ISPC代码的库的最终用户。如果不需要这种分离,还提供了一个ispc-rs crate,它将编译时和运行时crate捆绑成一个方便的单个crate。

文档

Rust文档可在此处找到,ISPC文档可在此处找到。

使用ispc-rs

使用ispc-rs,您可以从构建脚本编译您的ISPC代码以生成一个本地库和一个包含对导出ISPC函数的绑定的Rust模块。ispc-rs将输出命令到Cargo以链接本地库,您可以使用提供的宏将Rust绑定导入到代码中,以调用库。以这种方式使用ispc-rs需要在编译crate时提供ISPC编译器和clang。

当编写需要打包和使用ISPC代码的crate或程序,但并不一定要求这些依赖在最终用户系统上时,ispc-rs实际上分为两个crate:编译时crate(ispc_compile)和运行时crate(ispc_rt)。ispc_compile crate用于在构建脚本中编译ISPC代码,生成本地库和Rust绑定。ispc_rt crate包含轻量级代码,可以包含在构建脚本中,用于查找并链接先前编译的本地库,以及一个宏来导入先前生成的Rust绑定。建议的使用案例是将ispc_compile作为带有功能门控的可选依赖项。当使用此功能门控构建时,将构建ISPC代码,否则运行时crate将查找并使用现有的库。

报告ispc-rs的问题

请将任何问题或功能请求报告到GitHub问题跟踪器

编译ISPC代码的要求

ISPC编译器和libclang(用于rust-bindgen)必须在您的路径中可用,才能编译ISPC代码并生成绑定。如果您使用ispc_rt来链接到先前编译的库,则不需要这些。

Windows用户

您需要Visual Studio,并且必须使用Rust的MSVC ABI版本,因为在Windows上ISPC和Clang与MSVC链接。为了使bindgen能够找到libclang,您需要将libclang.lib复制到clang.lib,并将其放置在您的路径中。您还需要设置环境变量LIBCLANG_PATH=<LLVM路径\bin>,以便bindgen能够成功找到clang。

将ispc-rs作为单个crate使用

要使用ispc-rs作为单个crate,您需要在crate中添加一个构建脚本(build.rs),告诉Cargo关于它,并将ispc-rs作为构建时和编译时依赖项添加。

# Cargo.toml
[package]
# ...
build = "build.rs"

[dependencies]
ispc = "2.0"

[build-dependencies]
ispc = "2.0"

现在您可以使用ispc将您的代码编译成静态库

extern crate ispc;

fn main() {
    // Compile our ISPC library, this call will exit with EXIT_FAILURE if
    // compilation fails.
    ispc::compile_library("simple", &["src/simple.ispc"]);
}

运行cargo build现在应将您的ISPC文件编译成库,并将您的Rust应用程序与之链接。为了提供额外的便利,提供了ispc_module宏,用于将使用rust-bindgen生成的库绑定导入到具有相同名称的模块中。请注意,导入的所有函数都将是不安全的,因为它们是到您库的原始C绑定。

#[macro_use]
extern crate ispc;

// Functions exported from simple will be callable under simple::*
ispc_module!(simple);

使用独立的编译和运行时crate

使用独立crate的过程与单个crate的过程类似;然而,您将使用单独的ispc_compileispc_rt crate,其中前者标记为可选依赖项。这将允许最终用户使用crate并利用其ISPC代码,而无需在他们的机器上重新构建代码。因此,还建议为多个向量ISA构建您的ISPC代码,以便跨CPU架构提供可移植性。您还需要为每个宿主目标三元组打包编译的ISPC库。这可以通过在支持您库的用户的目标主机系统上启用ispc功能来构建crate来完成。请注意,在您未提供二进制的系统上使用您的crate的用户仍然可以通过使用带有ispc功能的crate来自行编译ISPC代码。

# Cargo.toml
[package]
# ...
build = "build.rs"

[dependencies]
ispc_rt = "2.0"

[build-dependencies]
ispc_rt = "2.0"
ispc_compile = { "2.0", optional = true }

[features]
ispc = ["ispc_compile"]

在构建脚本中,我们现在可以使用ispc特性,可选地使用ispc_compile编译ispc代码,否则我们将使用ispc_rt链接先前构建的代码。在这里,我们还将输出编译后的ISPC库和绑定到src/目录中。

extern crate ispc_rt;
#[cfg(feature = "ispc")]
extern crate ispc_compile;

#[cfg(feature = "ispc")]
fn link_ispc() {
    use ispc_compile::TargetISA;
    ispc_compile::Config::new()
        .file("src/simple.ispc")
        .target_isas(vec![
            TargetISA::SSE2i32x4,
            TargetISA::SSE4i32x4,
            TargetISA::AVX1i32x8,
            TargetISA::AVX2i32x8,
            TargetISA::AVX512KNLi32x16,
            TargetISA::AVX512SKXi32x16])
        .out_dir("src/")
        .compile("simple");
}

#[cfg(not(feature = "ispc"))]
fn link_ispc() {
    ispc_rt::PackagedModule::new("simple")
        .lib_path("src/")
        .link();
}

fn main() {
    link_ispc();
}

运行cargo build --features ispc现在将构建您的ISPC文件到库中,并为您导出的ISPC函数生成绑定。编译后的库和生成的绑定文件将保存在src/目录下,以便与crate的其他部分一起打包。当使用cargo build构建时,将链接之前为宿主系统编译的库。

无论是否使用ispc特性构建,您都可以像以前一样使用ispc_module!宏将生成的绑定导入到您的Rust代码中

#[macro_use]
extern crate ispc;

// Functions exported from simple will be callable under simple::*
ispc_module!(simple);

更多完整的示例可以在examples/文件夹中找到。单独的crate示例在这里

依赖关系

~6–8MB
~150K SLoC