summaryrefslogtreecommitdiffstats
path: root/scripts/lib/recipetool/create.py
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2015-12-22 17:03:02 +1300
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-12-28 09:25:13 +0000
commitdb5f9645ad3ffb4e9be7075d71cb1b13341f5195 (patch)
tree3c4bfcfc698840c310d069f26b57863fde877528 /scripts/lib/recipetool/create.py
parent6a7661b8005fadad10bde494131e27406e1e45b8 (diff)
downloadpoky-db5f9645ad3ffb4e9be7075d71cb1b13341f5195.tar.gz
recipetool: create: support extracting name and version from build scripts
Some build systems (notably autotools) support declaring the name and version of the program being built; since we need those for the recipe we can attempt to extract them. It's a little fuzzy as they are often omitted or may not be appropriately formatted for our purposes, but it does work on a reasonable number of software packages to be useful. (From OE-Core rev: 3b3fd33190d89c09e62126eea0e45aa84fe5442e) 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.py')
-rw-r--r--scripts/lib/recipetool/create.py130
1 files changed, 104 insertions, 26 deletions
diff --git a/scripts/lib/recipetool/create.py b/scripts/lib/recipetool/create.py
index 5c249ab0c6..6c7b9fd7e8 100644
--- a/scripts/lib/recipetool/create.py
+++ b/scripts/lib/recipetool/create.py
@@ -41,10 +41,17 @@ def tinfoil_init(instance):
41 41
42class RecipeHandler(): 42class RecipeHandler():
43 @staticmethod 43 @staticmethod
44 def checkfiles(path, speclist): 44 def checkfiles(path, speclist, recursive=False):
45 results = [] 45 results = []
46 for spec in speclist: 46 if recursive:
47 results.extend(glob.glob(os.path.join(path, spec))) 47 for root, _, files in os.walk(path):
48 for fn in files:
49 for spec in speclist:
50 if fnmatch.fnmatch(fn, spec):
51 results.append(os.path.join(root, fn))
52 else:
53 for spec in speclist:
54 results.extend(glob.glob(os.path.join(path, spec)))
48 return results 55 return results
49 56
50 def genfunction(self, outlines, funcname, content, python=False, forcespace=False): 57 def genfunction(self, outlines, funcname, content, python=False, forcespace=False):
@@ -70,10 +77,14 @@ class RecipeHandler():
70 outlines.append('}') 77 outlines.append('}')
71 outlines.append('') 78 outlines.append('')
72 79
73 def process(self, srctree, classes, lines_before, lines_after, handled): 80 def process(self, srctree, classes, lines_before, lines_after, handled, extravalues):
74 return False 81 return False
75 82
76 83
84def validate_pv(pv):
85 if not pv or '_version' in pv.lower() or pv[0] not in '0123456789':
86 return False
87 return True
77 88
78def supports_srcrev(uri): 89def supports_srcrev(uri):
79 localdata = bb.data.createCopy(tinfoil.config_data) 90 localdata = bb.data.createCopy(tinfoil.config_data)
@@ -152,7 +163,12 @@ def create_recipe(args):
152 srcuri = '' 163 srcuri = ''
153 srctree = args.source 164 srctree = args.source
154 165
155 outfile = args.outfile 166 if args.outfile and os.path.isdir(args.outfile):
167 outfile = None
168 outdir = args.outfile
169 else:
170 outfile = args.outfile
171 outdir = None
156 if outfile and outfile != '-': 172 if outfile and outfile != '-':
157 if os.path.exists(outfile): 173 if os.path.exists(outfile):
158 logger.error('Output file %s already exists' % outfile) 174 logger.error('Output file %s already exists' % outfile)
@@ -196,28 +212,29 @@ def create_recipe(args):
196 lines_before.append('') 212 lines_before.append('')
197 213
198 # FIXME This is kind of a hack, we probably ought to be using bitbake to do this 214 # FIXME This is kind of a hack, we probably ought to be using bitbake to do this
199 # we'd also want a way to automatically set outfile based upon auto-detecting these values from the source if possible 215 pn = None
200 recipefn = os.path.splitext(os.path.basename(outfile))[0] 216 pv = None
201 fnsplit = recipefn.split('_') 217 if outfile:
202 if len(fnsplit) > 1: 218 recipefn = os.path.splitext(os.path.basename(outfile))[0]
203 pn = fnsplit[0] 219 fnsplit = recipefn.split('_')
204 pv = fnsplit[1] 220 if len(fnsplit) > 1:
205 else: 221 pn = fnsplit[0]
206 pn = recipefn 222 pv = fnsplit[1]
207 pv = None 223 else:
224 pn = recipefn
208 225
209 if args.version: 226 if args.version:
210 pv = args.version 227 pv = args.version
211 228
229 if args.name:
230 pn = args.name
231
212 if pv and pv not in 'git svn hg'.split(): 232 if pv and pv not in 'git svn hg'.split():
213 realpv = pv 233 realpv = pv
214 else: 234 else:
215 realpv = None 235 realpv = None
216 236
217 if srcuri: 237 if not srcuri:
218 if realpv:
219 srcuri = srcuri.replace(realpv, '${PV}')
220 else:
221 lines_before.append('# No information for SRC_URI yet (only an external source tree was specified)') 238 lines_before.append('# No information for SRC_URI yet (only an external source tree was specified)')
222 lines_before.append('SRC_URI = "%s"' % srcuri) 239 lines_before.append('SRC_URI = "%s"' % srcuri)
223 (md5value, sha256value) = checksums 240 (md5value, sha256value) = checksums
@@ -232,13 +249,7 @@ def create_recipe(args):
232 lines_before.append('SRCREV = "%s"' % srcrev) 249 lines_before.append('SRCREV = "%s"' % srcrev)
233 lines_before.append('') 250 lines_before.append('')
234 251
235 if srcsubdir and pv:
236 if srcsubdir == "%s-%s" % (pn, pv):
237 # This would be the default, so we don't need to set S in the recipe
238 srcsubdir = ''
239 if srcsubdir: 252 if srcsubdir:
240 if pv and pv not in 'git svn hg'.split():
241 srcsubdir = srcsubdir.replace(pv, '${PV}')
242 lines_before.append('S = "${WORKDIR}/%s"' % srcsubdir) 253 lines_before.append('S = "${WORKDIR}/%s"' % srcsubdir)
243 lines_before.append('') 254 lines_before.append('')
244 255
@@ -276,8 +287,74 @@ def create_recipe(args):
276 classes.append('bin_package') 287 classes.append('bin_package')
277 handled.append('buildsystem') 288 handled.append('buildsystem')
278 289
290 extravalues = {}
279 for handler in handlers: 291 for handler in handlers:
280 handler.process(srctree, classes, lines_before, lines_after, handled) 292 handler.process(srctree, classes, lines_before, lines_after, handled, extravalues)
293
294 if not realpv:
295 realpv = extravalues.get('PV', None)
296 if realpv:
297 if not validate_pv(realpv):
298 realpv = None
299 else:
300 realpv = realpv.lower().split()[0]
301 if '_' in realpv:
302 realpv = realpv.replace('_', '-')
303 if not pn:
304 pn = extravalues.get('PN', None)
305 if pn:
306 if pn.startswith('GNU '):
307 pn = pn[4:]
308 if ' ' in pn:
309 # Probably a descriptive identifier rather than a proper name
310 pn = None
311 else:
312 pn = pn.lower()
313 if '_' in pn:
314 pn = pn.replace('_', '-')
315
316 if not outfile:
317 if not pn:
318 logger.error('Unable to determine short program name from source tree - please specify name with -N/--name or output file name with -o/--outfile')
319 # devtool looks for this specific exit code, so don't change it
320 sys.exit(15)
321 else:
322 if srcuri and srcuri.startswith(('git://', 'hg://', 'svn://')):
323 outfile = '%s_%s.bb' % (pn, srcuri.split(':', 1)[0])
324 elif realpv:
325 outfile = '%s_%s.bb' % (pn, realpv)
326 else:
327 outfile = '%s.bb' % pn
328 if outdir:
329 outfile = os.path.join(outdir, outfile)
330 # We need to check this again
331 if os.path.exists(outfile):
332 logger.error('Output file %s already exists' % outfile)
333 sys.exit(1)
334
335 lines = lines_before
336 lines_before = []
337 skipblank = True
338 for line in lines:
339 if skipblank:
340 skipblank = False
341 if not line:
342 continue
343 if line.startswith('S = '):
344 if realpv and pv not in 'git svn hg'.split():
345 line = line.replace(realpv, '${PV}')
346 if pn:
347 line = line.replace(pn, '${BPN}')
348 if line == 'S = "${WORKDIR}/${BPN}-${PV}"':
349 skipblank = True
350 continue
351 elif line.startswith('SRC_URI = '):
352 if realpv:
353 line = line.replace(realpv, '${PV}')
354 elif line.startswith('PV = '):
355 if realpv:
356 line = re.sub('"[^+]*\+', '"%s+' % realpv, line)
357 lines_before.append(line)
281 358
282 outlines = [] 359 outlines = []
283 outlines.extend(lines_before) 360 outlines.extend(lines_before)
@@ -469,9 +546,10 @@ def register_commands(subparsers):
469 help='Create a new recipe', 546 help='Create a new recipe',
470 description='Creates a new recipe from a source tree') 547 description='Creates a new recipe from a source tree')
471 parser_create.add_argument('source', help='Path or URL to source') 548 parser_create.add_argument('source', help='Path or URL to source')
472 parser_create.add_argument('-o', '--outfile', help='Specify filename for recipe to create', required=True) 549 parser_create.add_argument('-o', '--outfile', help='Specify filename for recipe to create')
473 parser_create.add_argument('-m', '--machine', help='Make recipe machine-specific as opposed to architecture-specific', action='store_true') 550 parser_create.add_argument('-m', '--machine', help='Make recipe machine-specific as opposed to architecture-specific', action='store_true')
474 parser_create.add_argument('-x', '--extract-to', metavar='EXTRACTPATH', help='Assuming source is a URL, fetch it and extract it to the directory specified as %(metavar)s') 551 parser_create.add_argument('-x', '--extract-to', metavar='EXTRACTPATH', help='Assuming source is a URL, fetch it and extract it to the directory specified as %(metavar)s')
552 parser_create.add_argument('-N', '--name', help='Name to use within recipe (PN)')
475 parser_create.add_argument('-V', '--version', help='Version to use within recipe (PV)') 553 parser_create.add_argument('-V', '--version', help='Version to use within recipe (PV)')
476 parser_create.add_argument('-b', '--binary', help='Treat the source tree as something that should be installed verbatim (no compilation, same directory structure)', action='store_true') 554 parser_create.add_argument('-b', '--binary', help='Treat the source tree as something that should be installed verbatim (no compilation, same directory structure)', action='store_true')
477 parser_create.set_defaults(func=create_recipe) 555 parser_create.set_defaults(func=create_recipe)