#环境变量 #变量 #环境 #env

构建 const_env_impl

通过环境变量配置常量和静态项

4 个版本

0.1.3 2021年11月25日
0.1.2 2019年10月30日
0.1.1 2019年10月30日
0.1.0 2019年10月30日

#705 in 构建实用工具

Download history 1471/week @ 2024-03-14 1330/week @ 2024-03-21 1222/week @ 2024-03-28 1645/week @ 2024-04-04 1853/week @ 2024-04-11 1263/week @ 2024-04-18 1660/week @ 2024-04-25 1434/week @ 2024-05-02 1501/week @ 2024-05-09 1271/week @ 2024-05-16 735/week @ 2024-05-23 946/week @ 2024-05-30 694/week @ 2024-06-06 810/week @ 2024-06-13 1254/week @ 2024-06-20 917/week @ 2024-06-27

3,853 每月下载量
50 个 crate 中使用 (通过 const_env)

CC0 许可

13KB
137

const_env

动机

你的目标:你希望在编译时根据环境变量定义代码中的各种常量。

你的问题:在今天的 Rust 中,仅可以对 &'static str 常量进行此类操作。

const MY_STR: &'static str = env!("SOME_ENV");

你不能以类似的方式初始化其他类型,例如常量 u32bool 或其他原始类型。参见 问题解决方案。最终,一旦支持在 const fn 中运行 parseunwrap,你将能够这样做,但到目前为止,这个 crate 提供了一个易于使用的解决方案,你可以现在就使用它。

crate 功能

功能名称 默认启用? 需要 nightly? 描述
tracked No yes 使用不稳定的功能 proc_macro_tracked_env 来通知构建系统使用的环境变量。

用法

添加依赖项。如果你的 crate 使用 nightly,为更好的构建依赖项跟踪启用 tracked 功能。

# If using a stable compiler:
[dependencies]
const_env = "0.1"

# If using a nightly compiler:
[dependencies]
const_env = { version = "0.1", features = ["tracked"] }

在文件顶部导入 from_env! 宏。

use const_env::from_env;

使用宏在构建时根据环境变量覆盖常量的值。

#[from_env]
const FOO: u32 = 123;

// This test will PASS if invoked as `FOO=456 cargo test`
#[test]
fn test() {
    assert_eq!(456, FOO);
}

默认情况下,该宏根据附加到常量的名称查找具有相同名称的环境变量。

// Use `FOO=true cargo build` to configure the value.
#[from_env]
const FOO: bool = false;

但您也可以明确指定名称。

// Use `BAR=true cargo build` to configure the value.
#[from_env("BAR")]
const FOO: bool = false;

您在源文件中分配的表达式在环境变量不存在时作为默认值。

// If env var FOO is not set then the FOO constant will have the default value of '🦀'.
#[from_env]
const FOO: char = '🦀';

支持 conststatic 声明。

// Both of these may be set by `FOO=abc BAZ=def cargo build`.
#[from_env]
const FOO: &'static str = "hello";
#[from_env("BAZ")]
static BAR: &'static [u8] = b"world";

支持类型

字符串!

#[from_env]
const FOO: &'static str = "hello";

// example: `FOO=abc cargo build`
// results in:
const FOO: &'static str = "abc";

字节字符串!

#[from_env]
const FOO: &'static [u8] = b"hello";

// example: `FOO=world cargo build`
// results in:
const FOO: &'static [u8] = b"world";

字节!

#[from_env]
const FOO: u8 = b'';

// example: `FOO=🦀 cargo build`
// results in:
const FOO: u8 = b'🦀';

字符!

#[from_env]
const FOO: char = '';

// example: `FOO=🦀 cargo build`
// results in:
const FOO: car = '🦀';

各种形状和大小的整数!

#[from_env]
const FOO: u32 = 123;
#[from_env]
const BAR: i64 = 456;
#[from_env]
const BAZ: usize = 0;

// example: `FOO=321 BAR=-456 BAZ=1usize cargo build`
// results in:
const FOO: u32 = 321;
const BAR: i64 = -456;
const BAZ: usize = 1usize;

各种形状和大小的浮点数!

#[from_env]
const FOO: f32 = 123.0;
#[from_env]
const BAR: f64 = 456.0;
#[from_env]
const BAZ: f32 = 0.0;

// example: `FOO=321.0 BAR=-456.0 BAZ=1f32 cargo build`
// results in:
const FOO: f32 = 321.0;
const BAR: f64 = -456.0;
const BAZ: f32 = 1f32;

布尔值!

#[from_env]
const FOO: bool = false;

// example: `FOO=true cargo build`
// results in:
const FOO: bool = true;

已知限制

  • 仅支持顶层 conststatic 声明。

替代方案

  • 编写一个 build.rs 脚本,该脚本检查环境变量并基于它们生成代码。这在概念上与这个crate的工作方式类似,不同之处在于这个crate使用过程宏而不是构建脚本。
  • 等待 const fn 完成。最终这个crate执行相当于 static FOO: u32 = std::option_env!("FOO").map(|val| val.parse::<u32>().unwrap_or(0)).unwrap_or(0); 的操作,所以一旦你可以简单地写出这段代码,这个crate就会变得多余。

依赖关系

~1.5MB
~35K SLoC