为什么过程宏在我的构建脚本中看不到 dotenv 设置的环境变量?

Why does a procedural macro not see environment variables set by dotenv in my build script?

我有一个程序宏包 Proc 和二进制包 BinBin 依赖于 ProcProc 需要填充的环境变量才能正常运行。

这是我在 Bin 中的 build.rs 中的一些代码。 Proc使用以下代码可以成功找到env值:

fn main() {
    println!("cargo:rustc-env=SOME_ENV_VALUE=somevalue");
}

然而,ProcBin 中的 build.rs 中使用此代码时无法找到环境变量(注意:在 dotenv 之后检查是否存在时打电话,我可以验证密钥是否确实存在):

fn main() {
    dotenv::dotenv().unwrap();
}

这是我的 Proc 箱子:

use proc_macro::TokenStream;

#[proc_macro_derive(MyProcMacro)]
pub fn my_proc_macro(input: TokenStream) -> TokenStream {
    if std::env::var("SOME_ENV_VALUE").is_err() {
        panic!("Failed to retrieve env value")
    }

    TokenStream::new()
}

为什么 println! 命令不会失败?它可以与 dotenv 一起使用吗?否则我需要编写一些代码,将密钥从我的 env 文件复制到 println! 命令...

所有代码都在我的minimal reproduction project.

我鼓励您重新阅读 Build Scripts chapter of the Cargo docs。构建脚本是一个 单独的可执行文件,Cargo 在开始构建源代码之前构建并执行。

  1. 货运开始
  2. Cargo 执行rustc 构建构建脚本
  3. Cargo 执行构建脚本
  4. Cargo 执行 rustc 来构建您的代码
  5. 货物出口

[dotenv] loads environment variables from a .env file, if available, and mashes those with the actual environment variables provided by the operating system.

它加载的变量被放入当前进程环境变量中。在您的示例中,这是构建脚本可执行文件。

[cargo:rustc-env] tells Cargo to set the given environment variable when compiling the package

构建脚本的标准输出与 Cargo 交互,然后修改代码的编译方式,包括要设置的环境变量。


您需要加载dotenv文件设置环境变量以便后续编译。像这个编译但未经测试的例子:

fn main() {
    if let Ok(env) = dotenv::dotenv_iter() {
        for (k,v) in env.flatten() {
            println!("cargo:rustc-env={}={}", k, v);
        }
    }
}

不用担心此方法已被标记为已弃用。维护者 changed their minds.