pkgconfig.py 4.1 KB

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