腐蚀(Corrosion)的作用是什么?

腐蚀(Corrosion)的具体作用应该被视为实现细节,在编写用户代码时不应依赖它。然而,基本了解腐蚀的作用可能有助于在调查问题时提供帮助。

FindRust

腐蚀(Corrosion)维护了一个 CMake 模块 FindRust,当腐蚀(Corrosion)被加载时执行,即在 find_package(corrosion)FetchContent_MakeAvailable(corrosion)add_subdirectory(corrosion) 的时候,具体取决于用于包含腐蚀(Corrosion)的方法。

FindRust 将搜索已安装的 Rust 工具链,尊重在 使用 章节中以 Rust_ 为前缀的选项。它将选择一个 Rust 工具链用于编译 Rust 代码。由 rustup 管理的工具链将被解析,腐蚀(Corrosion)总是选择一个特定的工具链,而不是 rustup 代理。

导入 Rust crates

腐蚀(Corrosion)的主要功能是 corrosion_import_crate,它在内部将调用 cargo metadata 以提供基于 Cargo.toml 清单的结构化信息。然后腐蚀(Corrosion)将遍历所有工作区和/或包成员,并找到所有 Rust crates,这些 crates 要么是静态库(staticlib),要么是共享库(cdylib),要么是 bin 目标,并创建与 crate 名称匹配的 CMake 目标。此外,为每个导入的目标创建一个构建目标,包含创建导入工件所需的构建命令。这个构建命令可以通过 corrosion_import_crate 的各种参数以及腐蚀(Corrosion)特定的目标属性来影响,这些属性在 使用 章节中有文档记录。腐蚀(Corrosion)添加了必要的依赖项,并在设置 OUTPUT_DIRECTORY 目标属性时,甚至将目标工件从 cargo 构建树复制到标准 CMake 位置。

链接

根据 crate 的类型,链接器将由 CMake 或 rustc 调用。Rust staticlib 通过 target_link_libraries() 链接到 C/C++ 代码中,链接器由 CMake 调用。对于 Rust cdylibbin,链接器通过 rustc 调用,CMake 只获取最终工件。

CMake 调用链接器

当 CMake 调用链接器时,一切如常。CMake 将使用编译器作为链接器驱动程序调用链接器,用户可以使用常规的 CMake 函数来修改链接行为。corrosion_set_linker() 没有 效果。作为方便,corrosion_link_libraries() 将其参数转发给 target_link_libraries()

Rustc 调用链接器

Rust cdylibbin 通过 rustc 链接。腐蚀(Corrosion)提供了几个辅助函数来影响这些目标的链接器调用。

corrosion_link_libraries()target_link_libraries() 的有限版本,用于 Rust cdylibbin 目标。在底层,这个函数将 -l-L 标志传递给链接器调用,并确保链接的库首先被构建。target_link_libraries() 中可用的许多高级功能尚未实现,但欢迎 pull-requests!与此同时,用户可能想使用 corrosion_add_target_local_rustflags() 来传递自定义的链接标志。

corrosion_set_linker() 可以用来指定自定义链接器,以防腐蚀(Corrosion)选择的默认链接器不是你想要的。腐蚀(Corrosion)目前指示 rustc 使用 C/C++ 编译器作为链接器驱动程序。这是由于:

  • 对于 C++ 代码,我们必须与 libstdc++libc++(取决于编译器)链接,因此我们必须在链接行上指定库,或使用 c++ 编译器作为链接器驱动程序。
  • Rustc 的默认链接器选择目前并不理想。对于许多平台,rustc 将回退到 cc 作为链接器驱动程序。在交叉编译时,这会导致链接失败,因为链接器驱动程序是针对主机架构的。腐蚀(Corrosion)通过指定 C/C++ 编译器作为链接器驱动程序来避免这个问题。

在某些情况下,特别是在旧版本的 Rust(1.68 之前),rustc 的链接器风味检测也不准确,因此当设置自定义链接器时,你可能想通过 corrosion_add_target_local_rustflags() 传递 -C linker-flavor rustflag。

FFI 绑定

为了 Rust 和其他语言之间的交互,需要一些 FFI 绑定。对于简单的情况,手动定义接口可能足够,但在许多情况下,用户希望使用像 bindgencbindgencxxautocxx 这样的工具来自动化生成绑定。

原则上,有两种不同的方法来生成绑定:

  • 使用 build.rs 脚本在调用 cargo 时生成绑定,使用库版本的工具来生成绑定。
  • 使用工具的 cli 版本,并设置自定义 CMake 目标/命令来生成绑定。如果 C/C++ 端需要绑定,应优先选择这种方法。

腐蚀(Corrosion)目前提供了 2 个实验性函数,将 cbindgen 和 cxx 集成到构建过程中。它们还没有完全准备好生产,但应该可以很好地作为如何将生成绑定集成到你的构建过程中的模板。

待办事项:扩展此文档并链接到其他资源。