#!/usr/bin/env python3 import argparse import os import re import subprocess import tempfile os.chdir(os.path.dirname(__file__) + "/..") PATH = "src/" CURL_RE=re.compile(r"\bcurl_\w*") def get_curl_calls(path): names = set() for directory, _, files in os.walk(path): for filename in files: if (filename.endswith(".cpp") or filename.endswith(".c") or filename.endswith(".h")): with open(os.path.join(directory, filename)) as f: contents = f.read() names = names.union(CURL_RE.findall(contents)) return names def assembly_source(names): names = sorted(names) result = [] for name in names: result.append(".type {},@function".format(name)) for name in names: result.append(".global {}".format(name)) for name in names: result.append("{}:".format(name)) return "\n".join(result + [""]) DEFAULT_OUTPUT="libcurl.so" DEFAULT_SONAME="libcurl.so.4" def main(): p = argparse.ArgumentParser(description="Create a stub shared object for linking") p.add_argument("-k", "--keep", action="store_true", help="Keep the intermediary assembly file") p.add_argument("--output", help="Output filename (default: {})".format(DEFAULT_OUTPUT), default=DEFAULT_OUTPUT) p.add_argument("--soname", help="soname of the produced shared object (default: {})".format(DEFAULT_SONAME), default=DEFAULT_SONAME) p.add_argument("--functions", metavar="FUNCTION", nargs="+", help="Function symbols that should be put into the shared object (default: look for curl_* names in the source code)") p.add_argument("--link-args", help="Colon-separated list of additional linking arguments") args = p.parse_args() if args.functions is not None: functions = args.functions else: functions = get_curl_calls(PATH) extra_link_args = [] if args.link_args: extra_link_args = args.link_args.split(":") with tempfile.NamedTemporaryFile("w", suffix=".s", delete=not args.keep) as f: if args.keep: print("using {} as temporary file".format(f.name)) f.write(assembly_source(functions)) f.flush() subprocess.check_call([ "cc", ] + extra_link_args + [ "-shared", "-nostdlib", # don't need to link to libc "-Wl,-soname,{}".format(args.soname), "-o", args.output, f.name, ]) subprocess.check_call(["strip", args.output]) if __name__ == '__main__': main()