mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 14:58:03 +03:00
hg.rust: add BuildInfo symbols
Summary: BuildInfo symbols are generated for fbcode binaries, and scanned by the internal procprint tool. The procprint tool also scans hg binaries, but cannot extract any build information. The procprint data is used by Push4Push to find out job owners running ancient software. This diff inserts BuildInfo symbols so Push4Push (and we) can use them to figure out people running old versions of hg and send tasks to them. Note rpmbuild strips symbols by default and is hard to customize. For now, I just disable the debuginfo packages to preserve the symbols. If space usage or runtime performance becomes an issue, we can try other workarounds (ex. provide a shim of `%_find_debuginfo_dwz_opts` that skips `hg.rust`, or provide a shim of `%__strip`, etc). By default, the symbols only get added when `setup.py` is run by `rpmbuild`. So `make local` won't rebuild `hg.rust` every time. Reviewed By: singhsrb Differential Revision: D14464056 fbshipit-source-id: ac6f9dedf28cee5fc8d65e144e3d7d1c544d1eda
This commit is contained in:
parent
b40af5890c
commit
41ccbe9f8d
@ -14,6 +14,7 @@ path = "../../lib/encoding"
|
||||
path = "../../lib/hgpython"
|
||||
|
||||
[features]
|
||||
buildinfo = []
|
||||
default = []
|
||||
with_chg = []
|
||||
hgdev = ["hgpython/hgdev"]
|
||||
|
@ -14,6 +14,11 @@ fn main() {
|
||||
"cargo:rerun-if-changed={}",
|
||||
lib_dir.join("libchg.a").display()
|
||||
);
|
||||
#[cfg(feature = "buildinfo")]
|
||||
println!(
|
||||
"cargo:rerun-if-changed={}",
|
||||
lib_dir.join("buildinfo.a").display()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
7
exec/hgmain/src/buildinfo.rs
Normal file
7
exec/hgmain/src/buildinfo.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright Facebook, Inc. 2019
|
||||
|
||||
#[cfg(feature = "buildinfo")]
|
||||
#[link(name = "buildinfo", kind = "static")]
|
||||
extern "C" {
|
||||
pub fn print_buildinfo();
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
// Copyright Facebook, Inc. 2018
|
||||
|
||||
#[cfg(feature = "with_chg")]
|
||||
extern crate dirs;
|
||||
extern crate encoding;
|
||||
@ -7,6 +8,7 @@ extern crate hgpython;
|
||||
extern crate libc;
|
||||
use hgpython::HgPython;
|
||||
|
||||
mod buildinfo;
|
||||
#[cfg(feature = "with_chg")]
|
||||
mod chg;
|
||||
#[cfg(feature = "with_chg")]
|
||||
@ -23,6 +25,20 @@ fn call_embedded_python() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
#[cfg(feature = "buildinfo")]
|
||||
{
|
||||
// This code path keeps buildinfo-related symbols alive.
|
||||
use std::env;
|
||||
if let Some(arg0) = env::args().nth(0) {
|
||||
if arg0.ends_with("buildinfo") {
|
||||
unsafe {
|
||||
buildinfo::print_buildinfo();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with_chg")]
|
||||
maybe_call_chg();
|
||||
call_embedded_python();
|
||||
|
102
setup.py
102
setup.py
@ -18,6 +18,7 @@ import os
|
||||
import py_compile
|
||||
import re
|
||||
import shutil
|
||||
import socket
|
||||
import stat
|
||||
import struct
|
||||
import subprocess
|
||||
@ -452,15 +453,24 @@ def localhgenv():
|
||||
return env
|
||||
|
||||
|
||||
def pickversion():
|
||||
hg = findhg()
|
||||
hg = findhg()
|
||||
|
||||
|
||||
def hgtemplate(template, cast=None):
|
||||
if not hg:
|
||||
# if hg is not found, fallback to a fixed version
|
||||
return "4.4.2"
|
||||
return None
|
||||
result = sysstr(hg.run(["log", "-r.", "-T", template]))
|
||||
if result and cast:
|
||||
result = cast(result)
|
||||
return result
|
||||
|
||||
|
||||
def pickversion():
|
||||
# New version system: YYMMDD_HHmmSS_hash
|
||||
# This is duplicated a bit from build_rpm.py:auto_release_str()
|
||||
template = '{sub("([:+-]|\d\d\d\d$)", "",date|isodatesec)} {node|short}'
|
||||
out = sysstr(hg.run(["log", "-r.", "-T", template]))
|
||||
# if hg is not found, fallback to a fixed version
|
||||
out = hgtemplate(template) or ""
|
||||
# Some tools parse this number to figure out if they support this version of
|
||||
# Mercurial, so prepend with 4.4.2.
|
||||
# ex. 4.4.2_20180105_214829_58fda95a0202
|
||||
@ -502,6 +512,77 @@ if not os.path.isdir(builddir):
|
||||
ensureexists(builddir)
|
||||
|
||||
|
||||
def writebuildinfoc():
|
||||
"""Write build/buildinfo.c"""
|
||||
commithash = hgtemplate("{node}")
|
||||
commitunixtime = hgtemplate('{sub("[^0-9].*","",date)}', cast=int)
|
||||
|
||||
# Search 'extractBuildInfoFromELF' in fbcode for supported fields.
|
||||
buildinfo = {
|
||||
"Host": socket.gethostname(),
|
||||
"PackageName": os.environ.get("RPM_PACKAGE_NAME")
|
||||
or os.environ.get("PACKAGE_NAME"),
|
||||
"PackageRelease": os.environ.get("RPM_PACKAGE_RELEASE")
|
||||
or os.environ.get("PACKAGE_RELEASE"),
|
||||
"PackageVersion": os.environ.get("RPM_PACKAGE_VERSION")
|
||||
or os.environ.get("PACKAGE_VERSION"),
|
||||
"Path": os.getcwd(),
|
||||
"Platform": os.environ.get("RPM_OS"),
|
||||
"Revision": commithash,
|
||||
"RevisionCommitTimeUnix": commitunixtime,
|
||||
"TimeUnix": int(time.time()),
|
||||
"UpstreamRevision": commithash,
|
||||
"UpstreamRevisionCommitTimeUnix": commitunixtime,
|
||||
"User": os.environ.get("USER"),
|
||||
}
|
||||
|
||||
buildinfosrc = """
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
"""
|
||||
for name, value in sorted(buildinfo.items()):
|
||||
if isinstance(value, str):
|
||||
buildinfosrc += 'const char *BuildInfo_k%s = "%s";\n' % (
|
||||
name,
|
||||
value.replace('"', '\\"'),
|
||||
)
|
||||
elif isinstance(value, int):
|
||||
# The only usage of int is timestamp
|
||||
buildinfosrc += "const time_t BuildInfo_k%s = %d;\n" % (name, value)
|
||||
|
||||
buildinfosrc += """
|
||||
/* This function keeps references of the symbols and prevents them from being
|
||||
* optimized out if this function is used. */
|
||||
void print_buildinfo() {
|
||||
"""
|
||||
for name, value in sorted(buildinfo.items()):
|
||||
if isinstance(value, str):
|
||||
buildinfosrc += (
|
||||
' fprintf(stderr, "%(name)s: %%s (at %%p)\\n", BuildInfo_k%(name)s, BuildInfo_k%(name)s);\n'
|
||||
% {"name": name}
|
||||
)
|
||||
elif isinstance(value, int):
|
||||
buildinfosrc += (
|
||||
' fprintf(stderr, "%(name)s: %%lu (at %%p)\\n", (long unsigned)BuildInfo_k%(name)s, &BuildInfo_k%(name)s) ;\n'
|
||||
% {"name": name}
|
||||
)
|
||||
buildinfosrc += """
|
||||
}
|
||||
"""
|
||||
|
||||
path = pjoin(builddir, "buildinfo.c")
|
||||
write_if_changed(path, buildinfosrc)
|
||||
return path
|
||||
|
||||
|
||||
# If NEED_BUILDINFO is set, write buildinfo.
|
||||
# For rpmbuild, imply NEED_BUILDINFO.
|
||||
needbuildinfo = bool(os.environ.get("NEED_BUILDINFO", "RPM_PACKAGE_NAME" in os.environ))
|
||||
|
||||
if needbuildinfo:
|
||||
buildinfocpath = writebuildinfoc()
|
||||
|
||||
|
||||
try:
|
||||
oldpolicy = os.environ.get("HGMODULEPOLICY", None)
|
||||
os.environ["HGMODULEPOLICY"] = "py"
|
||||
@ -1833,6 +1914,16 @@ libraries = [
|
||||
},
|
||||
),
|
||||
]
|
||||
if needbuildinfo:
|
||||
libraries += [
|
||||
(
|
||||
"buildinfo",
|
||||
{
|
||||
"sources": [buildinfocpath],
|
||||
"extra_args": filter(None, cflags + [WALL, PIC]),
|
||||
},
|
||||
)
|
||||
]
|
||||
|
||||
if not iswindows:
|
||||
libraries.append(
|
||||
@ -2104,6 +2195,7 @@ hgmainfeatures = (
|
||||
filter(
|
||||
None,
|
||||
[
|
||||
"buildinfo" if needbuildinfo else None,
|
||||
"hgdev" if os.environ.get("HGDEV") else None,
|
||||
"with_chg" if not iswindows else None,
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user