1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-30 00:00:15 +01:00
libhermit/usr/rdma-core/buildlib/gen-sparse.py
2017-10-06 15:13:04 +02:00

137 lines
4.3 KiB
Python
Executable file

#!/usr/bin/env python
# Copyright 2015-2017 Obsidian Research Corp.
# Licensed under BSD (MIT variant) or GPLv2. See COPYING.
import argparse
import subprocess
import os
import collections
headers = {
"endian.h",
"netinet/in.h",
"pthread.h",
"sys/socket.h",
"stdatomic.h",
};
def norm_header(fn):
for I in headers:
flat = I.replace("/","-");
if fn.endswith(flat):
return I;
if fn.endswith(flat + ".diff"):
return I;
return None;
def get_buildlib_patches(dfn):
"""Within the buildlib directory we store patches for the glibc headers. Each
patch is in a numbered sub directory that indicates the order to try, the
number should match the glibc version used to make the diff."""
res = [];
for d,_,files in os.walk(dfn):
for I in files:
if d != dfn:
bn = int(os.path.basename(d));
else:
bn = 0;
res.append((bn,os.path.join(d,I)));
res.sort(reverse=True);
ret = collections.defaultdict(list);
for _,I in res:
ret[norm_header(I)].append(I);
return ret;
def is_patch(fn):
with open(fn) as F:
return F.read(10).startswith("-- /");
def apply_patch(src,patch,dest):
"""Patch a single system header. The output goes into our include search path
and takes precedence over the system version."""
dfn = os.path.dirname(dest);
if not os.path.isdir(dfn):
os.makedirs(dfn);
if not patch.endswith(".diff"):
if not os.path.exists(dest):
os.symlink(patch,dest);
return True;
try:
if os.path.exists(dest + ".rej"):
os.unlink(dest + ".rej");
subprocess.check_output(["patch","-f","--follow-symlinks","-V","never","-i",patch,"-o",dest,src]);
if os.path.exists(dest + ".rej"):
print "Patch from %r failed"%(patch);
return False;
except subprocess.CalledProcessError:
print "Patch from %r failed"%(patch);
return False;
return True;
def replace_header(fn):
tries = 0;
for pfn in patches[fn]:
if apply_patch(os.path.join(args.REF,fn),
pfn,os.path.join(args.INCLUDE,fn)):
return;
tries = tries + 1;
print "Unable to apply any patch to %r, tries %u"%(fn,tries);
global failed;
failed = True;
def save(fn,outdir):
"""Diff the header file in our include directory against the system header and
store the diff into buildlib. This makes it fairly easy to maintain the
replacement headers."""
if os.path.islink(os.path.join(args.INCLUDE,fn)):
return;
flatfn = fn.replace("/","-") + ".diff";
flatfn = os.path.join(outdir,flatfn);
with open(flatfn,"wt") as F:
try:
subprocess.check_call(["diff","-u",
os.path.join(args.REF,fn),
os.path.join(args.INCLUDE,fn)],
stdout=F);
except subprocess.CalledProcessError as ex:
if ex.returncode == 1:
return;
raise;
parser = argparse.ArgumentParser(description='Produce sparse shim header files')
parser.add_argument("--out",dest="INCLUDE",required=True,
help="Directory to write header files to");
parser.add_argument("--src",dest="SRC",required=True,
help="Top of the source tree");
parser.add_argument("--ref",dest="REF",default="/usr/include/",
help="System headers to manipulate");
parser.add_argument("--save",action="store_true",default=False,
help="Save mode will write the current content of the headers to buildlib as a diff.");
args = parser.parse_args();
if args.save:
# Get the glibc version string
ver = subprocess.check_output(["ldd","--version"]).splitlines()[0].split(' ')[-1];
ver = ver.partition(".")[-1];
outdir = os.path.join(args.SRC,"buildlib","sparse-include",ver);
if not os.path.isdir(outdir):
os.makedirs(outdir);
for I in headers:
save(I,outdir);
else:
failed = False;
patches = get_buildlib_patches(os.path.join(args.SRC,"buildlib","sparse-include"));
for I in headers:
replace_header(I);
if failed:
raise ValueError("Patch applications failed");