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 | ||