Tristan Matthews | 0a329cc | 2013-07-17 13:20:14 -0400 | [diff] [blame] | 1 | import sys |
| 2 | import os |
| 3 | |
| 4 | REMOVE_THESE = ["-I/usr/include", "-I/usr/include/", "-L/usr/lib", "-L/usr/lib/"] |
| 5 | |
| 6 | class Pkg: |
| 7 | def __init__(self, pkg_name): |
| 8 | self.name = pkg_name |
| 9 | self.priority = 0 |
| 10 | self.vars = {} |
| 11 | |
| 12 | def parse(self, pkg_config_path): |
| 13 | f = None |
| 14 | for pkg_path in pkg_config_path.split(':'): |
| 15 | if pkg_path[-1] != '/': |
| 16 | pkg_path += '/' |
| 17 | fname = pkg_path + self.name + '.pc' |
| 18 | try: |
| 19 | f = open(fname, "r") |
| 20 | break |
| 21 | except: |
| 22 | continue |
| 23 | if not f: |
| 24 | #sys.stderr.write("pkgconfig.py: unable to find %s.pc in %s\n" % (self.name, pkg_config_path)) |
| 25 | return False |
| 26 | |
| 27 | for line in f.readlines(): |
| 28 | line = line.strip() |
| 29 | if not line: |
| 30 | continue |
| 31 | if line[0]=='#': |
| 32 | continue |
| 33 | pos1 = line.find('=') |
| 34 | pos2 = line.find(':') |
| 35 | if pos1 > 0 and (pos1 < pos2 or pos2 < 0): |
| 36 | pos = pos1 |
| 37 | elif pos2 > 0 and (pos2 < pos1 or pos1 < 0): |
| 38 | pos = pos2 |
| 39 | else: |
| 40 | continue |
| 41 | name = line[:pos].lower() |
| 42 | value = line[pos+1:] |
| 43 | self.vars[name] = value |
| 44 | f.close() |
| 45 | |
| 46 | for name in self.vars.keys(): |
| 47 | value = self.vars[name] |
| 48 | while True: |
| 49 | pos1 = value.find("${") |
| 50 | if pos1 < 0: |
| 51 | break |
| 52 | pos2 = value.find("}") |
| 53 | if pos2 < 0: |
| 54 | break |
| 55 | value = value.replace(value[pos1:pos2+1], self.vars[value[pos1+2:pos2]]) |
| 56 | self.vars[name] = value |
| 57 | return True |
| 58 | |
| 59 | def requires(self): |
| 60 | if not 'requires' in self.vars: |
| 61 | return [] |
| 62 | deps = [] |
| 63 | req_list = self.vars['requires'] |
| 64 | for req_item in req_list.split(','): |
| 65 | req_item = req_item.strip() |
| 66 | for i in range(len(req_item)): |
| 67 | if "=<>".find(req_item[i]) >= 0: |
| 68 | deps.append(req_item[:i].strip()) |
| 69 | break |
| 70 | return deps |
| 71 | |
| 72 | def libs(self): |
| 73 | if not 'libs' in self.vars: |
| 74 | return [] |
| 75 | return self.vars['libs'].split(' ') |
| 76 | |
| 77 | def cflags(self): |
| 78 | if not 'cflags' in self.vars: |
| 79 | return [] |
| 80 | return self.vars['cflags'].split(' ') |
| 81 | |
| 82 | |
| 83 | def calculate_pkg_priority(pkg, pkg_dict, loop_cnt): |
| 84 | if loop_cnt > 10: |
| 85 | sys.stderr.write("Circular dependency with pkg %s\n" % (pkg)) |
| 86 | return 0 |
| 87 | reqs = pkg.requires() |
| 88 | prio = 1 |
| 89 | for req in reqs: |
| 90 | if not req in pkg_dict: |
| 91 | continue |
| 92 | req_pkg = pkg_dict[req] |
| 93 | prio += calculate_pkg_priority(req_pkg, pkg_dict, loop_cnt+1) |
| 94 | return prio |
| 95 | |
| 96 | if __name__ == "__main__": |
| 97 | pkg_names = [] |
| 98 | pkg_dict = {} |
| 99 | commands = [] |
| 100 | exist_check = False |
| 101 | |
| 102 | for i in range(1,len(sys.argv)): |
| 103 | if sys.argv[i][0] == '-': |
| 104 | cmd = sys.argv[i] |
| 105 | commands.append(cmd) |
| 106 | if cmd=='--exists': |
| 107 | exist_check = True |
| 108 | elif cmd=="--help": |
| 109 | print "This is not very helpful, is it" |
| 110 | sys.exit(0) |
| 111 | elif cmd=="--version": |
| 112 | print "0.1" |
| 113 | sys.exit(0) |
| 114 | else: |
| 115 | pkg_names.append(sys.argv[i]) |
| 116 | |
| 117 | # Fix search path |
| 118 | PKG_CONFIG_PATH = os.getenv("PKG_CONFIG_PATH", "").strip() |
| 119 | if not PKG_CONFIG_PATH: |
| 120 | PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:/usr/lib/pkgconfig" |
| 121 | PKG_CONFIG_PATH = PKG_CONFIG_PATH.replace(";", ":") |
| 122 | |
| 123 | # Parse files |
| 124 | for pkg_name in pkg_names: |
| 125 | pkg = Pkg(pkg_name) |
| 126 | if not pkg.parse(PKG_CONFIG_PATH): |
| 127 | sys.exit(1) |
| 128 | pkg_dict[pkg_name] = pkg |
| 129 | |
| 130 | if exist_check: |
| 131 | sys.exit(0) |
| 132 | |
| 133 | # Calculate priority based on dependency |
| 134 | for pkg_name in pkg_dict.keys(): |
| 135 | pkg = pkg_dict[pkg_name] |
| 136 | pkg.priority = calculate_pkg_priority(pkg, pkg_dict, 1) |
| 137 | |
| 138 | # Sort package based on dependency |
| 139 | pkg_names = sorted(pkg_names, key=lambda pkg_name: pkg_dict[pkg_name].priority, reverse=True) |
| 140 | |
| 141 | # Get the options |
| 142 | opts = [] |
| 143 | for cmd in commands: |
| 144 | if cmd=='--libs': |
| 145 | for pkg_name in pkg_names: |
| 146 | libs = pkg_dict[pkg_name].libs() |
| 147 | for lib in libs: |
| 148 | opts.append(lib) |
| 149 | if lib[:2]=="-l": |
| 150 | break |
| 151 | for pkg_name in pkg_names: |
| 152 | opts += pkg_dict[pkg_name].libs() |
| 153 | elif cmd=='--cflags': |
| 154 | for pkg_name in pkg_names: |
| 155 | opts += pkg_dict[pkg_name].cflags() |
| 156 | elif cmd[0]=='-': |
| 157 | sys.stderr.write("pkgconfig.py: I don't know how to handle " + sys.argv[i] + "\n") |
| 158 | |
| 159 | filtered_opts = [] |
| 160 | for opt in opts: |
| 161 | opt = opt.strip() |
| 162 | if not opt: |
| 163 | continue |
| 164 | if REMOVE_THESE.count(opt) != 0: |
| 165 | continue |
| 166 | if opt != '-framework' and opt != '--framework' and filtered_opts.count(opt) != 0: |
| 167 | if len(filtered_opts) and (filtered_opts[-1] == '-framework' or filtered_opts[-1] == '--framework'): |
| 168 | filtered_opts.pop() |
| 169 | continue |
| 170 | filtered_opts.append(opt) |
| 171 | |
| 172 | print ' '.join(filtered_opts) |
| 173 | |