2019.2.2 改标题
文档列表见:Rust 移动端跨平台复杂图形渲染项目开发系列总结(目录)
主体项目编译前的操作(build.rs)
build.rs可实现本项目编译前的额外操作,比如代码生成、调用cmake/clang/gcc/ndk-build等编译所依赖的C/C++库、读取C/C++头文件生成FFI文件给Rust项目使用等等,相当于Rust写的shell脚本。 为了让编译过程更可控,通常输出日志表示通过了某一阶段,或遇到什么错误,Cargo支持build.rs编译时输出不同类型的语句,比如warning、error等,比如:
println!("cargo:warning=Error failed with {:?}.", some_reason);
复制代码
目前没找到输出info级别日志的办法,经实践println!("cargo:info={:?}, some_status);
无法在控制台输出信息。
build.rs拉取git submodule
以下代码摘自glsl-to-spirv。
use std::process::Command;
// Try to initialize submodules. Don't care if it fails, since this code also runs for
// the crates.io package.
let _ = Command::new("git")
.arg("submodule")
.arg("update")
.arg("--init")
.status();
复制代码
Cargo调用clang编译所依赖的第三方C/C++库
目前我看到比较完整的参考是官方的libstd/build.rs,编译我们业务所需的第三方库的命令几乎都可以从那找到“灵感”,下面贴出核心代码段镇宅,关键操作是build_libbacktrace()
,通过cc::Build
实例把需要编译的C/C++代码声明起来,理论上支持正则匹配文件名与路径 。
#![deny(warnings)]
extern crate build_helper;
extern crate cc;
use build_helper::native_lib_boilerplate;
use std::env;
use std::fs::File;
fn main() {
let target = env::var("TARGET").expect("TARGET was not set");
if cfg!(feature = "backtrace") &&
!target.contains("cloudabi")
// ... 更多条件
{
let _ = build_libbacktrace(&target);
}
if target.contains("linux") {
// ... 一系列操作系统判断及println!
}
}
fn build_libbacktrace(target: &str) -> Result<(), ()> {
let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", "")?;
let mut build = cc::Build::new();
build
.flag("-fvisibility=hidden")
.include("../libbacktrace")
.include(&native.out_dir)
.out_dir(&native.out_dir)
.warnings(false)
.file("../libbacktrace/alloc.c")
.file("../libbacktrace/backtrace.c")
// ...一堆.c文件
let any_debug = env::var("RUSTC_DEBUGINFO").unwrap_or_default() == "true" ||
env::var("RUSTC_DEBUGINFO_LINES").unwrap_or_default() == "true";
build.debug(any_debug);
if target.contains("darwin") {
build.file("../libbacktrace/macho.c");
} else if target.contains("windows") {
build.file("../libbacktrace/pecoff.c");
} else {
build.file("../libbacktrace/elf.c");
let pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
if pointer_width == "64" {
build.define("BACKTRACE_ELF_SIZE", "64");
} else {
build.define("BACKTRACE_ELF_SIZE", "32");
}
}
File::create(native.out_dir.join("backtrace-supported.h")).unwrap();
build.define("BACKTRACE_SUPPORTED", "1");
build.define("BACKTRACE_USES_MALLOC", "1");
build.define("BACKTRACE_SUPPORTS_THREADS", "0");
build.define("BACKTRACE_SUPPORTS_DATA", "0");
File::create(native.out_dir.join("config.h")).unwrap();
if !target.contains("apple-ios") &&
!target.contains("solaris") &&
!target.contains("redox") &&
!target.contains("android") &&
!target.