mirror of
https://github.com/rui314/mold.git
synced 2026-11-07 09:16:04 -10:00
Move the git hash lookup to mold-common
elf/build.rs looked up the commit mold is built from and made the ELF linker's version string from it. The Mach-O linker needs the hash as well, so mold-common's build script now looks it up and exports it as mold_common::GIT_HASH. The ELF linker's version string is unchanged.
This commit is contained in:
1 parent
afd7b70851
commit
96406a27e1
6 files changed
+89
-71
No files matched your search
@@ -0,0 +1,68 @@
|
||||
//! Finds the git commit that mold is built from, for the linkers' version
|
||||
//! strings.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
// Embed the current git commit hash into the mold executable. We ask git
|
||||
// instead of parsing files under .git because the repository format varies
|
||||
// (e.g. packed refs, reftable). When building from a source tarball, there's
|
||||
// no .git, and the hash is simply omitted.
|
||||
fn git_hash(source_dir: &Path) -> Option<String> {
|
||||
let dot_git = source_dir.join(".git");
|
||||
if !dot_git.exists() {
|
||||
// Source archives use the package version. If Git metadata is added
|
||||
// later, a clean rebuild is needed to embed the new commit hash.
|
||||
return None;
|
||||
}
|
||||
if dot_git.is_file() {
|
||||
println!("cargo:rerun-if-changed={}", dot_git.display());
|
||||
}
|
||||
|
||||
let git_path = |name: &str| -> Option<PathBuf> {
|
||||
let output = Command::new("git")
|
||||
.arg("-C")
|
||||
.arg(source_dir)
|
||||
.args(["rev-parse", "--git-path", name])
|
||||
.output()
|
||||
.ok()?;
|
||||
if !output.status.success() {
|
||||
return None;
|
||||
}
|
||||
let path = PathBuf::from(String::from_utf8(output.stdout).ok()?.trim());
|
||||
Some(if path.is_absolute() { path } else { source_dir.join(path) })
|
||||
};
|
||||
|
||||
let reftable = git_path("reftable/tables.list").filter(|p| p.exists());
|
||||
if let Some(head) = git_path("HEAD").filter(|p| p.exists()) {
|
||||
println!("cargo:rerun-if-changed={}", head.display());
|
||||
if let Ok(contents) = std::fs::read_to_string(&head)
|
||||
&& let Some(reference) =
|
||||
contents.strip_prefix("ref: ").map(str::trim).filter(|_| reftable.is_none())
|
||||
&& let Some(path) = git_path(reference)
|
||||
{
|
||||
// A packed reference may acquire a loose file later.
|
||||
// Watch its nearest existing directory until that happens.
|
||||
if let Some(path) = path.ancestors().find(|p| p.exists()) {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
for path in git_path("packed-refs").into_iter().chain(reftable).filter(|p| p.exists()) {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
}
|
||||
|
||||
let output =
|
||||
Command::new("git").arg("-C").arg(source_dir).args(["rev-parse", "HEAD"]).output().ok()?;
|
||||
output.status.success().then(|| String::from_utf8_lossy(&output.stdout).trim().to_string())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
// This crate is in common/ of the source tree.
|
||||
let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
if let Some(hash) = git_hash(manifest_dir.parent().unwrap()) {
|
||||
println!("cargo:rustc-env=MOLD_GIT_HASH={hash}");
|
||||
}
|
||||
}
|
||||
@@ -22,3 +22,7 @@ pub mod util;
|
||||
pub mod worker_local;
|
||||
|
||||
pub use prefetch::prefetch;
|
||||
|
||||
/// The git commit that mold is built from, or None if the source tree has
|
||||
/// no git metadata, as in a source tarball.
|
||||
pub const GIT_HASH: Option<&str> = option_env!("MOLD_GIT_HASH");
|
||||
+1
-64
@@ -8,73 +8,10 @@
|
||||
//! `lto-message.c` adapts the LTO plugin's printf-like diagnostics
|
||||
//! callback, which is C-variadic as well, and is linked into mold.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
// Embed the current git commit hash into the mold executable. We ask git
|
||||
// instead of parsing files under .git because the repository format varies
|
||||
// (e.g. packed refs, reftable). When building from a source tarball, there's
|
||||
// no .git, and the hash is simply omitted.
|
||||
fn git_hash(source_dir: &Path) -> Option<String> {
|
||||
let dot_git = source_dir.join(".git");
|
||||
if !dot_git.exists() {
|
||||
// Source archives use the package version. If Git metadata is added
|
||||
// later, a clean rebuild is needed to embed the new commit hash.
|
||||
return None;
|
||||
}
|
||||
if dot_git.is_file() {
|
||||
println!("cargo:rerun-if-changed={}", dot_git.display());
|
||||
}
|
||||
|
||||
let git_path = |name: &str| -> Option<PathBuf> {
|
||||
let output = Command::new("git")
|
||||
.arg("-C")
|
||||
.arg(source_dir)
|
||||
.args(["rev-parse", "--git-path", name])
|
||||
.output()
|
||||
.ok()?;
|
||||
if !output.status.success() {
|
||||
return None;
|
||||
}
|
||||
let path = PathBuf::from(String::from_utf8(output.stdout).ok()?.trim());
|
||||
Some(if path.is_absolute() { path } else { source_dir.join(path) })
|
||||
};
|
||||
|
||||
let reftable = git_path("reftable/tables.list").filter(|p| p.exists());
|
||||
if let Some(head) = git_path("HEAD").filter(|p| p.exists()) {
|
||||
println!("cargo:rerun-if-changed={}", head.display());
|
||||
if let Ok(contents) = std::fs::read_to_string(&head)
|
||||
&& let Some(reference) =
|
||||
contents.strip_prefix("ref: ").map(str::trim).filter(|_| reftable.is_none())
|
||||
&& let Some(path) = git_path(reference)
|
||||
{
|
||||
// A packed reference may acquire a loose file later.
|
||||
// Watch its nearest existing directory until that happens.
|
||||
if let Some(path) = path.ancestors().find(|p| p.exists()) {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
for path in git_path("packed-refs").into_iter().chain(reftable).filter(|p| p.exists()) {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
}
|
||||
|
||||
let output =
|
||||
Command::new("git").arg("-C").arg(source_dir).args(["rev-parse", "HEAD"]).output().ok()?;
|
||||
output.status.success().then(|| String::from_utf8_lossy(&output.stdout).trim().to_string())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// This crate is in elf/ of the source tree.
|
||||
let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
let source_dir = manifest_dir.parent().unwrap();
|
||||
let version = std::env::var("CARGO_PKG_VERSION").unwrap();
|
||||
let version = match git_hash(source_dir) {
|
||||
Some(hash) => format!("mold {version} ({hash}; compatible with GNU ld)"),
|
||||
None => format!("mold {version} (compatible with GNU ld)"),
|
||||
};
|
||||
println!("cargo:rustc-env=MOLD_VERSION={version}");
|
||||
|
||||
println!("cargo:rerun-if-changed=c/mold-wrapper.c");
|
||||
println!("cargo:rerun-if-changed=c/lto-message.c");
|
||||
|
||||
|
||||
+13
-5
@@ -5,6 +5,7 @@ use std::collections::{HashMap, HashSet};
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::io::{IsTerminal, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use bstr::{ByteSlice, ByteVec};
|
||||
use mold_common::error::strerror;
|
||||
@@ -237,7 +238,13 @@ Options:
|
||||
mold: supported targets: elf32-i386 elf64-x86-64 elf32-littlearm elf64-littleaarch64 elf64-bigaarch64 elf32-littleriscv elf32-bigriscv elf64-littleriscv elf64-bigriscv elf32-powerpc elf64-powerpc elf64-powerpc elf64-powerpcle elf64-s390 elf64-sparc elf32-m68k elf32-sh-linux elf64-loongarch elf32-loongarch
|
||||
mold: supported emulations: elf_i386 elf_x86_64 armelf_linux_eabi aarch64elf aarch64linux aarch64elfb aarch64linuxb elf32lriscv elf32briscv elf64lriscv elf64briscv elf32ppc elf32ppclinux elf64ppc elf64lppc elf64_s390 elf64_sparc m68kelf shlelf_linux shelf_linux elf64loongarch elf32loongarch";
|
||||
|
||||
pub const VERSION: &str = env!("MOLD_VERSION");
|
||||
pub static VERSION: LazyLock<String> = LazyLock::new(|| {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
match mold_common::GIT_HASH {
|
||||
Some(hash) => format!("mold {version} ({hash}; compatible with GNU ld)"),
|
||||
None => format!("mold {version} (compatible with GNU ld)"),
|
||||
}
|
||||
});
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub enum BuildId {
|
||||
@@ -1326,18 +1333,19 @@ pub fn parse_args(target: &TargetTraits, raw_cmdline: &[Cow<'_, OsStr>]) -> Pars
|
||||
} else if cursor.read_flag("no-dynamic-linker") {
|
||||
a.dynamic_linker.clear();
|
||||
} else if cursor.read_flag("v") {
|
||||
out!("{VERSION}");
|
||||
out!("{}", *VERSION);
|
||||
version_shown = true;
|
||||
} else if cursor.read_flag("version") {
|
||||
out!("{VERSION}");
|
||||
out!("{}", *VERSION);
|
||||
std::process::exit(0);
|
||||
} else if cursor.read_flag("V") {
|
||||
out!(
|
||||
"{VERSION}\n Supported emulations:\n elf_x86_64\n elf_i386\n aarch64elf\n \
|
||||
"{}\n Supported emulations:\n elf_x86_64\n elf_i386\n aarch64elf\n \
|
||||
aarch64linux\n aarch64elfb\n aarch64linuxb\n armelf_linux_eabi\n elf64lriscv\n \
|
||||
elf64briscv\n elf32lriscv\n elf32briscv\n elf32ppc\n elf64ppc\n elf64lppc\n \
|
||||
elf64_s390\n elf64_sparc\n m68kelf\n shlelf_linux\n shelf_linux\n \
|
||||
elf64loongarch\n elf32loongarch"
|
||||
elf64loongarch\n elf32loongarch",
|
||||
*VERSION
|
||||
);
|
||||
version_shown = true;
|
||||
} else if read_arg!("mllvm", true) {
|
||||
|
||||
+2
-1
@@ -544,7 +544,8 @@ unsafe extern "C" fn get_api_version(
|
||||
static LINKER_VERSION: OnceLock<CString> = OnceLock::new();
|
||||
unsafe {
|
||||
*linker_identifier = c"mold".as_ptr();
|
||||
*linker_version = LINKER_VERSION.get_or_init(|| CString::new(VERSION).unwrap()).as_ptr();
|
||||
*linker_version =
|
||||
LINKER_VERSION.get_or_init(|| CString::new(VERSION.as_str()).unwrap()).as_ptr();
|
||||
}
|
||||
if LAPI_V1 <= maximal_api_supported {
|
||||
HOOKS.lock().unwrap().gcc_api_v1 = true;
|
||||
|
||||
+1
-1
@@ -1707,7 +1707,7 @@ pub fn write_repro_file<E: Target>(ctx: &Context<E>) {
|
||||
write(
|
||||
&mut tar,
|
||||
std::path::Path::new("version.txt"),
|
||||
format!("{}\n", crate::cmdline::VERSION).as_bytes(),
|
||||
format!("{}\n", *crate::cmdline::VERSION).as_bytes(),
|
||||
);
|
||||
|
||||
// Input files are archived from memory. Their contents are still those
|
||||
|
||||
Reference in new issue
Block a user