Include extension build info at compile time

finchie
Dec 16, 2025, 8:32 AM
IAMJPC2QCHQGUON43V7JL5K5S23TKQORKTQBUGWHCI6EEK2TPDQQC

Dependencies

  • [2] 4IXB7PLV
  • [3] WFWTKCJN Create initial Visual Studio Code extension
  • [4] 72K45XKD Refactor inline credit to improve hover messages
  • [5] VKCHFDMC Create simple `FileSystemWatcher`

Change contents

  • edit in extensions/vscode/src/lib.rs at line 28
    [3.109515]
    [3.109515]
    const BUILD_INFO: extension_build_info::Build = extension_build_info::include_build_info!();
  • replacement in extensions/vscode/src/lib.rs at line 401
    [3.120997][3.120997:121040]()
    tracing::info!("Extension activated");
    [3.120997]
    [3.121040]
    tracing::info!(message = "Extension activated", ?BUILD_INFO);
  • replacement in extensions/vscode/build.rs at line 1
    [3.175349][3.175350:175385]()
    fn main() {
    napi_build::setup();
    [3.175349]
    [3.175385]
    fn main() -> Result<(), anyhow::Error> {
    napi_build::setup();
    extension_build_info::export()?;
    Ok(())
  • edit in extensions/vscode/Cargo.toml at line 18
    [3.175787]
    [3.175787]
    extension-build-info.workspace = true
  • edit in extensions/vscode/Cargo.toml at line 40
    [3.176141]
    [3.176141]
    anyhow.workspace = true
    extension-build-info.workspace = true
  • file addition: build-info (d--r------)
    [2.1]
  • file addition: src (d--r------)
    [0.402]
  • file addition: lib.rs (----------)
    [0.419]
    use std::num::NonZeroUsize;
    use camino::{Utf8Path, Utf8PathBuf};
    use libpijul::pristine::sanakirja::Pristine;
    use libpijul::{Base32, RecordBuilder, TxnT, TxnTExt};
    use quote::quote;
    #[derive(Debug)]
    pub struct Build {
    pub package: Package,
    pub toolchain: Toolchain,
    pub compilation: Compilation,
    pub repository: Repository,
    pub timestamp: jiff::Timestamp,
    }
    #[derive(Debug)]
    pub struct Package {
    pub package_name: &'static str,
    pub package_version: &'static str,
    }
    impl Package {
    fn export() -> Result<proc_macro2::TokenStream, anyhow::Error> {
    let package_name = std::env::var("CARGO_PKG_NAME")?;
    let package_version = &std::env::var("CARGO_PKG_VERSION")?;
    Ok(quote! {
    extension_build_info::Package {
    package_name: #package_name,
    package_version: #package_version,
    }
    })
    }
    }
    #[derive(Debug)]
    pub struct Toolchain {
    pub cargo_version: &'static str,
    pub rustc_version: &'static str,
    }
    impl Toolchain {
    fn get_version(program_location: String) -> Result<String, anyhow::Error> {
    let version_output = std::process::Command::new(program_location)
    .arg("--version")
    .output()?;
    let version_string = String::from_utf8(version_output.stdout)?;
    Ok(match version_string.strip_suffix('\n') {
    Some(version) => version.to_string(),
    None => version_string,
    })
    }
    fn export() -> Result<proc_macro2::TokenStream, anyhow::Error> {
    let cargo_version = Self::get_version(std::env::var("CARGO")?)?;
    let rustc_version = Self::get_version(std::env::var("RUSTC")?)?;
    Ok(quote! {
    extension_build_info::Toolchain {
    cargo_version: #cargo_version,
    rustc_version: #rustc_version,
    }
    })
    }
    }
    #[derive(Debug)]
    pub struct Compilation {
    pub target: &'static str,
    pub profile: &'static str,
    pub opt_level: &'static str,
    pub debug: &'static str,
    pub rustflags: &'static [&'static str],
    }
    impl Compilation {
    fn export() -> Result<proc_macro2::TokenStream, anyhow::Error> {
    let target = std::env::var("TARGET")?;
    let profile = std::env::var("PROFILE")?;
    let opt_level = std::env::var("OPT_LEVEL")?;
    let debug = std::env::var("DEBUG")?;
    let encoded_rustflags = std::env::var("CARGO_ENCODED_RUSTFLAGS")?;
    let rustflags = encoded_rustflags.split('\u{1f}');
    Ok(quote! {
    extension_build_info::Compilation {
    target: #target,
    profile: #profile,
    opt_level: #opt_level,
    debug: #debug,
    rustflags: &[#(#rustflags),*],
    }
    })
    }
    }
    #[derive(Debug)]
    pub struct Repository {
    pub channel_name: &'static str,
    pub channel_state: &'static str,
    pub has_unrecorded_changes: bool,
    }
    impl Repository {
    fn export() -> Result<proc_macro2::TokenStream, anyhow::Error> {
    let extension_manifest_directory = Utf8PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?);
    let repository_root = extension_manifest_directory
    .parent()
    .unwrap()
    .parent()
    .unwrap();
    let pristine_db = repository_root
    .join(libpijul::DOT_DIR)
    .join("pristine")
    .join("db");
    let pristine = Pristine::new(pristine_db.as_str())?;
    let change_store =
    libpijul::changestore::filesystem::FileSystem::from_root(repository_root.as_str(), 256);
    let working_copy = libpijul::working_copy::FileSystem::from_root(repository_root.as_str());
    // Recorded changes
    let transaction = pristine.arc_txn_begin()?;
    let read_transaction = transaction.read();
    let channel_name = read_transaction
    .current_channel()
    .unwrap_or(libpijul::DEFAULT_CHANNEL);
    let channel = read_transaction.load_channel(channel_name)?.unwrap();
    let channel_merkle = read_transaction.current_state(&*channel.read())?;
    let channel_state = channel_merkle.to_base32();
    // Unrecorded changes
    let mut record_builder = RecordBuilder::new();
    record_builder.record(
    transaction.clone(),
    libpijul::Algorithm::default(),
    true,
    &libpijul::DEFAULT_SEPARATOR,
    channel.clone(),
    &working_copy,
    &change_store,
    "",
    std::thread::available_parallelism()
    .unwrap_or(NonZeroUsize::MIN)
    .get(),
    )?;
    let unrecorded_changes = record_builder.finish();
    let has_unrecorded_changes = !unrecorded_changes.actions.is_empty();
    Ok(quote! {
    extension_build_info::Repository {
    channel_name: #channel_name,
    channel_state: #channel_state,
    has_unrecorded_changes: #has_unrecorded_changes,
    }
    })
    }
    }
    #[macro_export]
    macro_rules! include_build_info {
    () => {
    include!(concat!(env!("OUT_DIR"), "/build_info.rs"))
    };
    }
    pub fn export() -> Result<(), anyhow::Error> {
    let timestamp = jiff::Timestamp::now();
    let timestamp_seconds = timestamp.as_second();
    let timestamp_nanoseconds = timestamp.subsec_nanosecond();
    let package = Package::export()?;
    let toolchain = Toolchain::export()?;
    let compilation = Compilation::export()?;
    let repository = Repository::export()?;
    let token_stream = quote! {
    extension_build_info::Build {
    package: #package,
    toolchain: #toolchain,
    compilation: #compilation,
    repository: #repository,
    timestamp: jiff::Timestamp::constant(#timestamp_seconds, #timestamp_nanoseconds),
    }
    };
    let out_dir = std::env::var("OUT_DIR")?;
    let file_path = Utf8Path::new(&out_dir).join("build_info.rs");
    std::fs::write(file_path, token_stream.to_string().as_bytes())?;
    Ok(())
    }
  • file addition: Cargo.toml (----------)
    [0.402]
    [package]
    name = "extension-build-info"
    publish = false
    version = "0.1.0"
    edition = "2024"
    [dependencies]
    anyhow.workspace = true
    camino.workspace = true
    jiff.workspace = true
    libpijul.workspace = true
    proc-macro2.workspace = true
    quote.workspace = true
  • edit in Cargo.toml at line 2
    [3.176218]
    [3.176218]
    members = ["build-info", "extensions/vscode", "pijul-extension", "xtask"]
  • edit in Cargo.toml at line 4
    [3.176233][3.176233:176293]()
    members = ["xtask", "pijul-extension", "extensions/vscode"]
  • edit in Cargo.toml at line 21
    [3.176690]
    [3.176690]
    extension-build-info.path = "build-info"
  • edit in Cargo.toml at line 47
    [3.177173]
    [3.177173]
    proc-macro2 = "1.0"
    quote = "1.0"
  • edit in Cargo.lock at line 970
    [3.200355]
    [3.200355]
    ]
    [[package]]
    name = "extension-build-info"
    version = "0.1.0"
    dependencies = [
    "anyhow",
    "camino",
    "jiff",
    "libpijul",
    "proc-macro2",
    "quote",
  • edit in Cargo.lock at line 2578
    [3.235734]
    [4.16575]
    "anyhow",
  • edit in Cargo.lock at line 2581
    [3.235745]
    [4.16587]
    "extension-build-info",