| import sys |
| import os |
| |
| REMOVE_THESE = ["-I/usr/include", "-I/usr/include/", "-L/usr/lib", "-L/usr/lib/"] |
| |
| class Pkg: |
| def __init__(self, pkg_name): |
| self.name = pkg_name |
| self.priority = 0 |
| self.vars = {} |
| |
| def parse(self, pkg_config_path): |
| f = None |
| for pkg_path in pkg_config_path.split(':'): |
| if pkg_path[-1] != '/': |
| pkg_path += '/' |
| fname = pkg_path + self.name + '.pc' |
| try: |
| f = open(fname, "r") |
| break |
| except: |
| continue |
| if not f: |
| #sys.stderr.write("pkgconfig.py: unable to find %s.pc in %s\n" % (self.name, pkg_config_path)) |
| return False |
| |
| for line in f.readlines(): |
| line = line.strip() |
| if not line: |
| continue |
| if line[0]=='#': |
| continue |
| pos1 = line.find('=') |
| pos2 = line.find(':') |
| if pos1 > 0 and (pos1 < pos2 or pos2 < 0): |
| pos = pos1 |
| elif pos2 > 0 and (pos2 < pos1 or pos1 < 0): |
| pos = pos2 |
| else: |
| continue |
| name = line[:pos].lower() |
| value = line[pos+1:] |
| self.vars[name] = value |
| f.close() |
| |
| for name in self.vars.keys(): |
| value = self.vars[name] |
| while True: |
| pos1 = value.find("${") |
| if pos1 < 0: |
| break |
| pos2 = value.find("}") |
| if pos2 < 0: |
| break |
| value = value.replace(value[pos1:pos2+1], self.vars[value[pos1+2:pos2]]) |
| self.vars[name] = value |
| return True |
| |
| def requires(self): |
| if not 'requires' in self.vars: |
| return [] |
| deps = [] |
| req_list = self.vars['requires'] |
| for req_item in req_list.split(','): |
| req_item = req_item.strip() |
| for i in range(len(req_item)): |
| if "=<>".find(req_item[i]) >= 0: |
| deps.append(req_item[:i].strip()) |
| break |
| return deps |
| |
| def libs(self): |
| if not 'libs' in self.vars: |
| return [] |
| return self.vars['libs'].split(' ') |
| |
| def cflags(self): |
| if not 'cflags' in self.vars: |
| return [] |
| return self.vars['cflags'].split(' ') |
| |
| |
| def calculate_pkg_priority(pkg, pkg_dict, loop_cnt): |
| if loop_cnt > 10: |
| sys.stderr.write("Circular dependency with pkg %s\n" % (pkg)) |
| return 0 |
| reqs = pkg.requires() |
| prio = 1 |
| for req in reqs: |
| if not req in pkg_dict: |
| continue |
| req_pkg = pkg_dict[req] |
| prio += calculate_pkg_priority(req_pkg, pkg_dict, loop_cnt+1) |
| return prio |
| |
| if __name__ == "__main__": |
| pkg_names = [] |
| pkg_dict = {} |
| commands = [] |
| exist_check = False |
| |
| for i in range(1,len(sys.argv)): |
| if sys.argv[i][0] == '-': |
| cmd = sys.argv[i] |
| commands.append(cmd) |
| if cmd=='--exists': |
| exist_check = True |
| elif cmd=="--help": |
| print "This is not very helpful, is it" |
| sys.exit(0) |
| elif cmd=="--version": |
| print "0.1" |
| sys.exit(0) |
| else: |
| pkg_names.append(sys.argv[i]) |
| |
| # Fix search path |
| PKG_CONFIG_PATH = os.getenv("PKG_CONFIG_PATH", "").strip() |
| if not PKG_CONFIG_PATH: |
| PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:/usr/lib/pkgconfig" |
| PKG_CONFIG_PATH = PKG_CONFIG_PATH.replace(";", ":") |
| |
| # Parse files |
| for pkg_name in pkg_names: |
| pkg = Pkg(pkg_name) |
| if not pkg.parse(PKG_CONFIG_PATH): |
| sys.exit(1) |
| pkg_dict[pkg_name] = pkg |
| |
| if exist_check: |
| sys.exit(0) |
| |
| # Calculate priority based on dependency |
| for pkg_name in pkg_dict.keys(): |
| pkg = pkg_dict[pkg_name] |
| pkg.priority = calculate_pkg_priority(pkg, pkg_dict, 1) |
| |
| # Sort package based on dependency |
| pkg_names = sorted(pkg_names, key=lambda pkg_name: pkg_dict[pkg_name].priority, reverse=True) |
| |
| # Get the options |
| opts = [] |
| for cmd in commands: |
| if cmd=='--libs': |
| for pkg_name in pkg_names: |
| libs = pkg_dict[pkg_name].libs() |
| for lib in libs: |
| opts.append(lib) |
| if lib[:2]=="-l": |
| break |
| for pkg_name in pkg_names: |
| opts += pkg_dict[pkg_name].libs() |
| elif cmd=='--cflags': |
| for pkg_name in pkg_names: |
| opts += pkg_dict[pkg_name].cflags() |
| elif cmd[0]=='-': |
| sys.stderr.write("pkgconfig.py: I don't know how to handle " + sys.argv[i] + "\n") |
| |
| filtered_opts = [] |
| for opt in opts: |
| opt = opt.strip() |
| if not opt: |
| continue |
| if REMOVE_THESE.count(opt) != 0: |
| continue |
| if opt != '-framework' and opt != '--framework' and filtered_opts.count(opt) != 0: |
| if len(filtered_opts) and (filtered_opts[-1] == '-framework' or filtered_opts[-1] == '--framework'): |
| filtered_opts.pop() |
| continue |
| filtered_opts.append(opt) |
| |
| print ' '.join(filtered_opts) |
| |