使用 Nix Flake 搭建基础的 Rust 跨平台构建环境
-
新增 flake.nix 文件,并执行
git add flake.nix
。{ inputs = { utils.url = "github:numtide/flake-utils"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; }; outputs = { nixpkgs, utils, ... }: utils.lib.eachDefaultSystem ( system: let pkgs = import nixpkgs {inherit system;}; lib = pkgs.lib; in { devShells = { default = pkgs.mkShell { nativeBuildInputs = with pkgs; [ pkg-config gcc ]; }; } // builtins.listToAttrs (map (target: { name = target; value = let cross = import nixpkgs { inherit system; crossSystem = {config = target;}; }; cpkgs = cross.pkgsMusl; in (cross.mkShell { nativeBuildInputs = with pkgs; [ pkg-config gcc # proc macro 等编译过程,需要原架构 toolchians ]; env = let normalized = lib.strings.toUpper (builtins.replaceStrings ["-"] ["_"] target); in with cpkgs; { # https://doc.rust-lang.org/cargo/reference/environment-variables.html#configuration-environment-variables "CARGO_TARGET_${normalized}_LINKER" = "${stdenv.cc.targetPrefix}cc"; }; }); }) ["x86_64-unknown-linux-musl" "aarch64-unknown-linux-musl"]); } ); }
-
执行构建
# 本地构建 nix develop .#default --command \ cargo build # 跨平台构建 # # 别忘了先安装对应的 rustup 组件 # rustup target add aarch64-unknown-linux-musl # rustup target add x86_64-unknown-linux-musl TARGET=x86_64-unknown-linux-musl nix develop .#$TARGET --command \ cargo build --target $TARGET
openssl, pq 等 C/C++ 依赖处理
使用静态编译,并使用有 vendor (打包 C/C++ 源码 )版本的 bindings 项目,把这些加入依赖管理,确保能稳定的可重复构建。
-
在 Cargo.toml 文件中增加对应 target 的依赖。
[target.x86_64-unknown-linux-musl.dependencies] openssl-sys = { version = "0.9", features = ["vendored"] } pq-sys = { version = "0.7", features = ["bundled"] } [target.aarch64-unknown-linux-musl.dependencies] openssl-sys = { version = "0.9", features = ["vendored"] } pq-sys = { version = "0.7", features = ["bundled"] }
-
执行构建
# 本地静态编译则需要指定 RUSTFLAGS。经实测,有些架构该配置无效 RUSTFLAGS='-C target-feature=+crt-static' cargo build # 而 x86_64-unknown-linux-musl 则不需要指定,默认启用 TARGET=x86_64-unknown-linux-musl nix develop .#$TARGET --command \ cargo build --target $TARGET
CRT means standard C runtime. The default of crt-static will be different depending on the target. For example x86_64-unknown-linux-musl will have it on by default, whereas arm-unknown-linux-musleabi will have it turned off by default. 1