diff options
| author | Paul Eggleton <paul.eggleton@linux.intel.com> | 2016-01-19 00:18:33 +1300 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2016-01-19 17:24:53 +0000 |
| commit | 2c8c9fe3b4e2d3a0910d567e99f0b268a854c0fe (patch) | |
| tree | 863a899e78f3213f75729db08efc6cfed1a4a51c /scripts/lib/recipetool/create_buildsys.py | |
| parent | 3eb397fab6a5c5a86ac4eb30c5159f19e8ebf796 (diff) | |
| download | poky-2c8c9fe3b4e2d3a0910d567e99f0b268a854c0fe.tar.gz | |
recipetool: create: add basic support for extracting dependencies from cmake
Add support for extracting dependencies from CMakeLists.txt. There's
still a bunch of things missing that are outside the scope of OE-Core
and we still lack a proper extension mechanism, but this is a good
start.
This also adds an oe-selftest test to exercise the new code a bit.
Implements [YOCTO #7635].
(From OE-Core rev: 77e73e6930381fdbd6e78d3913d6467572e16568)
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib/recipetool/create_buildsys.py')
| -rw-r--r-- | scripts/lib/recipetool/create_buildsys.py | 177 |
1 files changed, 171 insertions, 6 deletions
diff --git a/scripts/lib/recipetool/create_buildsys.py b/scripts/lib/recipetool/create_buildsys.py index 40659d1ea8..6afb5de1c2 100644 --- a/scripts/lib/recipetool/create_buildsys.py +++ b/scripts/lib/recipetool/create_buildsys.py | |||
| @@ -36,6 +36,7 @@ class CmakeRecipeHandler(RecipeHandler): | |||
| 36 | if RecipeHandler.checkfiles(srctree, ['CMakeLists.txt']): | 36 | if RecipeHandler.checkfiles(srctree, ['CMakeLists.txt']): |
| 37 | classes.append('cmake') | 37 | classes.append('cmake') |
| 38 | values = CmakeRecipeHandler.extract_cmake_deps(lines_before, srctree, extravalues) | 38 | values = CmakeRecipeHandler.extract_cmake_deps(lines_before, srctree, extravalues) |
| 39 | classes.extend(values.pop('inherit', '').split()) | ||
| 39 | for var, value in values.iteritems(): | 40 | for var, value in values.iteritems(): |
| 40 | lines_before.append('%s = "%s"' % (var, value)) | 41 | lines_before.append('%s = "%s"' % (var, value)) |
| 41 | lines_after.append('# Specify any options you want to pass to cmake using EXTRA_OECMAKE:') | 42 | lines_after.append('# Specify any options you want to pass to cmake using EXTRA_OECMAKE:') |
| @@ -48,18 +49,182 @@ class CmakeRecipeHandler(RecipeHandler): | |||
| 48 | @staticmethod | 49 | @staticmethod |
| 49 | def extract_cmake_deps(outlines, srctree, extravalues, cmakelistsfile=None): | 50 | def extract_cmake_deps(outlines, srctree, extravalues, cmakelistsfile=None): |
| 50 | values = {} | 51 | values = {} |
| 52 | inherits = [] | ||
| 51 | 53 | ||
| 52 | if cmakelistsfile: | 54 | if cmakelistsfile: |
| 53 | srcfiles = [cmakelistsfile] | 55 | srcfiles = [cmakelistsfile] |
| 54 | else: | 56 | else: |
| 55 | srcfiles = RecipeHandler.checkfiles(srctree, ['CMakeLists.txt']) | 57 | srcfiles = RecipeHandler.checkfiles(srctree, ['CMakeLists.txt']) |
| 56 | 58 | ||
| 57 | proj_re = re.compile('project\(([^)]*)\)', re.IGNORECASE) | 59 | # Note that some of these are non-standard, but probably better to |
| 58 | with open(srcfiles[0], 'r') as f: | 60 | # be able to map them anyway if we see them |
| 59 | for line in f: | 61 | cmake_pkgmap = {'alsa': 'alsa-lib', |
| 60 | res = proj_re.match(line.strip()) | 62 | 'aspell': 'aspell', |
| 61 | if res: | 63 | 'atk': 'atk', |
| 62 | extravalues['PN'] = res.group(1).split()[0] | 64 | 'bison': 'bison-native', |
| 65 | 'boost': 'boost', | ||
| 66 | 'bzip2': 'bzip2', | ||
| 67 | 'cairo': 'cairo', | ||
| 68 | 'cups': 'cups', | ||
| 69 | 'curl': 'curl', | ||
| 70 | 'curses': 'ncurses', | ||
| 71 | 'cvs': 'cvs', | ||
| 72 | 'drm': 'libdrm', | ||
| 73 | 'dbus': 'dbus', | ||
| 74 | 'dbusglib': 'dbus-glib', | ||
| 75 | 'egl': 'virtual/egl', | ||
| 76 | 'expat': 'expat', | ||
| 77 | 'flex': 'flex-native', | ||
| 78 | 'fontconfig': 'fontconfig', | ||
| 79 | 'freetype': 'freetype', | ||
| 80 | 'gettext': '', | ||
| 81 | 'git': '', | ||
| 82 | 'gio': 'glib-2.0', | ||
| 83 | 'giounix': 'glib-2.0', | ||
| 84 | 'glew': 'glew', | ||
| 85 | 'glib': 'glib-2.0', | ||
| 86 | 'glib2': 'glib-2.0', | ||
| 87 | 'glu': 'libglu', | ||
| 88 | 'glut': 'freeglut', | ||
| 89 | 'gobject': 'glib-2.0', | ||
| 90 | 'gperf': 'gperf-native', | ||
| 91 | 'gnutls': 'gnutls', | ||
| 92 | 'gtk2': 'gtk+', | ||
| 93 | 'gtk3': 'gtk+3', | ||
| 94 | 'gtk': 'gtk+3', | ||
| 95 | 'harfbuzz': 'harfbuzz', | ||
| 96 | 'icu': 'icu', | ||
| 97 | 'intl': 'virtual/libintl', | ||
| 98 | 'jpeg': 'jpeg', | ||
| 99 | 'libarchive': 'libarchive', | ||
| 100 | 'libiconv': 'virtual/libiconv', | ||
| 101 | 'liblzma': 'xz', | ||
| 102 | 'libxml2': 'libxml2', | ||
| 103 | 'libxslt': 'libxslt', | ||
| 104 | 'opengl': 'virtual/libgl', | ||
| 105 | 'openmp': '', | ||
| 106 | 'openssl': 'openssl', | ||
| 107 | 'pango': 'pango', | ||
| 108 | 'perl': '', | ||
| 109 | 'perllibs': '', | ||
| 110 | 'pkgconfig': '', | ||
| 111 | 'png': 'libpng', | ||
| 112 | 'pthread': '', | ||
| 113 | 'pythoninterp': '', | ||
| 114 | 'pythonlibs': '', | ||
| 115 | 'ruby': 'ruby-native', | ||
| 116 | 'sdl': 'libsdl', | ||
| 117 | 'sdl2': 'libsdl2', | ||
| 118 | 'subversion': 'subversion-native', | ||
| 119 | 'swig': 'swig-native', | ||
| 120 | 'tcl': 'tcl-native', | ||
| 121 | 'threads': '', | ||
| 122 | 'tiff': 'tiff', | ||
| 123 | 'wget': 'wget', | ||
| 124 | 'x11': 'libx11', | ||
| 125 | 'xcb': 'libxcb', | ||
| 126 | 'xext': 'libxext', | ||
| 127 | 'xfixes': 'libxfixes', | ||
| 128 | 'zlib': 'zlib', | ||
| 129 | } | ||
| 130 | |||
| 131 | pcdeps = [] | ||
| 132 | libdeps = [] | ||
| 133 | deps = [] | ||
| 134 | unmappedpkgs = [] | ||
| 135 | |||
| 136 | proj_re = re.compile('project\s*\(([^)]*)\)', re.IGNORECASE) | ||
| 137 | pkgcm_re = re.compile('pkg_check_modules\s*\(\s*[a-zA-Z0-9-_]+\s*(REQUIRED)?\s+([^)\s]+)\s*\)', re.IGNORECASE) | ||
| 138 | pkgsm_re = re.compile('pkg_search_module\s*\(\s*[a-zA-Z0-9-_]+\s*(REQUIRED)?((\s+[^)\s]+)+)\s*\)', re.IGNORECASE) | ||
| 139 | findpackage_re = re.compile('find_package\s*\(\s*([a-zA-Z0-9-_]+)\s*.*', re.IGNORECASE) | ||
| 140 | checklib_re = re.compile('check_library_exists\s*\(\s*([^\s)]+)\s*.*', re.IGNORECASE) | ||
| 141 | include_re = re.compile('include\s*\(\s*([^)\s]*)\s*\)', re.IGNORECASE) | ||
| 142 | subdir_re = re.compile('add_subdirectory\s*\(\s*([^)\s]*)\s*([^)\s]*)\s*\)', re.IGNORECASE) | ||
| 143 | dep_re = re.compile('([^ ><=]+)( *[<>=]+ *[^ ><=]+)?') | ||
| 144 | |||
| 145 | def parse_cmake_file(fn, paths=None): | ||
| 146 | searchpaths = (paths or []) + [os.path.dirname(fn)] | ||
| 147 | logger.debug('Parsing file %s' % fn) | ||
| 148 | with open(fn, 'r') as f: | ||
| 149 | for line in f: | ||
| 150 | line = line.strip() | ||
| 151 | res = include_re.match(line) | ||
| 152 | if res: | ||
| 153 | includefn = bb.utils.which(':'.join(searchpaths), res.group(1)) | ||
| 154 | if includefn: | ||
| 155 | parse_cmake_file(includefn, searchpaths) | ||
| 156 | else: | ||
| 157 | logger.debug('Unable to recurse into include file %s' % res.group(1)) | ||
| 158 | continue | ||
| 159 | res = subdir_re.match(line) | ||
| 160 | if res: | ||
| 161 | subdirfn = os.path.join(os.path.dirname(fn), res.group(1), 'CMakeLists.txt') | ||
| 162 | if os.path.exists(subdirfn): | ||
| 163 | parse_cmake_file(subdirfn, searchpaths) | ||
| 164 | else: | ||
| 165 | logger.debug('Unable to recurse into subdirectory file %s' % subdirfn) | ||
| 166 | continue | ||
| 167 | res = proj_re.match(line) | ||
| 168 | if res: | ||
| 169 | extravalues['PN'] = res.group(1).split()[0] | ||
| 170 | continue | ||
| 171 | res = pkgcm_re.match(line) | ||
| 172 | if res: | ||
| 173 | res = dep_re.findall(res.group(2)) | ||
| 174 | if res: | ||
| 175 | pcdeps.extend([x[0] for x in res]) | ||
| 176 | inherits.append('pkgconfig') | ||
| 177 | continue | ||
| 178 | res = pkgsm_re.match(line) | ||
| 179 | if res: | ||
| 180 | res = dep_re.findall(res.group(2)) | ||
| 181 | if res: | ||
| 182 | # Note: appending a tuple here! | ||
| 183 | item = tuple((x[0] for x in res)) | ||
| 184 | if len(item) == 1: | ||
| 185 | item = item[0] | ||
| 186 | pcdeps.append(item) | ||
| 187 | inherits.append('pkgconfig') | ||
| 188 | continue | ||
| 189 | res = findpackage_re.match(line) | ||
| 190 | if res: | ||
| 191 | origpkg = res.group(1) | ||
| 192 | pkg = origpkg.lower() | ||
| 193 | if pkg == 'gettext': | ||
| 194 | inherits.append('gettext') | ||
| 195 | elif pkg == 'perl': | ||
| 196 | inherits.append('perlnative') | ||
| 197 | elif pkg == 'pkgconfig': | ||
| 198 | inherits.append('pkgconfig') | ||
| 199 | elif pkg == 'pythoninterp': | ||
| 200 | inherits.append('pythonnative') | ||
| 201 | elif pkg == 'pythonlibs': | ||
| 202 | inherits.append('python-dir') | ||
| 203 | else: | ||
| 204 | dep = cmake_pkgmap.get(pkg, None) | ||
| 205 | if dep: | ||
| 206 | deps.append(dep) | ||
| 207 | elif dep is None: | ||
| 208 | unmappedpkgs.append(origpkg) | ||
| 209 | continue | ||
| 210 | res = checklib_re.match(line) | ||
| 211 | if res: | ||
| 212 | lib = res.group(1) | ||
| 213 | if not lib.startswith('$'): | ||
| 214 | libdeps.append(lib) | ||
| 215 | if line.lower().startswith('useswig'): | ||
| 216 | deps.append('swig-native') | ||
| 217 | continue | ||
| 218 | |||
| 219 | parse_cmake_file(srcfiles[0]) | ||
| 220 | |||
| 221 | if unmappedpkgs: | ||
| 222 | outlines.append('# NOTE: unable to map the following CMake package dependencies: %s' % ' '.join(unmappedpkgs)) | ||
| 223 | |||
| 224 | RecipeHandler.handle_depends(libdeps, pcdeps, deps, outlines, values, tinfoil.config_data) | ||
| 225 | |||
| 226 | if inherits: | ||
| 227 | values['inherit'] = ' '.join(list(set(inherits))) | ||
| 63 | 228 | ||
| 64 | return values | 229 | return values |
| 65 | 230 | ||
