gpt4 book ai didi

rust - 如何将编译期间命令行上提供的字符串编译成我的 Rust 二进制文件?

转载 作者:行者123 更新时间:2023-11-29 08:02:54 34 4
gpt4 key购买 nike

我想让它在我的程序启动时打印到标准错误:

This is Program X v. 0.1.0 compiled on 20180110. Now listening on stdin,
quit with SIGINT (^C). EOF is ignored. For licensing information, read
LICENSE. To suppress this message, supply --quiet or --suppress-greeting

在 C/C++ 中,我将使用 Makefile 实现此目的,例如:

VERSION = 0.1.0
FLAGS = -Wall -pipe -O3 -funroll-loops -Wall -DVERSION="\"$(VERSION)\"" -DCOMPILED_AT="\"`date +%Y%m%d`\""

然后,在源代码中,我会随意使用这些常量,也许是在对 fprintf 的调用中。当然,在使用 #ifdef 检查它们是否确实存在之后。

这在 Rust 中如何实现?我需要使用程序宏吗?我能以某种方式使用 cargo 吗?

我知道 env!("CARGO_PKG_VERSION") 可以用作 VERSION 的替代品,但是 COMPILED_AT 呢?

最佳答案

有两种方法可以做到这一点。

使用build.rs脚本

使用build.rs 脚本的好处是其他编译您的程序的用户不必以特殊方式调用cargo 或设置他们的环境。这是如何执行此操作的最小示例。

build.rs

use std::process::{Command, exit};
use std::str;

static CARGOENV: &str = "cargo:rustc-env=";

fn main() {
let time_c = Command::new("date").args(&["+%Y%m%d"]).output();

match time_c {
Ok(t) => {
let time;
unsafe {
time = str::from_utf8_unchecked( &t.stdout );
}
println!("{}COMPILED_AT={}", CARGOENV, time);
}
Err(_) => exit(1)
}
}

src/main.rs

fn main() {
println!("This is Example Program {} compiled at {}", env!("CARGO_PKG_VERSION"), env!("COMPILED_AT"));
}

Cargo.toml

[package]
name = "compiled_at"
version = "0.1.0"
authors = ["Fredrick Brennan <copypaste@kittens.ph>"]
build = "build.rs"

[dependencies]

显然,可以对其进行调整,使其在没有 /bin/date 的其他平台上运行,或者在其他内容(例如 Git 版本号)中进行编译。该脚本基于 Jmb 提供的示例,展示了如何在编译时将 Mercurial 信息添加到您的程序中。

这保证 COMPILED_AT 将被设置,否则构建将失败。这样,其他 Rust 程序员只需执行 cargo build 即可构建。

[osboxes@osboxes compiled_at]$ cargo run
Compiling compiled_at v0.1.0 (file:///home/osboxes/Workspace/rust/compiled_at)
Finished dev [unoptimized + debuginfo] target(s) in 1.27 secs
Running `target/debug/compiled_at`
This is Example Program 0.1.0 compiled at 20180202

使用env!(),然后要求用户在构建之前设置他们的环境

在我提出这个问题并尝试以下操作后,我想到了它,它确实有效(vim 正在使用中,因此转义了 %s),cargo 确实将我的环境传递给 rustc:

COMPILED_AT=`date +\%Y\%m\%d` cargo run

然后,在 Rust 中:

fn main() {
eprintln!("{}", env!("COMPILED_AT"));
}

如果我不提供环境变量,Rust 编译器将拒绝编译代码,这是一个很好的做法。

error: environment variable `COMPILED_AT` not defined
--> src/main.rs:147:21
|
147 | eprintln!("{}", env!("COMPILED_AT"));
| ^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

这种方式非常 hacky,肯定会惹恼其他只希望使用 cargo build 构建的 Rust 程序员,但它确实有效。如果可以,建议改用build.rs

关于rust - 如何将编译期间命令行上提供的字符串编译成我的 Rust 二进制文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48182725/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com