Source code for pkgcore.system.libtool

__all__ = ("UnknownData", "FixLibtoolArchivesTrigger")

import re
from functools import partial
from os.path import basename, dirname

from snakeoil.currying import post_curry
from snakeoil.sequences import stable_unique

from ..exceptions import PkgcoreException
from ..merge import triggers

x11_sub = post_curry(partial(re.compile(r"X11R6/+lib").sub, "lib"), 1)
local_sub = post_curry(partial(re.compile(r"local/+lib").sub, "lib"), 1)
pkgconfig1_sub = post_curry(
    partial(re.compile(r"usr/+lib[^/]*/+pkgconfig/+\.\./\.\.").sub, "usr"), 1
)
pkgconfig2_sub = post_curry(
    partial(re.compile(r"usr/+lib[^/]*/+pkgconfig/+\.\.").sub, "usr"), 1
)
flags_match = re.compile(
    r"-(?:mt|mthreads|kthread|Kthread|pthread" r"|pthreads|-thread-safe|threads)"
).match

template = """# %(file)s - a libtool library file
# Generated by ltmain.sh - GNU libtool 1.5.10 (1.1220.2.130 2004/09/19 12:13:49)
%(content)s
"""


[docs] class UnknownData(PkgcoreException): def __init__(self, line, token=None): self.token, self.line = token, line def __str__(self): s = f"we don't know how to parse line {self.line!r}" if self.token: s += f"specifically token {self.token!r}" return s
# libtiff.la - a libtool library file # Generated by ltmain.sh - GNU libtool 1.5.10 (1.1220.2.130 2004/09/19 12:13:49) def parse_lafile(handle): d = {} for line in handle: line = line.rstrip() if not line or line.startswith("#"): continue try: key, val = line.split("=", 1) except ValueError: raise UnknownData(line) # ' is specifically forced by libtdl implementation if len(val) >= 2 and val[0] == val[-1] and val[0] == "'": val = val[1:-1] d[key] = val return d def rewrite_lafile(handle, filename): data = parse_lafile(handle) raw_dep_libs = data.get("dependency_libs", False) if not raw_dep_libs: return False, None original_libs = raw_dep_libs.split() rpaths, libs, libladirs, inherited_flags = [], [], [], [] original_inherited_flags = data.get("inherited_linker_flags", []) for item in stable_unique(original_libs): if item.startswith("-l"): libs.append(item) elif item.endswith(".la"): base = basename(item) if base.startswith("lib"): # convert to -l; punt .la, and 'lib' prefix libs.append("-l" + base[3:-3]) libladirs.append("-L" + dirname(item)) else: libs.append(item) elif item.startswith("-L"): # this is heinous, but is what the script did. item = x11_sub(item) item = local_sub(item) item = pkgconfig1_sub(item) item = pkgconfig2_sub(item) libladirs.append(item) elif item.startswith("-R"): rpaths.append(item) elif flags_match(item): if inherited_flags: inherited_flags.append(item) else: libs.append(item) else: raise UnknownData(raw_dep_libs, item) libs = stable_unique(rpaths + libladirs + libs) inherited_flags = stable_unique(inherited_flags) if libs == original_libs and inherited_flags == original_inherited_flags: return False, None # must be prefixed with a space data["dependency_libs"] = " " + (" ".join(libs)) if inherited_flags: # must be prefixed with a space data["inherited_flags"] = " " + (" ".join(inherited_flags)) content = "\n".join(f"{k}='{v}'" for k, v in sorted(data.items())) return True, template % {"content": content, "file": filename} def fix_fsobject(location): from ..fs import fs, livefs for obj in livefs.iter_scan(location): if not fs.isreg(obj) or not obj.basename.endswith(".la"): continue with open(obj.location, "r") as f: updated, content = rewrite_lafile(f, obj.basename) if updated: with open(obj.location, "w") as f: f.write(content)
[docs] class FixLibtoolArchivesTrigger(triggers.base): required_csets = ("install",) _engine_types = triggers.INSTALLING_MODES _hooks = ("pre_merge",)
[docs] def trigger(self, engine, cset): updates = [] for obj in cset.iterfiles(): if not obj.basename.endswith(".la"): continue handle = obj.data.text_fileobj() updated, content = rewrite_lafile(handle, obj.basename) if not updated: continue engine.observer.info(f"rewriting libtool archive {obj.location}") source = engine.get_writable_fsobj(obj, empty=True) source.text_fileobj(True).write(content) # force chksums to be regenerated updates.append(obj.change_attributes(data=source, chksums=None)) cset.update(updates)