Beispiel #1
0
 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())
Beispiel #2
0
    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 []
Beispiel #3
0
 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())
Beispiel #4
0
 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')
Beispiel #5
0
    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.')
Beispiel #6
0
 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
Beispiel #7
0
 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))
Beispiel #8
0
 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))
Beispiel #9
0
    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)
Beispiel #10
0
 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)
Beispiel #11
0
 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
Beispiel #12
0
    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()
Beispiel #13
0
 def verbose_error(self, line, args=None):
     if not Options().get_option('print_errors'):
         return
     self.error(line, args)
Beispiel #14
0
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())