解决Rust build.rs中NPM资源超出OUT_DIR无法发布至crates.io的问题
解决cargo publish时build.rs修改源目录的问题
核心问题是npm install默认在源目录生成node_modules,而cargo publish会严格校验build脚本是否修改了OUT_DIR之外的内容,因此需要将所有npm相关操作转移到OUT_DIR内执行。
解决方案:将UI构建流程完全移至OUT_DIR
步骤1:在build.rs中复制UI源码到OUT_DIR
首先把你的UI项目(比如martin-ui)的所有必要文件复制到OUT_DIR下的子目录,确保npm命令能在这个隔离的目录里执行,不会污染源目录。
步骤2:在OUT_DIR内执行npm install和打包
指定npm命令的工作目录为OUT_DIR下的UI子目录,这样node_modules和dist都会生成在OUT_DIR内,完全符合cargo的要求。
示例代码(build.rs)
use fs_extra::dir::CopyOptions; use fs_extra::dir::copy; use std::env; use std::path::Path; use std::process::Command; fn main() { // 获取cargo提供的OUT_DIR路径 let out_dir = env::var("OUT_DIR").expect("Failed to get OUT_DIR"); let ui_source = Path::new("./martin-ui"); let ui_target = Path::new(&out_dir).join("ui"); // 跨平台复制UI源码到OUT_DIR/ui let copy_opts = CopyOptions::new(); copy(ui_source, ui_target.parent().unwrap(), ©_opts) .expect("Failed to copy UI source to OUT_DIR"); // 在OUT_DIR/ui下执行npm install Command::new("npm") .arg("install") .current_dir(&ui_target) .status() .expect("npm install failed"); // 执行UI打包命令(比如npm run build) Command::new("npm") .arg("run") .arg("build") .current_dir(&ui_target) .status() .expect("npm run build failed"); // 用static-files将打包后的资源转为Rust代码 static_files::Builder::new(ui_target.join("dist")) .target(out_dir) .build() .expect("Failed to build static files"); }
依赖说明
需要在Cargo.toml的build-dependencies中添加fs_extra,用于跨平台复制目录:
[build-dependencies] static-files = "..." fs_extra = "1.3.0"
备选方案:预构建静态资源(适合手动场景)
如果不需要在build阶段自动构建UI,可以提前在本地执行npm install和npm run build,将生成的dist目录加入项目源码,并在Cargo.toml中确保该目录被包含:
include = ["src/**/*", "martin-ui/dist/**/*"]
之后build.rs只需直接处理已存在的dist目录,无需执行任何npm命令。
内容的提问来源于stack exchange,提问作者Yuri Astrakhan
相关产品推荐
相关产品推荐

