首页 > 其他分享 >Rust 在可执行文件中嵌入代码版本信息

Rust 在可执行文件中嵌入代码版本信息

时间:2023-11-06 14:24:42浏览次数:34  
标签:可执行文件 execute proc cmd let macro output 版本信息 Rust

缘起

我想要最终编译出的可执行文件中包含代码仓库的版本信息

fn main() {
    println!("Hello RustHub");

    // git rev-parse --short HEAD
	let commit_hash = "6c1b45f";
    println!("commit_hash: {}", commit_hash);
}

为了自动获取这个 "6c1b45f" 很自然的我们可以用 Rust 的过程宏(proc-macro), 只需要有一个 cmd_execute! 宏, 并且它可以这样用

let commit_hash = cmd_execute!("git rev-parse --short HEAD");

话不多说, 我们开整

新建一个 crate

# 我们把它命名为 my-proc-macro
cargo new --lib my-proc-macro
cd my-proc-macro
# 添加依赖
cargo add quote
cargo add syn --features full

然后修改 Cargo.toml, 把它改成 proc-macro 类型

[lib]
proc-macro = true

修改 src/lib.rs

use proc_macro::TokenStream;

#[proc_macro]
pub fn cmd_execute(input: TokenStream) -> TokenStream {
    // 只接受一个字符串参数
    let input: syn::LitStr = syn::parse(input).unwrap();

    #[cfg(target_os="windows")]
    let sh = "cmd";
    #[cfg(not(target_os="windows"))]
    let sh = "bash";

    let mut cmd = std::process::Command::new(sh);

    #[cfg(target_os="windows")]
    cmd.arg("/c");
    #[cfg(not(target_os="windows"))]
    cmd.arg("-c");

    cmd.arg(input.value());
    let output = match cmd.output() {
        Ok(out) => out,
        Err(e) => panic!("{}", e),
    };
    // println!("output: {:?}", output);
    if !output.status.success() {
        panic!("The command's output is: {:?}", output);
    }

    let stdout = output.stdout;

    quote::quote! {
        &[
            #(#stdout,)*
        ]
    }.into()
}

注意, 这里的 cmd_execute! 返回值是 &[u8], 如果你需要 String 只需自行转换一下

let commit_hash = cmd_execute!("git rev-parse --short HEAD");
let s = String::from_utf8_lossy(commit_hash);
let s = s.trim_end(); // 去掉末尾的换行符等空白字符

完事

这个短短的宏我已经上传到 crates.io 了, 你可以直接 cargo add cmd-proc-macro 来使用这个 cmd_execute!

标签:可执行文件,execute,proc,cmd,let,macro,output,版本信息,Rust
From: https://www.cnblogs.com/hangj/p/17812540.html

相关文章

  • 用Rust和Scraper库编写图像爬虫的建议
    本文提供一些有关如何使用Rust和Scraper库编写图像爬虫的一般建议:1、首先,你需要安装Rust和Scraper库。你可以通过Rustup或Cargo来安装Rust,然后使用Cargo来安装Scraper库。2、然后,你可以使用Scraper库的Crawler类来创建一个新的爬虫实例。3、接下来,你可以使用start方法来启动爬虫并......
  • 23_rust_练习
    练习编码实现一个简单的grep工具。建立项目:>cargonewminigrepCreatedbinary(application)`minigrep`package接收命令行参数usestd::env;fnmain(){//args返回一迭代器,collect将迭代器转换为Vector,需指明类型//args函数无法处理非法Unicode字符,如果......
  • [Rust] 对整形溢出的处理
    1.两种不同模式下的整形溢出坑了个爹的,书上说的没理解清楚,在Rust程序语言设计中文版3.2中提到了,当使用--release参数进行发布模式构建时,Rust不会检测导致panic的整形溢出,这里需要分两种情况考虑:编译期就可以发现的整形溢出程序运行过程中会发生的整形溢出1.1编译阶段如果......
  • 前端开发笔记[5]-rust的webassembly
    摘要基于rust开发webassembly入门,通过rust实现在网页中弹出警告框.rust的webassembly开发方式https://zhuanlan.zhihu.com/p/104299612入门Rust开发WebAssemblyRust编译为WebAssembly在前端项目中使用https://zhuanlan.zhihu.com/p/662991464相对来说,使用Rust开发......
  • 不可靠的 Rust Lifetime Elision
    众所周知,Rust编译器在分析代码的过程中,会对含有引用参数、返回值的函数、方法进行lifetime检查。经历数次版本迭代后Rust编译器发展出了一套惯用规则用于隐式推理lifetime注解(lifetimeelision),从而减小开发者的编写难度,尽可能省略不必要的lifetime注解。由于后文会涉......
  • 国货之光?用Rust编写的Vivo Blue OS
    ❝人生有两出悲剧:一是万念俱灰,另一是踌躇满志。——萧伯纳❞大家好,我是「柒八九」。前言“老乡,老乡,你看东方是不是有一轮朝阳在冉冉升起”。-一个稚嫩的声音从屋子中传来。而此时,一位佝偻着背的秃头老者正在简陋的屋子中,正无精打采的在用字迹早已模糊不清的键盘鼓捣着IDE,从电脑屏......
  • 8. 从零用Rust编写正反向代理, HTTP改造篇之HPACK原理
    wmproxywmproxy是由Rust编写,已实现http/https代理,socks5代理,反向代理,静态文件服务器,内网穿透,配置热更新等,后续将实现websocket代理等,同时会将实现过程分享出来,感兴趣的可以一起造个轮子法项目++wmproxy++gite:https://gitee.com/tickbh/wmproxygithub:https://github.com/tic......
  • Trust
    IsCybersecurityReally(VERY)Important?Peoplesometimesjusttrustthepeopletheycouldtrust,notshould,whichmeanssomebodywhohassomeactualabilitybutdoesn'thaveadegree/match/abilitythey(HR,Manager,Leader,Engineer,Officer,Scho......
  • 与c++比较学习rust3-2:数据类型
    rust的文章在数据类型数据类型标量类型整形,浮点型,布尔型,字符整形c++rustgoint8_ti8int8int16_ti16int16int32_ti32int32int64_ti64int64-i128-intisizeintunsignedintusizeuintuint8_tu8uint8uint16_tu16uint16ui......
  • 与c++比较学习rust3-1:变量和可变性
    rust文章:变量和可变性let,const这两个在c++中,没有与let相同的用法,letlet有点像constauto1.1.相同点:不需要指定类型。使用了constauto之后,不能改变值也不能改变类型。1.2.不同点:rust合法,c++中不合法(即c++中,不能重复定义一个变量)leta=2;leta=4;le......