__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)