2 # ex:ts=4:sw=4:sts=4:et
3 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
5 import sys, os, getopt, glob, copy, os.path, re
6 sys.path.append('/usr/share/oe')
10 import itertools, optparse
12 parsespin = itertools.cycle( r'|/-\-' )
15 __build_cache_fail = []
21 __world_target = Set()
22 __ignored_dependencies = Set()
23 __depcmds = { "clean": None,
28 def handle_options( args ):
29 parser = optparse.OptionParser( version = "OpenEmbedded Build Infrastructure Core version %s, %%prog version %s" % ( oe.__version__, __version__ ),
30 usage = """%prog [options] [package ...]
32 Builds specified packages, expecting that the .oe files
33 it has to work from are in OEFILES
34 Default packages are all packages in OEFILES.
35 Default OEFILES are the .oe files in the current directory.""" )
37 parser.add_option( "-k", "--continue", help = "continue as much as possible after an error. While the target that failed, and those that depend on it, cannot be remade, the other dependencies of these targets can be processed all the same.",
38 action = "store_false", dest = "abort", default = True )
40 parser.add_option( "-f", "--force", help = "force run of specified cmd, regardless of stamp status",
41 action = "store_true", dest = "force", default = False )
44 parser.add_option( "-c", "--cmd", help = "specify command to pass to oebuild. Valid commands are "
45 "'fetch' (fetch all sources), "
46 "'unpack' (unpack the sources), "
47 "'patch' (apply the patches), "
48 "'configure' (configure the source tree), "
49 "'compile' (compile the source tree), "
50 "'stage' (install libraries and headers needed for subsequent packages), "
51 "'install' (install libraries and executables), and"
52 "'package' (package files into the selected package format)",
53 action = "store", dest = "cmd", default = "build" )
55 parser.add_option( "-r", "--read", help = "read the specified file before oe.conf",
56 action = "append", dest = "file", default = [] )
58 parser.add_option( "-v", "--verbose", help = "output more chit-chat to the terminal",
59 action = "store_true", dest = "verbose", default = False )
61 parser.add_option( "-n", "--dry-run", help = "don't call oebuild, just go through the motions",
62 action = "store_true", dest = "dry_run", default = False )
64 parser.add_option( "-p", "--parse-only", help = "quit after parsing the OE files (developers only)",
65 action = "store_true", dest = "parse_only", default = False )
67 parser.add_option( "-d", "--disable-psyco", help = "disable using the psyco just-in-time compiler (not recommended)",
68 action = "store_true", dest = "disable_psyco", default = False )
70 options, args = parser.parse_args( args )
71 return options, args[1:]
73 def try_build(fn, virtual):
74 if fn in __building_list:
75 oe.error("%s depends on itself (eventually)" % fn)
76 oe.error("upwards chain is: %s" % (" -> ".join(__build_path)))
79 __building_list.append(fn)
81 the_data = make.pkgdata[fn]
82 item = oe.data.getVar('PN', the_data, 1)
83 pathstr = "%s (%s)" % (item, virtual)
84 __build_path.append(pathstr)
86 depends_list = (oe.data.getVar('DEPENDS', the_data, 1) or "").split()
87 if make.options.verbose:
88 oe.note("current path: %s" % (" -> ".join(__build_path)))
89 oe.note("dependencies for %s are: %s" % (item, " ".join(depends_list)))
95 oldcmd = make.options.cmd
96 make.options.cmd = __depcmd
98 for d in depends_list:
99 if d in __ignored_dependencies:
103 if buildPackage(d) == 0:
104 oe.error("dependency %s (for %s) not satisfied" % (d,item))
106 if make.options.abort:
110 make.options.cmd = oldcmd
116 oe.event.fire(oe.event.PkgStarted(item, make.pkgdata[fn]))
118 __stats["attempt"] += 1
119 if not make.options.dry_run:
120 oe.build.exec_task('do_%s' % make.options.cmd, make.pkgdata[fn])
121 oe.event.fire(oe.event.PkgSucceeded(item, make.pkgdata[fn]))
122 __build_cache.append(fn)
124 except oe.build.FuncFailed:
126 oe.error("task stack execution failed")
127 oe.event.fire(oe.event.PkgFailed(item, make.pkgdata[fn]))
128 __build_cache_fail.append(fn)
130 except oe.build.EventException:
132 (type, value, traceback) = sys.exc_info()
134 oe.error("%s event exception, aborting" % oe.event.getName(e))
135 oe.event.fire(oe.event.PkgFailed(item, make.pkgdata[fn]))
136 __build_cache_fail.append(fn)
139 __building_list.remove(fn)
140 __build_path.remove(pathstr)
142 def buildPackage(item):
145 if not providers.has_key(item):
146 oe.error("Nothing provides %s" % item)
149 all_p = providers[item]
152 if p in __build_cache:
157 the_data = make.pkgdata[p]
158 pn = oe.data.getVar('PN', the_data, 1)
159 pv = oe.data.getVar('PV', the_data, 1)
160 pr = oe.data.getVar('PR', the_data, 1)
161 if not versions.has_key(pn):
163 versions[pn].append(((pv, pr), p))
165 # # find the latest version of each provider
166 preferred_versions = {}
167 for p in versions.keys():
170 for (v, _fn) in versions[p]:
171 if (latest is None) or (make.vercmp(latest, v) < 0):
174 preferred_versions[p] = (latest, latest_f)
176 # # build a new list with just the latest version of everything
178 for p in preferred_versions.keys():
179 (v, f) = preferred_versions[p]
183 if p in __build_cache_fail:
184 oe.debug(1, "rejecting already-failed %s" % p)
187 if len(eligible) == 0:
188 oe.error("no eligible providers for %s" % item)
191 # # look to see if one of them is already staged, or marked as preferred.
192 # # if so, bump it to the head of the queue
194 the_data = make.pkgdata[p]
195 pn = oe.data.getVar('PN', the_data, 1)
196 pv = oe.data.getVar('PV', the_data, 1)
197 pr = oe.data.getVar('PR', the_data, 1)
198 tmpdir = oe.data.getVar('TMPDIR', the_data, 1)
199 stamp = '%s/stamps/%s-%s-%s.do_populate_staging' % (tmpdir, pn, pv, pr)
200 if os.path.exists(stamp):
201 (newvers, fn) = preferred_versions[pn]
202 if not fn in eligible:
203 # # package was made ineligible by already-failed check
205 oldver = "%s-%s" % (pv, pr)
206 newver = '-'.join(newvers)
207 if (newver != oldver):
208 extra_chat = "; upgrading from %s to %s" % (oldver, newver)
211 if make.options.verbose:
212 oe.note("selecting already-staged %s to satisfy %s%s" % (pn, item, extra_chat))
214 eligible = [fn] + eligible
217 prefervar = oe.data.getVar('PREFERRED_PROVIDER_%s' % item, make.cfg, 1)
219 __preferred[item] = prefervar
221 if __preferred.has_key(item):
223 the_data = make.pkgdata[p]
224 pn = oe.data.getVar('PN', the_data, 1)
225 if __preferred[item] == pn:
226 if make.options.verbose:
227 oe.note("selecting %s to satisfy %s due to PREFERRED_PROVIDERS" % (pn, item))
229 eligible = [p] + eligible
232 # # run through the list until we find one that we can build
234 oe.debug(2, "selecting %s to satisfy %s" % (fn, item))
235 if try_build(fn, item):
238 oe.note("no buildable providers for %s" % item)
241 def build_depgraph():
246 sys.stdout.write("\rNOTE: Building provider hash: [")
250 sys.stdout.write("#")
252 sys.stdout.write(" ")
254 sys.stdout.write("] (%02d%%)" % p)
257 n = len(make.pkgdata.keys())
262 for p in (oe.data.getVar('PREFERRED_PROVIDERS', make.cfg, 1) or "").split():
263 (providee, provider) = p.split(':')
264 if __preferred.has_key(providee) and __preferred[providee] != provider:
265 oe.error("conflicting preferences for %s: both %s and %s specified" % (providee, provider, __preferred[providee]))
266 __preferred[providee] = provider
268 for f in make.pkgdata.keys():
271 pn = oe.data.getVar('PN', d, 1)
273 deps = (oe.data.getVar("DEPENDS", d, 1) or "").split()
274 provides = Set([pn] + (oe.data.getVar("PROVIDES", d, 1) or "").split())
279 if not pn_provides.has_key(pn):
280 pn_provides[pn] = Set()
281 pn_provides[pn] |= provides
283 for provide in provides:
284 if not providers.has_key(provide):
285 providers[provide] = []
286 providers[provide].append(f)
294 sys.stdout.write("\n")
296 for f in make.pkgdata.keys():
298 if oe.data.getVar('BROKEN', d, 1):
301 pn = oe.data.getVar('PN', d, 1)
302 for p in pn_provides[pn]:
303 if p in all_depends or p.startswith('virtual/'):
307 __world_target.add(pn)
309 def myProgressCallback( x, y, f ):
310 if os.isatty(sys.stdout.fileno()):
311 sys.stdout.write("\rNOTE: Parsing .oe files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
315 sys.stdout.write("Parsing .oe files, please wait...")
318 sys.stdout.write("done.\n")
326 if __name__ == "__main__":
328 make.options, args = handle_options( sys.argv )
330 if not make.options.cmd:
331 make.options.cmd = "build"
333 if make.options.cmd in __depcmds:
334 __depcmd=__depcmds[make.options.cmd]
336 __depcmd=make.options.cmd
342 for f in make.options.file:
344 make.cfg = oe.parse.handle(f, make.cfg)
346 oe.fatal("Unable to open %s" % f)
349 make.cfg = oe.parse.handle("conf/oe.conf", make.cfg)
351 oe.fatal("Unable to open oe.conf")
353 if not oe.data.getVar("BUILDNAME", make.cfg):
354 oe.data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), make.cfg)
356 buildname = oe.data.getVar("BUILDNAME", make.cfg)
358 ignore = oe.data.getVar("ASSUME_PROVIDED", make.cfg, 1) or ""
359 __ignored_dependencies = ignore.split()
363 if not pkgs_to_build:
365 pkgs_to_build.extend(args)
366 if not pkgs_to_build:
367 oepkgs = oe.data.getVar('OEPKGS', make.cfg, 1)
369 pkgs_to_build = oepkgs.split()
370 if not pkgs_to_build:
371 print "Nothing to build. Use 'oemake world' to build everything."
374 __stats["attempt"] = 0
375 __stats["success"] = 0
379 # Import Psyco if available and not disabled
380 if not make.options.disable_psyco:
384 print "NOTE: Psyco JIT Compiler (http://psyco.sf.net) not available. Install it to increase performance."
386 psyco.bind( make.collect_oefiles )
388 print "NOTE: You have disabled Psyco. This decreases performance."
391 make.collect_oefiles( myProgressCallback )
393 if make.options.parse_only:
394 print "Requested parsing .oe files only. Exiting."
398 if 'world' in pkgs_to_build:
399 pkgs_to_build.remove('world')
400 for t in __world_target:
401 pkgs_to_build.append(t)
403 oe.event.fire(oe.event.BuildStarted(buildname, pkgs_to_build, make.cfg))
405 for k in pkgs_to_build:
406 if buildPackage(k) == 0:
407 oe.error("Build of " + k + " failed")
408 if make.options.abort:
411 oe.event.fire(oe.event.BuildCompleted(buildname, pkgs_to_build, make.cfg))
413 print "Build statistics:"
414 print " Attempted builds: %d" % __stats["attempt"]
415 if __stats["fail"] != 0:
416 print " Failed builds: %d" % __stats["fail"]
417 if __stats["deps"] != 0:
418 print " Dependencies not satisfied: %d" % __stats["deps"]
419 if __stats["fail"] != 0 or __stats["deps"] != 0:
423 except KeyboardInterrupt:
424 print "\nNOTE: KeyboardInterrupt - Build not completed."