Open1
rustでビルドするbinaryごとに--versionで出力する値を変える
以下のようなディレクトリ構造でビルドし、各バイナリごとにbinary_name --versionで実行時、各バイナリに指定した別のバージョンを取得できるようにしたい。
sample_module
- bin
- binary1.rs
- binary2.rs
その実装の一例です。
clapを使った前提
clap crateを使って、--versionでの出力情報を設定することができる。
最もシンプルな実装としては、以下の通り
binary1.rs
use clap::{Parser};
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
#[arg(short, long)]
mode: Option<String>,
}
fn main() {
let args = Args::parse();
}
この実装だと、
binary_name --versionで、
親モジュールのCargo.toml内で指定した[package]内のversion=xxx 情報を自動的に取得し、表示される。
が、binary毎に別のバージョンを指定することはできない。
各binaryに別のバージョンを設定する
- clapでは、versionに具体的な値を指定することができる
- rustでは、ビルド時の環境変数から、値を取得することができる
- rsutでは、ビルド時にbuild.rs で前処理を行い、環境変数に値をセットすることができる
以上を利用して、以下の方針を立てた
- 各バイナリのバージョン情報を記録する version.toml を作成する
- build.rs で、version.tomlから情報を取得し、環境変数に値をセット
- clapのversion情報に、std::env!を使ってビルド時の環境変数から値をセットする
実装
[versions]
binary1 = "0.0.1"
binary2 = "0.0.2"
build.rs
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use serde::Deserialize;
use toml;
#[derive(Deserialize)]
struct Versions {
versions: HashMap<String, String>,
}
fn main() {
let mut file = File::open("version.toml").expect("Failed to open version.toml");
let mut contents = String::new();
file.read_to_string(&mut contents)
.expect("Failed to read version.toml");
let versions: Versions = toml::from_str(&contents).expect("Failed to parse ver.toml");
for (key, value) in versions.versions.iter() {
//ビルドスクリプト内では、cargo:という接頭辞を持つprintln!はCargoによって特別に解釈されます。
//rustc-envは、ビルド実行時に有効な環境変数としてセットされます。
println!("cargo:rustc-env=VERSION_{}={}", key.to_uppercase(), value);
}
}
binary1.rs
use clap::{Parser};
#[derive(Parser, Debug)]
#[command(author, version=std::env!("VERSION_BINARY1"), about, long_about = None)]
//--versionで出力される名称も、パッケージ名でなくバイナリ名にしたい場合、nameも指定する
//#[command(author, name="binary1", version=std::env!("VERSION_BINARY1"), about, long_about = None)]
struct Args {
#[arg(short, long)]
mode: Option<String>,
}
fn main() {
let args = Args::parse();
}