def extract_cmake_deps(outlines, srctree, extravalues, cmakelistsfile=None):
        values = {}
        inherits = []

        if cmakelistsfile:
            srcfiles = [cmakelistsfile]
        else:
            srcfiles = RecipeHandler.checkfiles(srctree, ['CMakeLists.txt'])

        # Note that some of these are non-standard, but probably better to
        # be able to map them anyway if we see them
        cmake_pkgmap = {'alsa': 'alsa-lib',
                        'aspell': 'aspell',
                        'atk': 'atk',
                        'bison': 'bison-native',
                        'boost': 'boost',
                        'bzip2': 'bzip2',
                        'cairo': 'cairo',
                        'cups': 'cups',
                        'curl': 'curl',
                        'curses': 'ncurses',
                        'cvs': 'cvs',
                        'drm': 'libdrm',
                        'dbus': 'dbus',
                        'dbusglib': 'dbus-glib',
                        'egl': 'virtual/egl',
                        'expat': 'expat',
                        'flex': 'flex-native',
                        'fontconfig': 'fontconfig',
                        'freetype': 'freetype',
                        'gettext': '',
                        'git': '',
                        'gio': 'glib-2.0',
                        'giounix': 'glib-2.0',
                        'glew': 'glew',
                        'glib': 'glib-2.0',
                        'glib2': 'glib-2.0',
                        'glu': 'libglu',
                        'glut': 'freeglut',
                        'gobject': 'glib-2.0',
                        'gperf': 'gperf-native',
                        'gnutls': 'gnutls',
                        'gtk2': 'gtk+',
                        'gtk3': 'gtk+3',
                        'gtk': 'gtk+3',
                        'harfbuzz': 'harfbuzz',
                        'icu': 'icu',
                        'intl': 'virtual/libintl',
                        'jpeg': 'jpeg',
                        'libarchive': 'libarchive',
                        'libiconv': 'virtual/libiconv',
                        'liblzma': 'xz',
                        'libxml2': 'libxml2',
                        'libxslt': 'libxslt',
                        'opengl': 'virtual/libgl',
                        'openmp': '',
                        'openssl': 'openssl',
                        'pango': 'pango',
                        'perl': '',
                        'perllibs': '',
                        'pkgconfig': '',
                        'png': 'libpng',
                        'pthread': '',
                        'pythoninterp': '',
                        'pythonlibs': '',
                        'ruby': 'ruby-native',
                        'sdl': 'libsdl',
                        'sdl2': 'libsdl2',
                        'subversion': 'subversion-native',
                        'swig': 'swig-native',
                        'tcl': 'tcl-native',
                        'threads': '',
                        'tiff': 'tiff',
                        'wget': 'wget',
                        'x11': 'libx11',
                        'xcb': 'libxcb',
                        'xext': 'libxext',
                        'xfixes': 'libxfixes',
                        'zlib': 'zlib',
                        }

        pcdeps = []
        libdeps = []
        deps = []
        unmappedpkgs = []

        proj_re = re.compile('project\s*\(([^)]*)\)', re.IGNORECASE)
        pkgcm_re = re.compile('pkg_check_modules\s*\(\s*[a-zA-Z0-9-_]+\s*(REQUIRED)?\s+([^)\s]+)\s*\)', re.IGNORECASE)
        pkgsm_re = re.compile('pkg_search_module\s*\(\s*[a-zA-Z0-9-_]+\s*(REQUIRED)?((\s+[^)\s]+)+)\s*\)', re.IGNORECASE)
        findpackage_re = re.compile('find_package\s*\(\s*([a-zA-Z0-9-_]+)\s*.*', re.IGNORECASE)
        checklib_re = re.compile('check_library_exists\s*\(\s*([^\s)]+)\s*.*', re.IGNORECASE)
        include_re = re.compile('include\s*\(\s*([^)\s]*)\s*\)', re.IGNORECASE)
        subdir_re = re.compile('add_subdirectory\s*\(\s*([^)\s]*)\s*([^)\s]*)\s*\)', re.IGNORECASE)
        dep_re = re.compile('([^ ><=]+)( *[<>=]+ *[^ ><=]+)?')

        def interpret_value(value):
            return value.strip('"')

        def parse_cmake_file(fn, paths=None):
            searchpaths = (paths or []) + [os.path.dirname(fn)]
            logger.debug('Parsing file %s' % fn)
            with open(fn, 'r') as f:
                for line in f:
                    line = line.strip()
                    res = include_re.match(line)
                    if res:
                        includefn = bb.utils.which(':'.join(searchpaths), res.group(1))
                        if includefn:
                            parse_cmake_file(includefn, searchpaths)
                        else:
                            logger.debug('Unable to recurse into include file %s' % res.group(1))
                        continue
                    res = subdir_re.match(line)
                    if res:
                        subdirfn = os.path.join(os.path.dirname(fn), res.group(1), 'CMakeLists.txt')
                        if os.path.exists(subdirfn):
                            parse_cmake_file(subdirfn, searchpaths)
                        else:
                            logger.debug('Unable to recurse into subdirectory file %s' % subdirfn)
                        continue
                    res = proj_re.match(line)
                    if res:
                        extravalues['PN'] = interpret_value(res.group(1).split()[0])
                        continue
                    res = pkgcm_re.match(line)
                    if res:
                        res = dep_re.findall(res.group(2))
                        if res:
                            pcdeps.extend([interpret_value(x[0]) for x in res])
                        inherits.append('pkgconfig')
                        continue
                    res = pkgsm_re.match(line)
                    if res:
                        res = dep_re.findall(res.group(2))
                        if res:
                            # Note: appending a tuple here!
                            item = tuple((interpret_value(x[0]) for x in res))
                            if len(item) == 1:
                                item = item[0]
                            pcdeps.append(item)
                        inherits.append('pkgconfig')
                        continue
                    res = findpackage_re.match(line)
                    if res:
                        origpkg = res.group(1)
                        pkg = interpret_value(origpkg.lower())
                        if pkg == 'gettext':
                            inherits.append('gettext')
                        elif pkg == 'perl':
                            inherits.append('perlnative')
                        elif pkg == 'pkgconfig':
                            inherits.append('pkgconfig')
                        elif pkg == 'pythoninterp':
                            inherits.append('pythonnative')
                        elif pkg == 'pythonlibs':
                            inherits.append('python-dir')
                        else:
                            dep = cmake_pkgmap.get(pkg, None)
                            if dep:
                                deps.append(dep)
                            elif dep is None:
                                unmappedpkgs.append(origpkg)
                        continue
                    res = checklib_re.match(line)
                    if res:
                        lib = interpret_value(res.group(1))
                        if not lib.startswith('$'):
                            libdeps.append(lib)
                    if line.lower().startswith('useswig'):
                        deps.append('swig-native')
                        continue

        parse_cmake_file(srcfiles[0])

        if unmappedpkgs:
            outlines.append('# NOTE: unable to map the following CMake package dependencies: %s' % ' '.join(unmappedpkgs))

        RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data)

        if inherits:
            values['inherit'] = ' '.join(list(set(inherits)))

        return values
    def extract_autotools_deps(outlines, srctree, extravalues=None, acfile=None):
        import shlex

        values = {}
        inherits = []

        # FIXME this mapping is very thin
        progmap = {'flex': 'flex-native',
                'bison': 'bison-native',
                'm4': 'm4-native',
                'tar': 'tar-native',
                'ar': 'binutils-native'}
        progclassmap = {'gconftool-2': 'gconf',
                'pkg-config': 'pkgconfig'}

        pkg_re = re.compile('PKG_CHECK_MODULES\(\[?[a-zA-Z0-9_]*\]?, *\[?([^,\]]*)\]?[),].*')
        pkgce_re = re.compile('PKG_CHECK_EXISTS\(\[?([^,\]]*)\]?[),].*')
        lib_re = re.compile('AC_CHECK_LIB\(\[?([^,\]]*)\]?,.*')
        libx_re = re.compile('AX_CHECK_LIBRARY\(\[?[^,\]]*\]?, *\[?([^,\]]*)\]?, *\[?([a-zA-Z0-9-]*)\]?,.*')
        progs_re = re.compile('_PROGS?\(\[?[a-zA-Z0-9_]*\]?, \[?([^,\]]*)\]?[),].*')
        dep_re = re.compile('([^ ><=]+)( [<>=]+ [^ ><=]+)?')
        ac_init_re = re.compile('AC_INIT\(([^,]+), *([^,]+)[,)].*')
        am_init_re = re.compile('AM_INIT_AUTOMAKE\(([^,]+), *([^,]+)[,)].*')
        define_re = re.compile(' *(m4_)?define\(([^,]+), *([^,]+)\)')

        defines = {}
        def subst_defines(value):
            newvalue = value
            for define, defval in defines.iteritems():
                newvalue = newvalue.replace(define, defval)
            if newvalue != value:
                return subst_defines(newvalue)
            return value

        def process_value(value):
            value = value.replace('[', '').replace(']', '')
            if value.startswith('m4_esyscmd(') or value.startswith('m4_esyscmd_s('):
                cmd = subst_defines(value[value.index('(')+1:-1])
                try:
                    if '|' in cmd:
                        cmd = 'set -o pipefail; ' + cmd
                    stdout, _ = bb.process.run(cmd, cwd=srctree, shell=True)
                    ret = stdout.rstrip()
                except bb.process.ExecutionError as e:
                    ret = ''
            elif value.startswith('m4_'):
                return None
            ret = subst_defines(value)
            if ret:
                ret = ret.strip('"\'')
            return ret

        # Since a configure.ac file is essentially a program, this is only ever going to be
        # a hack unfortunately; but it ought to be enough of an approximation
        if acfile:
            srcfiles = [acfile]
        else:
            srcfiles = RecipeHandler.checkfiles(srctree, ['acinclude.m4', 'configure.ac', 'configure.in'])

        pcdeps = []
        libdeps = []
        deps = []
        unmapped = []

        def process_macro(keyword, value):
            if keyword == 'PKG_CHECK_MODULES':
                res = pkg_re.search(value)
                if res:
                    res = dep_re.findall(res.group(1))
                    if res:
                        pcdeps.extend([x[0] for x in res])
                inherits.append('pkgconfig')
            elif keyword == 'PKG_CHECK_EXISTS':
                res = pkgce_re.search(value)
                if res:
                    res = dep_re.findall(res.group(1))
                    if res:
                        pcdeps.extend([x[0] for x in res])
                inherits.append('pkgconfig')
            elif keyword in ('AM_GNU_GETTEXT', 'AM_GLIB_GNU_GETTEXT', 'GETTEXT_PACKAGE'):
                inherits.append('gettext')
            elif keyword in ('AC_PROG_INTLTOOL', 'IT_PROG_INTLTOOL'):
                deps.append('intltool-native')
            elif keyword == 'AM_PATH_GLIB_2_0':
                deps.append('glib-2.0')
            elif keyword in ('AC_CHECK_PROG', 'AC_PATH_PROG', 'AX_WITH_PROG'):
                res = progs_re.search(value)
                if res:
                    for prog in shlex.split(res.group(1)):
                        prog = prog.split()[0]
                        progclass = progclassmap.get(prog, None)
                        if progclass:
                            inherits.append(progclass)
                        else:
                            progdep = progmap.get(prog, None)
                            if progdep:
                                deps.append(progdep)
                            else:
                                if not prog.startswith('$'):
                                    unmapped.append(prog)
            elif keyword == 'AC_CHECK_LIB':
                res = lib_re.search(value)
                if res:
                    lib = res.group(1)
                    if not lib.startswith('$'):
                        libdeps.append(lib)
            elif keyword == 'AX_CHECK_LIBRARY':
                res = libx_re.search(value)
                if res:
                    lib = res.group(2)
                    if not lib.startswith('$'):
                        header = res.group(1)
                        libdeps.add((lib, header))
            elif keyword == 'AC_PATH_X':
                deps.append('libx11')
            elif keyword in ('AX_BOOST', 'BOOST_REQUIRE'):
                deps.append('boost')
            elif keyword in ('AC_PROG_LEX', 'AM_PROG_LEX', 'AX_PROG_FLEX'):
                deps.append('flex-native')
            elif keyword in ('AC_PROG_YACC', 'AX_PROG_BISON'):
                deps.append('bison-native')
            elif keyword == 'AX_CHECK_ZLIB':
                deps.append('zlib')
            elif keyword in ('AX_CHECK_OPENSSL', 'AX_LIB_CRYPTO'):
                deps.append('openssl')
            elif keyword == 'AX_LIB_CURL':
                deps.append('curl')
            elif keyword == 'AX_LIB_BEECRYPT':
                deps.append('beecrypt')
            elif keyword == 'AX_LIB_EXPAT':
                deps.append('expat')
            elif keyword == 'AX_LIB_GCRYPT':
                deps.append('libgcrypt')
            elif keyword == 'AX_LIB_NETTLE':
                deps.append('nettle')
            elif keyword == 'AX_LIB_READLINE':
                deps.append('readline')
            elif keyword == 'AX_LIB_SQLITE3':
                deps.append('sqlite3')
            elif keyword == 'AX_LIB_TAGLIB':
                deps.append('taglib')
            elif keyword == 'AX_PKG_SWIG':
                deps.append('swig')
            elif keyword == 'AX_PROG_XSLTPROC':
                deps.append('libxslt-native')
            elif keyword == 'AX_WITH_CURSES':
                deps.append('ncurses')
            elif keyword == 'AX_PATH_BDB':
                deps.append('db')
            elif keyword == 'AX_PATH_LIB_PCRE':
                deps.append('libpcre')
            elif keyword == 'AC_INIT':
                if extravalues is not None:
                    res = ac_init_re.match(value)
                    if res:
                        extravalues['PN'] = process_value(res.group(1))
                        pv = process_value(res.group(2))
                        if validate_pv(pv):
                            extravalues['PV'] = pv
            elif keyword == 'AM_INIT_AUTOMAKE':
                if extravalues is not None:
                    if 'PN' not in extravalues:
                        res = am_init_re.match(value)
                        if res:
                            if res.group(1) != 'AC_PACKAGE_NAME':
                                extravalues['PN'] = process_value(res.group(1))
                            pv = process_value(res.group(2))
                            if validate_pv(pv):
                                extravalues['PV'] = pv
            elif keyword == 'define(':
                res = define_re.match(value)
                if res:
                    key = res.group(2).strip('[]')
                    value = process_value(res.group(3))
                    if value is not None:
                        defines[key] = value

        keywords = ['PKG_CHECK_MODULES',
                    'PKG_CHECK_EXISTS',
                    'AM_GNU_GETTEXT',
                    'AM_GLIB_GNU_GETTEXT',
                    'GETTEXT_PACKAGE',
                    'AC_PROG_INTLTOOL',
                    'IT_PROG_INTLTOOL',
                    'AM_PATH_GLIB_2_0',
                    'AC_CHECK_PROG',
                    'AC_PATH_PROG',
                    'AX_WITH_PROG',
                    'AC_CHECK_LIB',
                    'AX_CHECK_LIBRARY',
                    'AC_PATH_X',
                    'AX_BOOST',
                    'BOOST_REQUIRE',
                    'AC_PROG_LEX',
                    'AM_PROG_LEX',
                    'AX_PROG_FLEX',
                    'AC_PROG_YACC',
                    'AX_PROG_BISON',
                    'AX_CHECK_ZLIB',
                    'AX_CHECK_OPENSSL',
                    'AX_LIB_CRYPTO',
                    'AX_LIB_CURL',
                    'AX_LIB_BEECRYPT',
                    'AX_LIB_EXPAT',
                    'AX_LIB_GCRYPT',
                    'AX_LIB_NETTLE',
                    'AX_LIB_READLINE'
                    'AX_LIB_SQLITE3',
                    'AX_LIB_TAGLIB',
                    'AX_PKG_SWIG',
                    'AX_PROG_XSLTPROC',
                    'AX_WITH_CURSES',
                    'AX_PATH_BDB',
                    'AX_PATH_LIB_PCRE',
                    'AC_INIT',
                    'AM_INIT_AUTOMAKE',
                    'define(',
                    ]
        for srcfile in srcfiles:
            nesting = 0
            in_keyword = ''
            partial = ''
            with open(srcfile, 'r') as f:
                for line in f:
                    if in_keyword:
                        partial += ' ' + line.strip()
                        if partial.endswith('\\'):
                            partial = partial[:-1]
                        nesting = nesting + line.count('(') - line.count(')')
                        if nesting == 0:
                            process_macro(in_keyword, partial)
                            partial = ''
                            in_keyword = ''
                    else:
                        for keyword in keywords:
                            if keyword in line:
                                nesting = line.count('(') - line.count(')')
                                if nesting > 0:
                                    partial = line.strip()
                                    if partial.endswith('\\'):
                                        partial = partial[:-1]
                                    in_keyword = keyword
                                else:
                                    process_macro(keyword, line.strip())
                                break

            if in_keyword:
                process_macro(in_keyword, partial)

        if extravalues:
            for k,v in extravalues.items():
                if v:
                    if v.startswith('$') or v.startswith('@') or v.startswith('%'):
                        del extravalues[k]
                    else:
                        extravalues[k] = v.strip('"\'').rstrip('()')

        if unmapped:
            outlines.append('# NOTE: the following prog dependencies are unknown, ignoring: %s' % ' '.join(list(set(unmapped))))

        RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data)

        if inherits:
            values['inherit'] = ' '.join(list(set(inherits)))

        return values
示例#3
0
    def extract_cmake_deps(outlines, srctree, extravalues, cmakelistsfile=None):
        # Find all plugins that want to register handlers
        logger.debug('Loading cmake handlers')
        handlers = []
        for plugin in plugins:
            if hasattr(plugin, 'register_cmake_handlers'):
                plugin.register_cmake_handlers(handlers)

        values = {}
        inherits = []

        if cmakelistsfile:
            srcfiles = [cmakelistsfile]
        else:
            srcfiles = RecipeHandler.checkfiles(srctree, ['CMakeLists.txt'])

        # Note that some of these are non-standard, but probably better to
        # be able to map them anyway if we see them
        cmake_pkgmap = {'alsa': 'alsa-lib',
                        'aspell': 'aspell',
                        'atk': 'atk',
                        'bison': 'bison-native',
                        'boost': 'boost',
                        'bzip2': 'bzip2',
                        'cairo': 'cairo',
                        'cups': 'cups',
                        'curl': 'curl',
                        'curses': 'ncurses',
                        'cvs': 'cvs',
                        'drm': 'libdrm',
                        'dbus': 'dbus',
                        'dbusglib': 'dbus-glib',
                        'egl': 'virtual/egl',
                        'expat': 'expat',
                        'flex': 'flex-native',
                        'fontconfig': 'fontconfig',
                        'freetype': 'freetype',
                        'gettext': '',
                        'git': '',
                        'gio': 'glib-2.0',
                        'giounix': 'glib-2.0',
                        'glew': 'glew',
                        'glib': 'glib-2.0',
                        'glib2': 'glib-2.0',
                        'glu': 'libglu',
                        'glut': 'freeglut',
                        'gobject': 'glib-2.0',
                        'gperf': 'gperf-native',
                        'gnutls': 'gnutls',
                        'gtk2': 'gtk+',
                        'gtk3': 'gtk+3',
                        'gtk': 'gtk+3',
                        'harfbuzz': 'harfbuzz',
                        'icu': 'icu',
                        'intl': 'virtual/libintl',
                        'jpeg': 'jpeg',
                        'libarchive': 'libarchive',
                        'libiconv': 'virtual/libiconv',
                        'liblzma': 'xz',
                        'libxml2': 'libxml2',
                        'libxslt': 'libxslt',
                        'opengl': 'virtual/libgl',
                        'openmp': '',
                        'openssl': 'openssl',
                        'pango': 'pango',
                        'perl': '',
                        'perllibs': '',
                        'pkgconfig': '',
                        'png': 'libpng',
                        'pthread': '',
                        'pythoninterp': '',
                        'pythonlibs': '',
                        'ruby': 'ruby-native',
                        'sdl': 'libsdl',
                        'sdl2': 'libsdl2',
                        'subversion': 'subversion-native',
                        'swig': 'swig-native',
                        'tcl': 'tcl-native',
                        'threads': '',
                        'tiff': 'tiff',
                        'wget': 'wget',
                        'x11': 'libx11',
                        'xcb': 'libxcb',
                        'xext': 'libxext',
                        'xfixes': 'libxfixes',
                        'zlib': 'zlib',
                        }

        pcdeps = []
        libdeps = []
        deps = []
        unmappedpkgs = []

        proj_re = re.compile('project\s*\(([^)]*)\)', re.IGNORECASE)
        pkgcm_re = re.compile('pkg_check_modules\s*\(\s*[a-zA-Z0-9-_]+\s*(REQUIRED)?\s+([^)\s]+)\s*\)', re.IGNORECASE)
        pkgsm_re = re.compile('pkg_search_module\s*\(\s*[a-zA-Z0-9-_]+\s*(REQUIRED)?((\s+[^)\s]+)+)\s*\)', re.IGNORECASE)
        findpackage_re = re.compile('find_package\s*\(\s*([a-zA-Z0-9-_]+)\s*.*', re.IGNORECASE)
        findlibrary_re = re.compile('find_library\s*\(\s*[a-zA-Z0-9-_]+\s*(NAMES\s+)?([a-zA-Z0-9-_ ]+)\s*.*')
        checklib_re = re.compile('check_library_exists\s*\(\s*([^\s)]+)\s*.*', re.IGNORECASE)
        include_re = re.compile('include\s*\(\s*([^)\s]*)\s*\)', re.IGNORECASE)
        subdir_re = re.compile('add_subdirectory\s*\(\s*([^)\s]*)\s*([^)\s]*)\s*\)', re.IGNORECASE)
        dep_re = re.compile('([^ ><=]+)( *[<>=]+ *[^ ><=]+)?')

        def find_cmake_package(pkg):
            RecipeHandler.load_devel_filemap(tinfoil.config_data)
            for fn, pn in RecipeHandler.recipecmakefilemap.iteritems():
                splitname = fn.split('/')
                if len(splitname) > 1:
                    if splitname[0].lower().startswith(pkg.lower()):
                        if splitname[1] == '%s-config.cmake' % pkg.lower() or splitname[1] == '%sConfig.cmake' % pkg or splitname[1] == 'Find%s.cmake' % pkg:
                            return pn
            return None

        def interpret_value(value):
            return value.strip('"')

        def parse_cmake_file(fn, paths=None):
            searchpaths = (paths or []) + [os.path.dirname(fn)]
            logger.debug('Parsing file %s' % fn)
            with open(fn, 'r') as f:
                for line in f:
                    line = line.strip()
                    for handler in handlers:
                        if handler.process_line(srctree, fn, line, libdeps, pcdeps, deps, outlines, inherits, values):
                            continue
                    res = include_re.match(line)
                    if res:
                        includefn = bb.utils.which(':'.join(searchpaths), res.group(1))
                        if includefn:
                            parse_cmake_file(includefn, searchpaths)
                        else:
                            logger.debug('Unable to recurse into include file %s' % res.group(1))
                        continue
                    res = subdir_re.match(line)
                    if res:
                        subdirfn = os.path.join(os.path.dirname(fn), res.group(1), 'CMakeLists.txt')
                        if os.path.exists(subdirfn):
                            parse_cmake_file(subdirfn, searchpaths)
                        else:
                            logger.debug('Unable to recurse into subdirectory file %s' % subdirfn)
                        continue
                    res = proj_re.match(line)
                    if res:
                        extravalues['PN'] = interpret_value(res.group(1).split()[0])
                        continue
                    res = pkgcm_re.match(line)
                    if res:
                        res = dep_re.findall(res.group(2))
                        if res:
                            pcdeps.extend([interpret_value(x[0]) for x in res])
                        inherits.append('pkgconfig')
                        continue
                    res = pkgsm_re.match(line)
                    if res:
                        res = dep_re.findall(res.group(2))
                        if res:
                            # Note: appending a tuple here!
                            item = tuple((interpret_value(x[0]) for x in res))
                            if len(item) == 1:
                                item = item[0]
                            pcdeps.append(item)
                        inherits.append('pkgconfig')
                        continue
                    res = findpackage_re.match(line)
                    if res:
                        origpkg = res.group(1)
                        pkg = interpret_value(origpkg)
                        found = False
                        for handler in handlers:
                            if handler.process_findpackage(srctree, fn, pkg, deps, outlines, inherits, values):
                                logger.debug('Mapped CMake package %s via handler %s' % (pkg, handler.__class__.__name__))
                                found = True
                                break
                        if found:
                            continue
                        elif pkg == 'Gettext':
                            inherits.append('gettext')
                        elif pkg == 'Perl':
                            inherits.append('perlnative')
                        elif pkg == 'PkgConfig':
                            inherits.append('pkgconfig')
                        elif pkg == 'PythonInterp':
                            inherits.append('pythonnative')
                        elif pkg == 'PythonLibs':
                            inherits.append('python-dir')
                        else:
                            # Try to map via looking at installed CMake packages in pkgdata
                            dep = find_cmake_package(pkg)
                            if dep:
                                logger.debug('Mapped CMake package %s to recipe %s via pkgdata' % (pkg, dep))
                                deps.append(dep)
                            else:
                                dep = cmake_pkgmap.get(pkg.lower(), None)
                                if dep:
                                    logger.debug('Mapped CMake package %s to recipe %s via internal list' % (pkg, dep))
                                    deps.append(dep)
                                elif dep is None:
                                    unmappedpkgs.append(origpkg)
                        continue
                    res = checklib_re.match(line)
                    if res:
                        lib = interpret_value(res.group(1))
                        if not lib.startswith('$'):
                            libdeps.append(lib)
                    res = findlibrary_re.match(line)
                    if res:
                        libs = res.group(2).split()
                        for lib in libs:
                            if lib in ['HINTS', 'PATHS', 'PATH_SUFFIXES', 'DOC', 'NAMES_PER_DIR'] or lib.startswith(('NO_', 'CMAKE_', 'ONLY_CMAKE_')):
                                break
                            lib = interpret_value(lib)
                            if not lib.startswith('$'):
                                libdeps.append(lib)
                    if line.lower().startswith('useswig'):
                        deps.append('swig-native')
                        continue

        parse_cmake_file(srcfiles[0])

        if unmappedpkgs:
            outlines.append('# NOTE: unable to map the following CMake package dependencies: %s' % ' '.join(list(set(unmappedpkgs))))

        RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data)

        for handler in handlers:
            handler.post_process(srctree, libdeps, pcdeps, deps, outlines, inherits, values)

        if inherits:
            values['inherit'] = ' '.join(list(set(inherits)))

        return values
示例#4
0
    def extract_cmake_deps(outlines,
                           srctree,
                           extravalues,
                           cmakelistsfile=None):
        # Find all plugins that want to register handlers
        logger.debug('Loading cmake handlers')
        handlers = []
        for plugin in plugins:
            if hasattr(plugin, 'register_cmake_handlers'):
                plugin.register_cmake_handlers(handlers)

        values = {}
        inherits = []

        if cmakelistsfile:
            srcfiles = [cmakelistsfile]
        else:
            srcfiles = RecipeHandler.checkfiles(srctree, ['CMakeLists.txt'])

        # Note that some of these are non-standard, but probably better to
        # be able to map them anyway if we see them
        cmake_pkgmap = {
            'alsa': 'alsa-lib',
            'aspell': 'aspell',
            'atk': 'atk',
            'bison': 'bison-native',
            'boost': 'boost',
            'bzip2': 'bzip2',
            'cairo': 'cairo',
            'cups': 'cups',
            'curl': 'curl',
            'curses': 'ncurses',
            'cvs': 'cvs',
            'drm': 'libdrm',
            'dbus': 'dbus',
            'dbusglib': 'dbus-glib',
            'egl': 'virtual/egl',
            'expat': 'expat',
            'flex': 'flex-native',
            'fontconfig': 'fontconfig',
            'freetype': 'freetype',
            'gettext': '',
            'git': '',
            'gio': 'glib-2.0',
            'giounix': 'glib-2.0',
            'glew': 'glew',
            'glib': 'glib-2.0',
            'glib2': 'glib-2.0',
            'glu': 'libglu',
            'glut': 'freeglut',
            'gobject': 'glib-2.0',
            'gperf': 'gperf-native',
            'gnutls': 'gnutls',
            'gtk2': 'gtk+',
            'gtk3': 'gtk+3',
            'gtk': 'gtk+3',
            'harfbuzz': 'harfbuzz',
            'icu': 'icu',
            'intl': 'virtual/libintl',
            'jpeg': 'jpeg',
            'libarchive': 'libarchive',
            'libiconv': 'virtual/libiconv',
            'liblzma': 'xz',
            'libxml2': 'libxml2',
            'libxslt': 'libxslt',
            'opengl': 'virtual/libgl',
            'openmp': '',
            'openssl': 'openssl',
            'pango': 'pango',
            'perl': '',
            'perllibs': '',
            'pkgconfig': '',
            'png': 'libpng',
            'pthread': '',
            'pythoninterp': '',
            'pythonlibs': '',
            'ruby': 'ruby-native',
            'sdl': 'libsdl',
            'sdl2': 'libsdl2',
            'subversion': 'subversion-native',
            'swig': 'swig-native',
            'tcl': 'tcl-native',
            'threads': '',
            'tiff': 'tiff',
            'wget': 'wget',
            'x11': 'libx11',
            'xcb': 'libxcb',
            'xext': 'libxext',
            'xfixes': 'libxfixes',
            'zlib': 'zlib',
        }

        pcdeps = []
        libdeps = []
        deps = []
        unmappedpkgs = []

        proj_re = re.compile('project\s*\(([^)]*)\)', re.IGNORECASE)
        pkgcm_re = re.compile(
            'pkg_check_modules\s*\(\s*[a-zA-Z0-9-_]+\s*(REQUIRED)?\s+([^)\s]+)\s*\)',
            re.IGNORECASE)
        pkgsm_re = re.compile(
            'pkg_search_module\s*\(\s*[a-zA-Z0-9-_]+\s*(REQUIRED)?((\s+[^)\s]+)+)\s*\)',
            re.IGNORECASE)
        findpackage_re = re.compile(
            'find_package\s*\(\s*([a-zA-Z0-9-_]+)\s*.*', re.IGNORECASE)
        findlibrary_re = re.compile(
            'find_library\s*\(\s*[a-zA-Z0-9-_]+\s*(NAMES\s+)?([a-zA-Z0-9-_ ]+)\s*.*'
        )
        checklib_re = re.compile('check_library_exists\s*\(\s*([^\s)]+)\s*.*',
                                 re.IGNORECASE)
        include_re = re.compile('include\s*\(\s*([^)\s]*)\s*\)', re.IGNORECASE)
        subdir_re = re.compile(
            'add_subdirectory\s*\(\s*([^)\s]*)\s*([^)\s]*)\s*\)',
            re.IGNORECASE)
        dep_re = re.compile('([^ ><=]+)( *[<>=]+ *[^ ><=]+)?')

        def find_cmake_package(pkg):
            RecipeHandler.load_devel_filemap(tinfoil.config_data)
            for fn, pn in RecipeHandler.recipecmakefilemap.items():
                splitname = fn.split('/')
                if len(splitname) > 1:
                    if splitname[0].lower().startswith(pkg.lower()):
                        if splitname[1] == '%s-config.cmake' % pkg.lower(
                        ) or splitname[
                                1] == '%sConfig.cmake' % pkg or splitname[
                                    1] == 'Find%s.cmake' % pkg:
                            return pn
            return None

        def interpret_value(value):
            return value.strip('"')

        def parse_cmake_file(fn, paths=None):
            searchpaths = (paths or []) + [os.path.dirname(fn)]
            logger.debug('Parsing file %s' % fn)
            with open(fn, 'r', errors='surrogateescape') as f:
                for line in f:
                    line = line.strip()
                    for handler in handlers:
                        if handler.process_line(srctree, fn, line, libdeps,
                                                pcdeps, deps, outlines,
                                                inherits, values):
                            continue
                    res = include_re.match(line)
                    if res:
                        includefn = bb.utils.which(':'.join(searchpaths),
                                                   res.group(1))
                        if includefn:
                            parse_cmake_file(includefn, searchpaths)
                        else:
                            logger.debug(
                                'Unable to recurse into include file %s' %
                                res.group(1))
                        continue
                    res = subdir_re.match(line)
                    if res:
                        subdirfn = os.path.join(os.path.dirname(fn),
                                                res.group(1), 'CMakeLists.txt')
                        if os.path.exists(subdirfn):
                            parse_cmake_file(subdirfn, searchpaths)
                        else:
                            logger.debug(
                                'Unable to recurse into subdirectory file %s' %
                                subdirfn)
                        continue
                    res = proj_re.match(line)
                    if res:
                        extravalues['PN'] = interpret_value(
                            res.group(1).split()[0])
                        continue
                    res = pkgcm_re.match(line)
                    if res:
                        res = dep_re.findall(res.group(2))
                        if res:
                            pcdeps.extend([interpret_value(x[0]) for x in res])
                        inherits.append('pkgconfig')
                        continue
                    res = pkgsm_re.match(line)
                    if res:
                        res = dep_re.findall(res.group(2))
                        if res:
                            # Note: appending a tuple here!
                            item = tuple((interpret_value(x[0]) for x in res))
                            if len(item) == 1:
                                item = item[0]
                            pcdeps.append(item)
                        inherits.append('pkgconfig')
                        continue
                    res = findpackage_re.match(line)
                    if res:
                        origpkg = res.group(1)
                        pkg = interpret_value(origpkg)
                        found = False
                        for handler in handlers:
                            if handler.process_findpackage(
                                    srctree, fn, pkg, deps, outlines, inherits,
                                    values):
                                logger.debug(
                                    'Mapped CMake package %s via handler %s' %
                                    (pkg, handler.__class__.__name__))
                                found = True
                                break
                        if found:
                            continue
                        elif pkg == 'Gettext':
                            inherits.append('gettext')
                        elif pkg == 'Perl':
                            inherits.append('perlnative')
                        elif pkg == 'PkgConfig':
                            inherits.append('pkgconfig')
                        elif pkg == 'PythonInterp':
                            inherits.append('pythonnative')
                        elif pkg == 'PythonLibs':
                            inherits.append('python-dir')
                        else:
                            # Try to map via looking at installed CMake packages in pkgdata
                            dep = find_cmake_package(pkg)
                            if dep:
                                logger.debug(
                                    'Mapped CMake package %s to recipe %s via pkgdata'
                                    % (pkg, dep))
                                deps.append(dep)
                            else:
                                dep = cmake_pkgmap.get(pkg.lower(), None)
                                if dep:
                                    logger.debug(
                                        'Mapped CMake package %s to recipe %s via internal list'
                                        % (pkg, dep))
                                    deps.append(dep)
                                elif dep is None:
                                    unmappedpkgs.append(origpkg)
                        continue
                    res = checklib_re.match(line)
                    if res:
                        lib = interpret_value(res.group(1))
                        if not lib.startswith('$'):
                            libdeps.append(lib)
                    res = findlibrary_re.match(line)
                    if res:
                        libs = res.group(2).split()
                        for lib in libs:
                            if lib in [
                                    'HINTS', 'PATHS', 'PATH_SUFFIXES', 'DOC',
                                    'NAMES_PER_DIR'
                            ] or lib.startswith(
                                ('NO_', 'CMAKE_', 'ONLY_CMAKE_')):
                                break
                            lib = interpret_value(lib)
                            if not lib.startswith('$'):
                                libdeps.append(lib)
                    if line.lower().startswith('useswig'):
                        deps.append('swig-native')
                        continue

        parse_cmake_file(srcfiles[0])

        if unmappedpkgs:
            outlines.append(
                '# NOTE: unable to map the following CMake package dependencies: %s'
                % ' '.join(list(set(unmappedpkgs))))

        RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values,
                                     tinfoil.config_data)

        for handler in handlers:
            handler.post_process(srctree, libdeps, pcdeps, deps, outlines,
                                 inherits, values)

        if inherits:
            values['inherit'] = ' '.join(list(set(inherits)))

        return values
示例#5
0
    def extract_cmake_deps(outlines, srctree, extravalues, cmakelistsfile=None):
        # Find all plugins that want to register handlers
        logger.debug("Loading cmake handlers")
        handlers = []
        for plugin in plugins:
            if hasattr(plugin, "register_cmake_handlers"):
                plugin.register_cmake_handlers(handlers)

        values = {}
        inherits = []

        if cmakelistsfile:
            srcfiles = [cmakelistsfile]
        else:
            srcfiles = RecipeHandler.checkfiles(srctree, ["CMakeLists.txt"])

        # Note that some of these are non-standard, but probably better to
        # be able to map them anyway if we see them
        cmake_pkgmap = {
            "alsa": "alsa-lib",
            "aspell": "aspell",
            "atk": "atk",
            "bison": "bison-native",
            "boost": "boost",
            "bzip2": "bzip2",
            "cairo": "cairo",
            "cups": "cups",
            "curl": "curl",
            "curses": "ncurses",
            "cvs": "cvs",
            "drm": "libdrm",
            "dbus": "dbus",
            "dbusglib": "dbus-glib",
            "egl": "virtual/egl",
            "expat": "expat",
            "flex": "flex-native",
            "fontconfig": "fontconfig",
            "freetype": "freetype",
            "gettext": "",
            "git": "",
            "gio": "glib-2.0",
            "giounix": "glib-2.0",
            "glew": "glew",
            "glib": "glib-2.0",
            "glib2": "glib-2.0",
            "glu": "libglu",
            "glut": "freeglut",
            "gobject": "glib-2.0",
            "gperf": "gperf-native",
            "gnutls": "gnutls",
            "gtk2": "gtk+",
            "gtk3": "gtk+3",
            "gtk": "gtk+3",
            "harfbuzz": "harfbuzz",
            "icu": "icu",
            "intl": "virtual/libintl",
            "jpeg": "jpeg",
            "libarchive": "libarchive",
            "libiconv": "virtual/libiconv",
            "liblzma": "xz",
            "libxml2": "libxml2",
            "libxslt": "libxslt",
            "opengl": "virtual/libgl",
            "openmp": "",
            "openssl": "openssl",
            "pango": "pango",
            "perl": "",
            "perllibs": "",
            "pkgconfig": "",
            "png": "libpng",
            "pthread": "",
            "pythoninterp": "",
            "pythonlibs": "",
            "ruby": "ruby-native",
            "sdl": "libsdl",
            "sdl2": "libsdl2",
            "subversion": "subversion-native",
            "swig": "swig-native",
            "tcl": "tcl-native",
            "threads": "",
            "tiff": "tiff",
            "wget": "wget",
            "x11": "libx11",
            "xcb": "libxcb",
            "xext": "libxext",
            "xfixes": "libxfixes",
            "zlib": "zlib",
        }

        pcdeps = []
        libdeps = []
        deps = []
        unmappedpkgs = []

        proj_re = re.compile("project\s*\(([^)]*)\)", re.IGNORECASE)
        pkgcm_re = re.compile("pkg_check_modules\s*\(\s*[a-zA-Z0-9-_]+\s*(REQUIRED)?\s+([^)\s]+)\s*\)", re.IGNORECASE)
        pkgsm_re = re.compile(
            "pkg_search_module\s*\(\s*[a-zA-Z0-9-_]+\s*(REQUIRED)?((\s+[^)\s]+)+)\s*\)", re.IGNORECASE
        )
        findpackage_re = re.compile("find_package\s*\(\s*([a-zA-Z0-9-_]+)\s*.*", re.IGNORECASE)
        findlibrary_re = re.compile("find_library\s*\(\s*[a-zA-Z0-9-_]+\s*(NAMES\s+)?([a-zA-Z0-9-_ ]+)\s*.*")
        checklib_re = re.compile("check_library_exists\s*\(\s*([^\s)]+)\s*.*", re.IGNORECASE)
        include_re = re.compile("include\s*\(\s*([^)\s]*)\s*\)", re.IGNORECASE)
        subdir_re = re.compile("add_subdirectory\s*\(\s*([^)\s]*)\s*([^)\s]*)\s*\)", re.IGNORECASE)
        dep_re = re.compile("([^ ><=]+)( *[<>=]+ *[^ ><=]+)?")

        def find_cmake_package(pkg):
            RecipeHandler.load_devel_filemap(tinfoil.config_data)
            for fn, pn in RecipeHandler.recipecmakefilemap.iteritems():
                splitname = fn.split("/")
                if len(splitname) > 1:
                    if splitname[0].lower().startswith(pkg.lower()):
                        if (
                            splitname[1] == "%s-config.cmake" % pkg.lower()
                            or splitname[1] == "%sConfig.cmake" % pkg
                            or splitname[1] == "Find%s.cmake" % pkg
                        ):
                            return pn
            return None

        def interpret_value(value):
            return value.strip('"')

        def parse_cmake_file(fn, paths=None):
            searchpaths = (paths or []) + [os.path.dirname(fn)]
            logger.debug("Parsing file %s" % fn)
            with open(fn, "r") as f:
                for line in f:
                    line = line.strip()
                    for handler in handlers:
                        if handler.process_line(srctree, fn, line, libdeps, pcdeps, deps, outlines, inherits, values):
                            continue
                    res = include_re.match(line)
                    if res:
                        includefn = bb.utils.which(":".join(searchpaths), res.group(1))
                        if includefn:
                            parse_cmake_file(includefn, searchpaths)
                        else:
                            logger.debug("Unable to recurse into include file %s" % res.group(1))
                        continue
                    res = subdir_re.match(line)
                    if res:
                        subdirfn = os.path.join(os.path.dirname(fn), res.group(1), "CMakeLists.txt")
                        if os.path.exists(subdirfn):
                            parse_cmake_file(subdirfn, searchpaths)
                        else:
                            logger.debug("Unable to recurse into subdirectory file %s" % subdirfn)
                        continue
                    res = proj_re.match(line)
                    if res:
                        extravalues["PN"] = interpret_value(res.group(1).split()[0])
                        continue
                    res = pkgcm_re.match(line)
                    if res:
                        res = dep_re.findall(res.group(2))
                        if res:
                            pcdeps.extend([interpret_value(x[0]) for x in res])
                        inherits.append("pkgconfig")
                        continue
                    res = pkgsm_re.match(line)
                    if res:
                        res = dep_re.findall(res.group(2))
                        if res:
                            # Note: appending a tuple here!
                            item = tuple((interpret_value(x[0]) for x in res))
                            if len(item) == 1:
                                item = item[0]
                            pcdeps.append(item)
                        inherits.append("pkgconfig")
                        continue
                    res = findpackage_re.match(line)
                    if res:
                        origpkg = res.group(1)
                        pkg = interpret_value(origpkg)
                        found = False
                        for handler in handlers:
                            if handler.process_findpackage(srctree, fn, pkg, deps, outlines, inherits, values):
                                logger.debug(
                                    "Mapped CMake package %s via handler %s" % (pkg, handler.__class__.__name__)
                                )
                                found = True
                                break
                        if found:
                            continue
                        elif pkg == "Gettext":
                            inherits.append("gettext")
                        elif pkg == "Perl":
                            inherits.append("perlnative")
                        elif pkg == "PkgConfig":
                            inherits.append("pkgconfig")
                        elif pkg == "PythonInterp":
                            inherits.append("pythonnative")
                        elif pkg == "PythonLibs":
                            inherits.append("python-dir")
                        else:
                            # Try to map via looking at installed CMake packages in pkgdata
                            dep = find_cmake_package(pkg)
                            if dep:
                                logger.debug("Mapped CMake package %s to recipe %s via pkgdata" % (pkg, dep))
                                deps.append(dep)
                            else:
                                dep = cmake_pkgmap.get(pkg.lower(), None)
                                if dep:
                                    logger.debug("Mapped CMake package %s to recipe %s via internal list" % (pkg, dep))
                                    deps.append(dep)
                                elif dep is None:
                                    unmappedpkgs.append(origpkg)
                        continue
                    res = checklib_re.match(line)
                    if res:
                        lib = interpret_value(res.group(1))
                        if not lib.startswith("$"):
                            libdeps.append(lib)
                    res = findlibrary_re.match(line)
                    if res:
                        libs = res.group(2).split()
                        for lib in libs:
                            if lib in ["HINTS", "PATHS", "PATH_SUFFIXES", "DOC", "NAMES_PER_DIR"] or lib.startswith(
                                ("NO_", "CMAKE_", "ONLY_CMAKE_")
                            ):
                                break
                            lib = interpret_value(lib)
                            if not lib.startswith("$"):
                                libdeps.append(lib)
                    if line.lower().startswith("useswig"):
                        deps.append("swig-native")
                        continue

        parse_cmake_file(srcfiles[0])

        if unmappedpkgs:
            outlines.append(
                "# NOTE: unable to map the following CMake package dependencies: %s" % " ".join(list(set(unmappedpkgs)))
            )

        RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data)

        for handler in handlers:
            handler.post_process(srctree, libdeps, pcdeps, deps, outlines, inherits, values)

        if inherits:
            values["inherit"] = " ".join(list(set(inherits)))

        return values
示例#6
0
    def extract_autotools_deps(outlines, srctree, extravalues=None, acfile=None):
        import shlex

        # Find all plugins that want to register handlers
        logger.debug("Loading autotools handlers")
        handlers = []
        for plugin in plugins:
            if hasattr(plugin, "register_autotools_handlers"):
                plugin.register_autotools_handlers(handlers)

        values = {}
        inherits = []

        # Hardcoded map, we also use a dynamic one based on what's in the sysroot
        progmap = {
            "flex": "flex-native",
            "bison": "bison-native",
            "m4": "m4-native",
            "tar": "tar-native",
            "ar": "binutils-native",
            "ranlib": "binutils-native",
            "ld": "binutils-native",
            "strip": "binutils-native",
            "libtool": "",
            "autoconf": "",
            "autoheader": "",
            "automake": "",
            "uname": "",
            "rm": "",
            "cp": "",
            "mv": "",
            "find": "",
            "awk": "",
            "sed": "",
        }
        progclassmap = {
            "gconftool-2": "gconf",
            "pkg-config": "pkgconfig",
            "python": "pythonnative",
            "python3": "python3native",
            "perl": "perlnative",
            "makeinfo": "texinfo",
        }

        pkg_re = re.compile("PKG_CHECK_MODULES\(\s*\[?[a-zA-Z0-9_]*\]?,\s*\[?([^,\]]*)\]?[),].*")
        pkgce_re = re.compile("PKG_CHECK_EXISTS\(\s*\[?([^,\]]*)\]?[),].*")
        lib_re = re.compile("AC_CHECK_LIB\(\s*\[?([^,\]]*)\]?,.*")
        libx_re = re.compile("AX_CHECK_LIBRARY\(\s*\[?[^,\]]*\]?,\s*\[?([^,\]]*)\]?,\s*\[?([a-zA-Z0-9-]*)\]?,.*")
        progs_re = re.compile("_PROGS?\(\s*\[?[a-zA-Z0-9_]*\]?,\s*\[?([^,\]]*)\]?[),].*")
        dep_re = re.compile("([^ ><=]+)( [<>=]+ [^ ><=]+)?")
        ac_init_re = re.compile("AC_INIT\(\s*([^,]+),\s*([^,]+)[,)].*")
        am_init_re = re.compile("AM_INIT_AUTOMAKE\(\s*([^,]+),\s*([^,]+)[,)].*")
        define_re = re.compile("\s*(m4_)?define\(\s*([^,]+),\s*([^,]+)\)")

        defines = {}

        def subst_defines(value):
            newvalue = value
            for define, defval in defines.iteritems():
                newvalue = newvalue.replace(define, defval)
            if newvalue != value:
                return subst_defines(newvalue)
            return value

        def process_value(value):
            value = value.replace("[", "").replace("]", "")
            if value.startswith("m4_esyscmd(") or value.startswith("m4_esyscmd_s("):
                cmd = subst_defines(value[value.index("(") + 1 : -1])
                try:
                    if "|" in cmd:
                        cmd = "set -o pipefail; " + cmd
                    stdout, _ = bb.process.run(cmd, cwd=srctree, shell=True)
                    ret = stdout.rstrip()
                except bb.process.ExecutionError as e:
                    ret = ""
            elif value.startswith("m4_"):
                return None
            ret = subst_defines(value)
            if ret:
                ret = ret.strip("\"'")
            return ret

        # Since a configure.ac file is essentially a program, this is only ever going to be
        # a hack unfortunately; but it ought to be enough of an approximation
        if acfile:
            srcfiles = [acfile]
        else:
            srcfiles = RecipeHandler.checkfiles(srctree, ["acinclude.m4", "configure.ac", "configure.in"])

        pcdeps = []
        libdeps = []
        deps = []
        unmapped = []

        RecipeHandler.load_binmap(tinfoil.config_data)

        def process_macro(keyword, value):
            for handler in handlers:
                if handler.process_macro(
                    srctree, keyword, value, process_value, libdeps, pcdeps, deps, outlines, inherits, values
                ):
                    return
            if keyword == "PKG_CHECK_MODULES":
                res = pkg_re.search(value)
                if res:
                    res = dep_re.findall(res.group(1))
                    if res:
                        pcdeps.extend([x[0] for x in res])
                inherits.append("pkgconfig")
            elif keyword == "PKG_CHECK_EXISTS":
                res = pkgce_re.search(value)
                if res:
                    res = dep_re.findall(res.group(1))
                    if res:
                        pcdeps.extend([x[0] for x in res])
                inherits.append("pkgconfig")
            elif keyword in ("AM_GNU_GETTEXT", "AM_GLIB_GNU_GETTEXT", "GETTEXT_PACKAGE"):
                inherits.append("gettext")
            elif keyword in ("AC_PROG_INTLTOOL", "IT_PROG_INTLTOOL"):
                deps.append("intltool-native")
            elif keyword == "AM_PATH_GLIB_2_0":
                deps.append("glib-2.0")
            elif keyword in ("AC_CHECK_PROG", "AC_PATH_PROG", "AX_WITH_PROG"):
                res = progs_re.search(value)
                if res:
                    for prog in shlex.split(res.group(1)):
                        prog = prog.split()[0]
                        for handler in handlers:
                            if handler.process_prog(srctree, keyword, value, prog, deps, outlines, inherits, values):
                                return
                        progclass = progclassmap.get(prog, None)
                        if progclass:
                            inherits.append(progclass)
                        else:
                            progdep = RecipeHandler.recipebinmap.get(prog, None)
                            if not progdep:
                                progdep = progmap.get(prog, None)
                            if progdep:
                                deps.append(progdep)
                            elif progdep is None:
                                if not prog.startswith("$"):
                                    unmapped.append(prog)
            elif keyword == "AC_CHECK_LIB":
                res = lib_re.search(value)
                if res:
                    lib = res.group(1)
                    if not lib.startswith("$"):
                        libdeps.append(lib)
            elif keyword == "AX_CHECK_LIBRARY":
                res = libx_re.search(value)
                if res:
                    lib = res.group(2)
                    if not lib.startswith("$"):
                        header = res.group(1)
                        libdeps.append((lib, header))
            elif keyword == "AC_PATH_X":
                deps.append("libx11")
            elif keyword in ("AX_BOOST", "BOOST_REQUIRE"):
                deps.append("boost")
            elif keyword in ("AC_PROG_LEX", "AM_PROG_LEX", "AX_PROG_FLEX"):
                deps.append("flex-native")
            elif keyword in ("AC_PROG_YACC", "AX_PROG_BISON"):
                deps.append("bison-native")
            elif keyword == "AX_CHECK_ZLIB":
                deps.append("zlib")
            elif keyword in ("AX_CHECK_OPENSSL", "AX_LIB_CRYPTO"):
                deps.append("openssl")
            elif keyword == "AX_LIB_CURL":
                deps.append("curl")
            elif keyword == "AX_LIB_BEECRYPT":
                deps.append("beecrypt")
            elif keyword == "AX_LIB_EXPAT":
                deps.append("expat")
            elif keyword == "AX_LIB_GCRYPT":
                deps.append("libgcrypt")
            elif keyword == "AX_LIB_NETTLE":
                deps.append("nettle")
            elif keyword == "AX_LIB_READLINE":
                deps.append("readline")
            elif keyword == "AX_LIB_SQLITE3":
                deps.append("sqlite3")
            elif keyword == "AX_LIB_TAGLIB":
                deps.append("taglib")
            elif keyword == "AX_PKG_SWIG":
                deps.append("swig")
            elif keyword == "AX_PROG_XSLTPROC":
                deps.append("libxslt-native")
            elif keyword == "AX_WITH_CURSES":
                deps.append("ncurses")
            elif keyword == "AX_PATH_BDB":
                deps.append("db")
            elif keyword == "AX_PATH_LIB_PCRE":
                deps.append("libpcre")
            elif keyword == "AC_INIT":
                if extravalues is not None:
                    res = ac_init_re.match(value)
                    if res:
                        extravalues["PN"] = process_value(res.group(1))
                        pv = process_value(res.group(2))
                        if validate_pv(pv):
                            extravalues["PV"] = pv
            elif keyword == "AM_INIT_AUTOMAKE":
                if extravalues is not None:
                    if "PN" not in extravalues:
                        res = am_init_re.match(value)
                        if res:
                            if res.group(1) != "AC_PACKAGE_NAME":
                                extravalues["PN"] = process_value(res.group(1))
                            pv = process_value(res.group(2))
                            if validate_pv(pv):
                                extravalues["PV"] = pv
            elif keyword == "define(":
                res = define_re.match(value)
                if res:
                    key = res.group(2).strip("[]")
                    value = process_value(res.group(3))
                    if value is not None:
                        defines[key] = value

        keywords = [
            "PKG_CHECK_MODULES",
            "PKG_CHECK_EXISTS",
            "AM_GNU_GETTEXT",
            "AM_GLIB_GNU_GETTEXT",
            "GETTEXT_PACKAGE",
            "AC_PROG_INTLTOOL",
            "IT_PROG_INTLTOOL",
            "AM_PATH_GLIB_2_0",
            "AC_CHECK_PROG",
            "AC_PATH_PROG",
            "AX_WITH_PROG",
            "AC_CHECK_LIB",
            "AX_CHECK_LIBRARY",
            "AC_PATH_X",
            "AX_BOOST",
            "BOOST_REQUIRE",
            "AC_PROG_LEX",
            "AM_PROG_LEX",
            "AX_PROG_FLEX",
            "AC_PROG_YACC",
            "AX_PROG_BISON",
            "AX_CHECK_ZLIB",
            "AX_CHECK_OPENSSL",
            "AX_LIB_CRYPTO",
            "AX_LIB_CURL",
            "AX_LIB_BEECRYPT",
            "AX_LIB_EXPAT",
            "AX_LIB_GCRYPT",
            "AX_LIB_NETTLE",
            "AX_LIB_READLINE" "AX_LIB_SQLITE3",
            "AX_LIB_TAGLIB",
            "AX_PKG_SWIG",
            "AX_PROG_XSLTPROC",
            "AX_WITH_CURSES",
            "AX_PATH_BDB",
            "AX_PATH_LIB_PCRE",
            "AC_INIT",
            "AM_INIT_AUTOMAKE",
            "define(",
        ]

        for handler in handlers:
            handler.extend_keywords(keywords)

        for srcfile in srcfiles:
            nesting = 0
            in_keyword = ""
            partial = ""
            with open(srcfile, "r") as f:
                for line in f:
                    if in_keyword:
                        partial += " " + line.strip()
                        if partial.endswith("\\"):
                            partial = partial[:-1]
                        nesting = nesting + line.count("(") - line.count(")")
                        if nesting == 0:
                            process_macro(in_keyword, partial)
                            partial = ""
                            in_keyword = ""
                    else:
                        for keyword in keywords:
                            if keyword in line:
                                nesting = line.count("(") - line.count(")")
                                if nesting > 0:
                                    partial = line.strip()
                                    if partial.endswith("\\"):
                                        partial = partial[:-1]
                                    in_keyword = keyword
                                else:
                                    process_macro(keyword, line.strip())
                                break

            if in_keyword:
                process_macro(in_keyword, partial)

        if extravalues:
            for k, v in extravalues.items():
                if v:
                    if v.startswith("$") or v.startswith("@") or v.startswith("%"):
                        del extravalues[k]
                    else:
                        extravalues[k] = v.strip("\"'").rstrip("()")

        if unmapped:
            outlines.append(
                "# NOTE: the following prog dependencies are unknown, ignoring: %s" % " ".join(list(set(unmapped)))
            )

        RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data)

        for handler in handlers:
            handler.post_process(srctree, libdeps, pcdeps, deps, outlines, inherits, values)

        if inherits:
            values["inherit"] = " ".join(list(set(inherits)))

        return values