diff options
Diffstat (limited to 'portage_with_autodep/pym/portage/util/lafilefixer.py')
-rw-r--r-- | portage_with_autodep/pym/portage/util/lafilefixer.py | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/portage_with_autodep/pym/portage/util/lafilefixer.py b/portage_with_autodep/pym/portage/util/lafilefixer.py new file mode 100644 index 0000000..2b093d8 --- /dev/null +++ b/portage_with_autodep/pym/portage/util/lafilefixer.py @@ -0,0 +1,185 @@ +# Copyright 2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +import os as _os +import re + +from portage import _unicode_decode +from portage.exception import InvalidData + +######################################################### +# This an re-implementaion of dev-util/lafilefixer-0.5. +# rewrite_lafile() takes the contents of an lafile as a string +# It then parses the dependency_libs and inherited_linker_flags +# entries. +# We insist on dependency_libs being present. inherited_linker_flags +# is optional. +# There are strict rules about the syntax imposed by libtool's libltdl. +# See 'parse_dotla_file' and 'trim' functions in libltdl/ltdl.c. +# Note that duplicated entries of dependency_libs and inherited_linker_flags +# are ignored by libtool (last one wins), but we treat it as error (like +# lafilefixer does). +# What it does: +# * Replaces all .la files with absolut paths in dependency_libs with +# corresponding -l* and -L* entries +# (/usr/lib64/libfoo.la -> -L/usr/lib64 -lfoo) +# * Moves various flags (see flag_re below) to inherited_linker_flags, +# if such an entry was present. +# * Reorders dependency_libs such that all -R* entries precede -L* entries +# and these precede all other entries. +# * Remove duplicated entries from dependency_libs +# * Takes care that no entry to inherited_linker_flags is added that is +# already there. +######################################################### + +#These regexes are used to parse the interesting entries in the la file +dep_libs_re = re.compile(b"dependency_libs='(?P<value>[^']*)'$") +inh_link_flags_re = re.compile(b"inherited_linker_flags='(?P<value>[^']*)'$") + +#regexes for replacing stuff in -L entries. +#replace 'X11R6/lib' and 'local/lib' with 'lib', no idea what's this about. +X11_local_sub = re.compile(b"X11R6/lib|local/lib") +#get rid of the '..' +pkgconfig_sub1 = re.compile(b"usr/lib[^/]*/pkgconfig/\.\./\.\.") +pkgconfig_sub2 = re.compile(b"(?P<usrlib>usr/lib[^/]*)/pkgconfig/\.\.") + +#detect flags that should go into inherited_linker_flags instead of dependency_libs +flag_re = re.compile(b"-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads") + +def _parse_lafile_contents(contents): + """ + Parses 'dependency_libs' and 'inherited_linker_flags' lines. + """ + + dep_libs = None + inh_link_flags = None + + for line in contents.split(b"\n"): + m = dep_libs_re.match(line) + if m: + if dep_libs is not None: + raise InvalidData("duplicated dependency_libs entry") + dep_libs = m.group("value") + continue + + m = inh_link_flags_re.match(line) + if m: + if inh_link_flags is not None: + raise InvalidData("duplicated inherited_linker_flags entry") + inh_link_flags = m.group("value") + continue + + return dep_libs, inh_link_flags + +def rewrite_lafile(contents): + """ + Given the contents of an .la file, parse and fix it. + This operates with strings of raw bytes (assumed to contain some ascii + characters), in order to avoid any potential character encoding issues. + Raises 'InvalidData' if the .la file is invalid. + @param contents: the contents of a libtool archive file + @type contents: bytes + @rtype: tuple + @returns: (True, fixed_contents) if something needed to be + fixed, (False, None) otherwise. + """ + #Parse the 'dependency_libs' and 'inherited_linker_flags' lines. + dep_libs, inh_link_flags = \ + _parse_lafile_contents(contents) + + if dep_libs is None: + raise InvalidData("missing or invalid dependency_libs") + + new_dep_libs = [] + new_inh_link_flags = [] + librpath = [] + libladir = [] + + if inh_link_flags is not None: + new_inh_link_flags = inh_link_flags.split() + + #Check entries in 'dependency_libs'. + for dep_libs_entry in dep_libs.split(): + if dep_libs_entry.startswith(b"-l"): + #-lfoo, keep it + if dep_libs_entry not in new_dep_libs: + new_dep_libs.append(dep_libs_entry) + + elif dep_libs_entry.endswith(b".la"): + #Two cases: + #1) /usr/lib64/libfoo.la, turn it into -lfoo and append -L/usr/lib64 to libladir + #2) libfoo.la, keep it + dir, file = _os.path.split(dep_libs_entry) + + if not dir or not file.startswith(b"lib"): + if dep_libs_entry not in new_dep_libs: + new_dep_libs.append(dep_libs_entry) + else: + #/usr/lib64/libfoo.la -> -lfoo + lib = b"-l" + file[3:-3] + if lib not in new_dep_libs: + new_dep_libs.append(lib) + #/usr/lib64/libfoo.la -> -L/usr/lib64 + ladir = b"-L" + dir + if ladir not in libladir: + libladir.append(ladir) + + elif dep_libs_entry.startswith(b"-L"): + #Do some replacement magic and store them in 'libladir'. + #This allows us to place all -L entries at the beginning + #of 'dependency_libs'. + ladir = dep_libs_entry + + ladir = X11_local_sub.sub(b"lib", ladir) + ladir = pkgconfig_sub1.sub(b"usr", ladir) + ladir = pkgconfig_sub2.sub(b"\g<usrlib>", ladir) + + if ladir not in libladir: + libladir.append(ladir) + + elif dep_libs_entry.startswith(b"-R"): + if dep_libs_entry not in librpath: + librpath.append(dep_libs_entry) + + elif flag_re.match(dep_libs_entry): + #All this stuff goes into inh_link_flags, if the la file has such an entry. + #If it doesn't, they stay in 'dependency_libs'. + if inh_link_flags is not None: + if dep_libs_entry not in new_inh_link_flags: + new_inh_link_flags.append(dep_libs_entry) + else: + if dep_libs_entry not in new_dep_libs: + new_dep_libs.append(dep_libs_entry) + + else: + raise InvalidData("Error: Unexpected entry '%s' in 'dependency_libs'" \ + % _unicode_decode(dep_libs_entry)) + + #What should 'dependency_libs' and 'inherited_linker_flags' look like? + expected_dep_libs = b"" + for x in (librpath, libladir, new_dep_libs): + if x: + expected_dep_libs += b" " + b" ".join(x) + + expected_inh_link_flags = b"" + if new_inh_link_flags: + expected_inh_link_flags += b" " + b" ".join(new_inh_link_flags) + + #Don't touch the file if we don't need to, otherwise put the expected values into + #'contents' and write it into the la file. + + changed = False + if dep_libs != expected_dep_libs: + contents = contents.replace(b"dependency_libs='" + dep_libs + b"'", \ + b"dependency_libs='" + expected_dep_libs + b"'") + changed = True + + if inh_link_flags is not None and expected_inh_link_flags != inh_link_flags: + contents = contents.replace(b"inherited_linker_flags='" + inh_link_flags + b"'", \ + b"inherited_linker_flags='" + expected_inh_link_flags + b"'") + changed = True + + if changed: + return True, contents + else: + return False, None |