[vlc-commits] contrib: Workaround for absolute paths in pc files

Marvin Scholz git at videolan.org
Thu Oct 24 17:53:05 CEST 2019


vlc | branch: master | Marvin Scholz <epirat07 at gmail.com> | Thu Sep 19 18:18:49 2019 +0200| [4c942a2018997cba94005b42729ee9b57a0fc99f] | committer: Marvin Scholz

contrib: Workaround for absolute paths in pc files

Meson generates pc files with absolute paths to static libraries, while
this is completely fine, libtool can not deal with this and produces
broken build results in that case.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=4c942a2018997cba94005b42729ee9b57a0fc99f
---

 contrib/src/libplacebo/rules.mak    |   3 +
 contrib/src/pkg-rewrite-absolute.py | 141 ++++++++++++++++++++++++++++++++++++
 2 files changed, 144 insertions(+)

diff --git a/contrib/src/libplacebo/rules.mak b/contrib/src/libplacebo/rules.mak
index 9d4295e72c..1f34691824 100644
--- a/contrib/src/libplacebo/rules.mak
+++ b/contrib/src/libplacebo/rules.mak
@@ -36,4 +36,7 @@ libplacebo: $(PLACEBO_ARCHIVE) .sum-libplacebo
 	cd $< && cd build && ninja install
 # Work-around messon issue https://github.com/mesonbuild/meson/issues/4091
 	sed -i.orig -e 's/Libs: \(.*\) -L$${libdir} -lplacebo/Libs: -L$${libdir} -lplacebo \1/g' $(PREFIX)/lib/pkgconfig/libplacebo.pc
+# Work-around for full paths to static libraries, which libtool does not like
+# See https://github.com/mesonbuild/meson/issues/5479
+	(cd $(UNPACK_DIR) && $(SRC_BUILT)/pkg-rewrite-absolute.py -i "$(PREFIX)/lib/pkgconfig/libplacebo.pc")
 	touch $@
diff --git a/contrib/src/pkg-rewrite-absolute.py b/contrib/src/pkg-rewrite-absolute.py
new file mode 100755
index 0000000000..7cab6c89d4
--- /dev/null
+++ b/contrib/src/pkg-rewrite-absolute.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python3
+import os, sys, argparse
+
+class PkgConfigFile():
+    """Representation of a pkg-config file (.pc)"""
+
+    pc_variables = {}
+    pc_variables_expanded = {}
+
+    pc_keywords = {}
+
+    def __init__(self, file):
+        for line in file:
+            self.parse_pc_line(line)
+
+    def parse_pc_line(self, line):
+        for i, c in enumerate(line):
+            if c is '=':
+                # This is a pkg-config variable line
+                key = line[:i].strip()
+                val = line[(i + 1):].strip()
+
+                # Add unexpanded version of variable
+                self.pc_variables.update({ key : val })
+
+                # Add expanded version of variable
+                self.pc_variables_expanded.update({ key : self.expand_pc_vars(val) })
+            elif c is ':':
+                # This is a pkg-config keyword line
+                key = line[:i].strip()
+                val = line[(i + 1):].strip()
+
+                self.pc_keywords.update({ key : val })
+
+    def expand_pc_vars(self, line):
+        for key, val in self.pc_variables_expanded.items():
+            line = line.replace('${' + key + '}', val)
+        return line
+
+    def get_variable(self, key, expand=True):
+        if expand:
+            return self.pc_variables_expanded.get(key, None)
+        else:
+            return self.pc_variables.get(key, None)
+
+    def get_keyword(self, key, expand=True):
+        keyword = self.pc_keywords.get(key, None)
+        if expand and keyword != None:
+            return self.expand_pc_vars(keyword)
+        else:
+            return keyword
+
+    def set_keyword(self, key, value):
+        self.pc_keywords.update({ key : value })
+
+    def write(self, file):
+        pc_contents = ''
+        # Print variables
+        for key, val in self.pc_variables.items():
+            pc_contents += key + '=' + val + '\n'
+        pc_contents += '\n'
+        # Print keywords
+        for key, val in self.pc_keywords.items():
+            pc_contents += key + ': ' + val + '\n'
+
+        file.write(pc_contents)
+
+def remove_str_fix(text, prefix, suffix):
+    start = len(prefix) if text.startswith(prefix) else 0
+    end_offset = len(suffix) if text.endswith(suffix) else 0
+    end = len(text) - end_offset
+    return text[start:end]
+
+def rewrite_abs_to_rel(pc_file):
+    linker_args = pc_file.get_keyword('Libs', expand=False)
+    if linker_args is None:
+        raise KeyError('No "Libs" keyword in input .pc file found!')
+    linker_args_list = linker_args.split()
+
+    # Replace absolute library paths with relative ones
+    # i.e. /foo/bar/baz.a to -L/foo/bar -lbaz
+    lib_paths = []
+    out_args = []
+    for arg in linker_args_list:
+        if arg.startswith('-L'):
+            path = arg[2:]
+            path = pc_file.expand_pc_vars(path)
+            lib_paths.append(path)
+
+        # Filter all absolute static library paths
+        if arg.startswith('/') and arg.endswith('.a'):
+            lib_path = os.path.dirname(arg)
+            lib_filename = os.path.basename(arg)
+            # Remove lib prefix and .a suffix
+            lib_name = remove_str_fix(lib_filename, 'lib', '.a')
+            if lib_path not in lib_paths:
+                out_args.append('-L' + lib_path)
+                lib_paths.append(lib_path)
+            out_args.append('-l' + lib_name)
+        else:
+            out_args.append(arg)
+
+    linker_args = ' '.join(out_args)
+    pc_file.set_keyword('Libs', linker_args)
+
+# Main function
+# Do argument parsing and other stuff needed
+# for CLI usage here.
+def main():
+    if not sys.version_info >= (3, 4):
+        print("Python version 3.4 or higher required!", file=sys.stderr)
+        exit(1)
+
+    # Create main parser
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-i', '--input', required=True)
+    parser.add_argument('-o', '--output')
+
+    args = parser.parse_args()
+
+    # Default to input file (in-place editing) if no output file is given
+    args.output = args.output or args.input
+
+    # Read .pc from input file
+    input_file = sys.stdin if args.input is '-' else open(args.input, 'r')
+    pc_file = PkgConfigFile(input_file)
+    if input_file is not sys.stdin:
+        input_file.close()
+
+    rewrite_abs_to_rel(pc_file)
+
+    # Write output
+    output_file = sys.stdout if args.output is '-' else open(args.output, 'w')
+    pc_file.write(output_file)
+    if output_file is not sys.stdout:
+        output_file.close()
+
+    return 0
+
+if __name__ == "__main__":
+    exit(main())



More information about the vlc-commits mailing list