def _parse_cflags(self, value, global_variables): flags = shlex.split(value, posix=False) for flag in flags: if flag.startswith('-I'): if flag[2:] not in \ Options().get_option('forbidden_cflags'): # Prepend pc_sysrootdir if necessary pc_sysrootdir = global_variables['pc_sysrootdir'] if pc_sysrootdir: # Strip the leading slashes from the flag path # because os.path.join() will ignore # pc_sysrootdir if it thinks the flag is an # absolute path include_dir = join(pc_sysrootdir, flag[2:].strip().lstrip('/')) else: include_dir = flag[2:].strip() if Options().get_option('full_compatibility') and \ include_dir: # Drop everything after the first space when trying # to be fully compatible (sucky behaviour on Win32). include_dir = include_dir.split()[0] if sys.platform == 'win32': if Options().get_option('normalise_paths'): include_dir = normpath(include_dir) else: include_dir = include_dir.replace('\\', '/') self.properties['include_dirs'].append(include_dir) else: self.properties['other_cflags'].append(flag.strip())
def search_for_pcfile(self, pkgname): """Search for one or more pkg-config files matching the given package name. If a matching pkg-config file cannot be found, an empty list will be returned. The dictionary of known packages is stored in _known_pkgs and is initialised by calling init_search_dirs(). """ ErrorPrinter().debug_print('Looking for files matching %s', (pkgname)) if Options().get_option('prefer_uninstalled'): if pkgname + '-uninstalled' in self._known_pkgs: # Prefer uninstalled version of a package ErrorPrinter().debug_print('Using uninstalled package %s', (self._known_pkgs[pkgname + '-uninstalled'])) return self._known_pkgs[pkgname + '-uninstalled'] elif Options().get_option('uninstalled_only'): ErrorPrinter().debug_print('Uninstalled only, no suitable package.') return [] if pkgname in self._known_pkgs: ErrorPrinter().debug_print('Using any package: %s', (self._known_pkgs[pkgname])) return self._known_pkgs[pkgname] else: ErrorPrinter().debug_print('No suitable package found') return []
def _parse_cflags(self, value): flags = shlex.split(value, posix=False) for flag in flags: if flag.startswith('-I'): if flag[2:] not in \ Options().get_option('forbidden_cflags'): # Prepend pc_sysrootdir if necessary pc_sysrootdir = Options().get_option('pc_sysrootdir') if pc_sysrootdir: include_dir = join(pc_sysrootdir, flag[2:].strip()) else: include_dir = flag[2:].strip() if Options().get_option('full_compatibility') and \ include_dir: # Drop everything after the first space when trying # to be fully compatible (sucky behaviour on Win32). include_dir = include_dir.split()[0] if sys.platform == 'win32': if Options().get_option('normalise_paths'): include_dir = normpath(include_dir) else: include_dir = include_dir.replace('\\', '/') self.properties['include_dirs'].append(include_dir) else: self.properties['other_cflags'].append(flag.strip())
def debug_print(self, line, args=None): if not Options().get_option('debug'): return if hasattr(self, 'vars'): for var in self.vars: line = line.replace('%(' + var + ')', self.vars[var]) if args is not None: line = line % args Options().get_option('error_dest').write(line + '\n')
def _process_props(self, global_variables): # Processing of file data props = self.raw_props # May need to reset the prefix variable if sys.platform == 'win32' and \ not Options().get_option('dont_define_prefix'): # Use the location of the .pc file to guess a suitable value for # the prefix variable. Start by checking if the absolute .pc # location ends with '\lib\pkgconfig'. abs_loc = dirname(abspath(self.filename)) if Options().get_option('normalise_paths'): abs_loc = normpath(abs_loc) else: # If not normalising paths, then all paths should be in / # format for consistency abs_loc = abs_loc.replace('\\', '/') if abs_loc.endswith('\\lib\\pkgconfig'): self.variables[Options().get_option('prefix_variable')] = \ abs_loc.rstrip('\\lib\\pkgconfig') ErrorPrinter().debug_print('Replaced {0} with \ {1}'.format(Options().get_option('prefix_variable'), self.variables[Options().get_option('prefix_variable')])) # Perform substitutions for key in props: props[key] = substitute(props[key], self.variables, global_variables) # Parse the data self.properties = deepcopy(empty_processed_props) self.properties['name'] = props['name'] if props['description']: self.properties['description'] = props['description'] if props['version']: try: self.properties['version'] = Version(props['version']) except BadVersionFormatError as e: raise BadVersionFormatError(e.versionstring, props['name']) self.properties['requires'] = \ parse_package_spec_list(props['requires']) self.properties['requires.private'] = \ parse_package_spec_list(props['requires.private']) + \ self.properties['requires'] self.properties['conflicts'] = \ parse_package_spec_list(props['conflicts']) self._parse_cflags(props['cflags'], global_variables) self._parse_libs(props['libs'], global_variables) self._parse_libs(props['libs.private'], global_variables, dest='private.')
def _can_open_file(self, filename): try: result = open(filename, 'r') except IOError as e: ErrorPrinter().debug_print('Could not open {0}'.format(filename)) search_string = Options().get_option('search_string').split() if (not search_string and \ Options().get_option('command') == 'list-all') or \ True in [p.startswith(split(filename)[-1].split('.')[0]) \ for p in search_string]: ErrorPrinter().verbose_error( "Failed to open '{0}': {1}".format(filename, e.strerror)) return False return True
def get_all_lib_flags(self): result = [] for name, pkg in self.packages: result += pkg.properties['otherlibs'] if Options().get_option('private_libs'): result += pkg.properties['private.otherlibs'] result += [self.lib_path_flag + path \ for path in pkg.properties['libpaths']] if Options().get_option('private_libs'): result += [self.lib_path_flag + path \ for path in pkg.properties['private.libpaths']] result += [self.lib_flag + lib for lib in pkg.properties['libs']] if Options().get_option('private_libs'): result += [self.lib_flag + lib \ for lib in pkg.properties['private.libs']] return self._format_list(_filter_duplicates(result))
def get_other_l_flags(self): result = [] for name, pkg in self.packages: result += pkg.properties['otherlibs'] if Options().get_option('private_libs'): result += pkg.properties['private.otherlibs'] return self._format_list(_filter_duplicates(result))
def _init_search_dirs(self): # Append dirs in PKG_CONFIG_PATH if "config_path" in self.globals and self.globals["config_path"]: for d in self.globals["config_path"]: if not d or not isdir(d): continue self._append_packages(d) # Append dirs in PKG_CONFIG_LIBDIR if "config_libdir" in self.globals and self.globals["config_libdir"]: for d in self.globals["config_libdir"]: if not d or not isdir(d): continue self._append_packages(d) if sys.platform == 'win32': key_path = 'Software\\pkg-config\\PKG_CONFIG_PATH' for root in ((_winreg.HKEY_CURRENT_USER, 'HKEY_CURRENT_USER'), (_winreg.HKEY_LOCAL_MACHINE, 'HKEY_LOCAL_MACHINE')): try: key = _winreg.OpenKey(root[0], key_path) except WindowsError as e: ErrorPrinter().debug_print('Failed to add paths from \ {0}\\{1}: {2}'.format(root[1], key_path, e)) continue try: num_subkeys, num_vals, modified = _winreg.QueryInfoKey(key) for ii in range(num_vals): name, val, type = _winreg.EnumValue(key, ii) if type == _winreg.REG_SZ and isdir(val): self._append_packages(val) except WindowsError as e: ErrorPrinter().debug_print('Failed to add paths from \ {0}\\{1}: {2}'.format(root[1], key_path, e)) finally: _winreg.CloseKey(key) # Default path: If a hard-coded path has been set, use that (excluding # paths that don't exist) if "prefix" in self.globals: prefix = self.globals["prefix"] else: prefix = sys.prefix if pc_path: for d in pc_path.split(self._split_char()): if d and isdir(d): self._append_packages(d) # Default path: Else append prefix/lib/pkgconfig, prefix/share/pkgconfig else: if Options().get_option('is_64bit'): suffix = '64' else: suffix = '' dirs2check = (join(prefix, 'lib' + suffix), join(prefix, 'lib', str(thisArchTriple)), join(prefix, 'share'), join(prefix, "lib")) for d in dirs2check: d = join(d, "pkgconfig") if isdir(d): self._append_packages(d)
def _parse_libs(self, value, global_variables, dest=''): # Parse lib flags libs = shlex.split(value) skip_next = False for ii, lib in enumerate(libs): if skip_next: # Possibly skip an entry that was eaten by a -framework skip_next = False continue if lib.startswith('-l'): self.properties[dest + 'libs'].append(lib[2:].strip() + \ self.lib_suffix) elif lib.startswith('-L'): if lib[2:] not in \ Options().get_option('forbidden_libdirs'): # Prepend pc_sysrootdir if necessary pc_sysrootdir = global_variables['pc_sysrootdir'] if pc_sysrootdir: # Strip the leading slashes from the flag path # because os.path.join() will ignore # pc_sysrootdir if it thinks the flag is an # absolute path libpath = join(pc_sysrootdir, lib[2:].strip().lstrip('/')) else: libpath = lib[2:].strip() if Options().get_option('full_compatibility'): # Drop everything after the first space when trying # to be fully compatible (sucky behaviour on Win32). libpath = libpath.split()[0] if sys.platform == 'win32': if Options().get_option('normalise_paths'): libpath = normpath(libpath) else: libpath = libpath.replace('\\', '/') self.properties[dest + 'libpaths'].append(libpath) elif lib.startswith('-framework'): self.properties[dest + 'otherlibs']. \ append(libs[ii + 1].strip() + self.lib_suffix) skip_next = True else: self.properties[dest + 'otherlibs'].append(lib.strip() + \ self.lib_suffix)
def __init__(self, globals): # Different platforms may use different flags and extensions if sys.platform == 'win32' and Options().get_option('use_msvc_syntax'): self.lib_path_flag = '/libpath:' self.lib_flag = '' else: self.lib_path_flag = '-L' self.lib_flag = '-l' # Can't use a dictionary for the loaded packages list because the # ordering must be maintained (when Python 3.1 is standard, switch to # collections.OrderedDict). self.packages = [] self.searched_packages = [] self.searcher = PkgSearcher(globals) self.globals = globals
def __init__(self, filename=None, globals={}): # Different platforms may use different flags and extensions if sys.platform == 'win32' and Options().get_option('use_msvc_syntax'): self.lib_suffix = '.lib' else: self.lib_suffix = '' # Parse a file if one was given if filename is not None: self.load_from_pc_file(filename, globals) if filename.endswith('-uninstalled'): self.uninstalled = True else: self.uninstalled = False else: self.clear()
def verbose_error(self, line, args=None): if not Options().get_option('print_errors'): return self.error(line, args)
def main(argv): parser = setup_option_parser() try: options, args = parser.parse_args() except OptionError as e: print('OptionError: ' + str (e)) sys.exit(1) if options.realversion: print('{0} (Equivalent to {1}'.format(PYKG_CONFIG_VERSION, CORRESPONDING_VERSION)) sys.exit(0) global_variables = {} zip_name = 'python{0}{1}.zip'.format(sys.version_info[0], sys.version_info[1]) for path in sys.path: if path.endswith('64/' + zip_name): Options().set_option('is_64bit', True) break if getenv('PKG_CONFIG_SYSROOT_DIR'): global_variables['pc_sysrootdir'] = getenv('PKG_CONFIG_SYSROOT_DIR') if getenv('PKG_CONFIG_TOP_BUILD_DIR'): global_variables['pc_topbuilddir'] = getenv('PKG_CONFIG_TOP_BUILD_DIR') if getenv('PKG_CONFIG_DISABLE_UNINSTALLED'): Options().set_option('prefer_uninstalled', False) if getenv('PKG_CONFIG_ALLOW_SYSTEM_LIBS'): Options().set_option('forbidden_libdirs', []) else: if Options().get_option('is_64bit'): Options().set_option('forbidden_libdirs', ['/usr/lib64']) else: Options().set_option('forbidden_libdirs', ['/usr/lib']) if getenv('PKG_CONFIG_ALLOW_SYSTEM_CFLAGS'): Options().set_option('forbidden_cflags', []) else: forbidden = [] if sys.platform != 'win32': forbidden.append('/usr/include') if getenv('C_INCLUDE_PATH'): forbidden.append(getenv('C_INCLUDE_PATH')) if getenv('CPLUS_INCLUDE_PATH'): forbidden.append(getenv('CPLUS_INCLUDE_PATH')) Options().set_option('forbidden_cflags', forbidden) if options.full_compatibility: Options().set_option('full_compatibility', True) else: Options().set_option('full_compatibility', False) if options.atleast_pkgconfig_version: other_version = Version(options.atleast_pkgconfig_version) if other_version > get_pkg_config_version(): sys.exit(1) else: sys.exit(0) if options.static: Options().set_option('private_libs', True) if options.short_errors: Options().set_option('short_errors', True) if options.define_variable: for var_def in options.define_variable: sub_strings = var_def.split('=') if len(sub_strings) != 2: print('Bad argument format for define-variable: {1}'.format(var_def)) sys.exit(1) global_variables[sub_strings[0]] = sub_strings[1] if options.debug: Options().set_option('debug', True) if options.errors_to_stdout: Options().set_option('error_dest', sys.stdout) if sys.platform == 'win32': if options.dont_define_prefix: Options().set_option('dont_define_prefix', True) else: Options().set_option('dont_define_prefix', False) if options.prefix_variable: Options().set_option('prefix_variable', options.prefix_variable) if options.msvc_syntax: Options().set_option('use_msvc_syntax', True) else: Options().set_option('use_msvc_syntax', False) if options.normalise_paths: Options().set_option('normalise_paths', True) else: Options().set_option('normalise_paths', False) if options.modversion or options.libs or options.libs_only_l or \ options.libs_only_big_l or options.libs_only_other or \ options.cflags or options.cflags_only_big_i or \ options.cflags_only_other or options.list_all: if options.silence_errors: Options().set_option('print_errors', False) else: Options().set_option('print_errors', True) else: if options.print_errors: Options().set_option('print_errors', True) else: Options().set_option('print_errors', False) if options.list_all: Options().set_option('command', 'list-all') try: result = PkgCfgResult(global_variables) all_packages, errors = result.known_packages_list() except: ErrorPrinter().error('Exception searching for packages:') traceback.print_exc() sys.exit(1) if all_packages: max_width = max([(len(p), p) for p, n, d in all_packages]) for package, name, description in all_packages: print('{0:{3}}{1} - {2}'.format(package, name, description, max_width[0] + 1)) for e in errors: ErrorPrinter().error(e) sys.exit(0) try: Options().set_option('command', 'search') search = ' '.join(args) Options().set_option('search_string', search) result = PkgCfgResult(global_variables) result.find_packages(search, True) except NoOpenableFilesError as e: ErrorPrinter().verbose_error(str(e)) sys.exit(1) except PackageNotFoundError as e: if not Options().get_option('short_errors'): ErrorPrinter().verbose_error('''Package {0} was not found in the \ pkg-config search path. Perhaps you should add the directory containing `{0}.pc' to the PKG_CONFIG_PATH environment variable'''.format(e.pkgname)) ErrorPrinter().verbose_error(str(e)) sys.exit(1) except NoPackagesSpecifiedError: Options().get_option('error_dest').write( 'Must specify package names on the command line\n') sys.exit(1) except UndefinedVarError as e: ErrorPrinter().error("Variable '{0}' not defined in '{1}'".format( e.variable, e.pkgfile)) sys.exit(1) except: print('Exception searching for packages') traceback.print_exc() sys.exit(1) if options.dump_package: result.dump_package() sys.exit(0) if options.exists: # Even if the packages don't meet the requirements, they exist, which # is good enough for the exists option. sys.exit(0) if options.uninstalled: # Check if any packages loaded (both searched-for and dependencies) # are uninstalled. if result.have_uninstalled(): sys.exit(0) sys.exit(1) if options.modversion: for l in result.get_searched_pkgs_versions(): print(l) found_version = \ result.get_package_version(result.get_searched_pkg_list()[0].name) if options.atleast_version: if found_version < Version(options.atleast_version): sys.exit(1) sys.exit(0) if options.exact_version: if found_version != Version(options.exact_version): sys.exit(1) sys.exit(0) if options.max_version: if found_version > Version(options.max_version): sys.exit(1) sys.exit(0) if options.variable: value = result.get_variable_value(options.variable) if value == None: print('') else: print(value) if options.cflags_only_big_i: print(result.get_big_i_flags()) if options.cflags_only_other: print(result.get_other_i_flags()) if options.cflags: print(result.get_cflags()) if options.libs_only_l: print(result.get_l_flags()) if options.libs_only_big_l: print(result.get_big_l_flags()) if options.libs_only_other: print(result.get_other_l_flags()) if options.libs: print(result.get_all_lib_flags())