blob: 496e311b9e9f78f4ce9833d11ae1ce300d6e3c15 [file] [log] [blame]
Benny Prijonoeeebfab2012-04-23 13:46:21 +00001import sys
2import os
3
4REMOVE_THESE = ["-I/usr/include", "-I/usr/include/", "-L/usr/lib", "-L/usr/lib/"]
5
6class 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
83def 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
96if __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 filtered_opts.count(opt) != 0:
167 continue
168 filtered_opts.append(opt)
169
170 print ' '.join(filtered_opts)
171