3 import sys, os, getopt, glob, copy, os.path, re, sets
4 sys.path.append('/usr/share/oe')
11 except ImportError: # itertools appears in Python 2.3
12 from utils import itertools
15 except ImportError: # optparse appears in Python 2.3
16 from utils import optparse
17 parsespin = itertools.cycle( r'|/-\-' )
20 __build_cache_fail = []
26 __world_target = Set()
30 def handle_options( args ):
31 parser = optparse.OptionParser( version = "OpenEmbedded Build Infrastructure Core version %s, %%prog version %s" % ( oe.__version__, __version__ ),
32 usage = """%prog [options] [package ...]
34 Builds specified packages, expecting that the .oe files
35 it has to work from are in OEFILES
36 Default packages are all packages in OEFILES.
37 Default OEFILES are the .oe files in the current directory.""" )
39 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.",
40 action = "store_false", dest = "abort", default = True )
42 parser.add_option( "-f", "--force", help = "force run of specified cmd, regardless of stamp status",
43 action = "store_true", dest = "force", default = False )
46 parser.add_option( "-c", "--cmd", help = "specify command to pass to oebuild",
47 action = "store", dest = "cmd", default = "build" )
49 parser.add_option( "-r", "--read", help = "read the specified file before oe.conf",
50 action = "append", dest = "file", default = [] )
52 parser.add_option( "-v", "--verbose", help = "output more chit-chat to the terminal",
53 action = "store_true", dest = "verbose", default = False )
55 parser.add_option( "-n", "--dry-run", help = "don't call oebuild, just go through the motions",
56 action = "store_true", dest = "dry_run", default = False )
58 options, args = parser.parse_args( args )
59 return options, args[1:]
61 def try_build(fn, virtual):
62 if fn in __building_list:
63 oe.error("%s depends on itself (eventually)" % fn)
64 oe.error("upwards chain is: %s" % (" -> ".join(__build_path)))
67 __building_list.append(fn)
69 the_data = make.pkgdata[fn]
70 item = oe.data.getVar('PN', the_data, 1)
71 pathstr = "%s (%s)" % (item, virtual)
72 __build_path.append(pathstr)
74 depends_list = (oe.data.getVar('DEPENDS', the_data, 1) or "").split()
75 if make.options.verbose:
76 oe.note("current path: %s" % (" -> ".join(__build_path)))
77 oe.note("dependencies for %s are: %s" % (item, " ".join(depends_list)))
82 for d in depends_list:
83 if buildPackage(d) == 0:
85 if make.options.abort:
89 oe.error("dependency %s (for %s) not satisfied" % (d,item))
93 command = make.options.cmd
94 oe.debug(1, "oebuild %s %s" % (command, fn))
95 oe.event.fire(oe.event.PkgStarted(item, make.pkgdata[fn]))
97 __stats["attempt"] += 1
98 if not make.options.dry_run:
99 oe.build.exec_task('do_%s' % command, make.pkgdata[fn])
100 oe.event.fire(oe.event.PkgSucceeded(item, make.pkgdata[fn]))
101 __build_cache.append(fn)
103 except oe.build.FuncFailed:
105 oe.error("task stack execution failed")
106 oe.event.fire(oe.event.PkgFailed(item, make.pkgdata[fn]))
107 __build_cache_fail.append(fn)
109 except oe.build.EventException:
111 (type, value, traceback) = sys.exc_info()
113 oe.error("%s event exception, aborting" % oe.event.getName(e))
114 oe.event.fire(oe.event.PkgFailed(item, make.pkgdata[fn]))
115 __build_cache_fail.append(fn)
118 __building_list.remove(fn)
119 __build_path.remove(pathstr)
122 def buildPackage(item):
125 if not providers.has_key(item):
126 oe.error("Nothing provides %s" % item)
129 all_p = providers[item]
132 if p in __build_cache:
137 the_data = make.pkgdata[p]
138 pn = oe.data.getVar('PN', the_data, 1)
139 pv = oe.data.getVar('PV', the_data, 1)
140 pr = oe.data.getVar('PR', the_data, 1)
141 if not versions.has_key(pn):
143 versions[pn].append(((pv, pr), p))
145 # find the latest version of each provider
146 preferred_versions = {}
147 for p in versions.keys():
150 for (v, _fn) in versions[p]:
151 if (latest is None) or (make.vercmp(latest, v) < 0):
154 preferred_versions[p] = (latest, latest_f)
156 # build a new list with just the latest version of everything
158 for p in preferred_versions.keys():
159 (v, f) = preferred_versions[p]
163 if p in __build_cache_fail:
164 oe.debug(1, "rejecting already-failed %s" % p)
167 if len(eligible) == 0:
168 oe.error("no eligible providers for %s" % item)
171 # look to see if one of them is already staged, or marked as preferred.
172 # if so, bump it to the head of the queue
174 the_data = make.pkgdata[p]
175 pn = oe.data.getVar('PN', the_data, 1)
176 pv = oe.data.getVar('PV', the_data, 1)
177 pr = oe.data.getVar('PR', the_data, 1)
178 tmpdir = oe.data.getVar('TMPDIR', the_data, 1)
179 stamp = '%s/stamps/%s-%s-%s.do_populate_staging' % (tmpdir, pn, pv, pr)
180 if os.path.exists(stamp):
181 (newvers, fn) = preferred_versions[pn]
182 oldver = "%s-%s" % (pv, pr)
183 newver = '-'.join(newvers)
184 if (newver != oldver):
185 extra_chat = "; upgrading from %s to %s" % (oldver, newver)
188 if make.options.verbose:
189 oe.note("selecting already-staged %s to satisfy %s%s" % (pn, item, extra_chat))
191 eligible = [fn] + eligible
194 if __preferred.has_key(item):
196 the_data = make.pkgdata[p]
197 pn = oe.data.getVar('PN', the_data, 1)
198 if __preferred[item] == pn:
199 if make.options.verbose:
200 oe.note("selecting %s to satisfy %s due to PREFERRED_PROVIDERS" % (pn, item))
202 eligible = [p] + eligible
205 # run through the list until we find one that we can build
207 oe.debug(2, "selecting %s to satisfy %s" % (fn, item))
208 if try_build(fn, item):
211 oe.note("no buildable providers for %s" % item)
215 def build_depgraph():
219 for f in make.pkgdata.keys():
222 pn = oe.data.getVar('PN', d, 1)
224 deps = (oe.data.getVar("DEPENDS", d, 1) or "").split()
225 provides = Set([pn] + (oe.data.getVar("PROVIDES", d, 1) or "").split())
230 if not pn_provides.has_key(pn):
231 pn_provides[pn] = Set()
232 pn_provides[pn] |= provides
234 for provide in provides:
235 if not providers.has_key(provide):
236 providers[provide] = []
237 providers[provide].append(f)
239 for p in (oe.data.getVar('PREFERRED_PROVIDERS', d, 1) or "").split():
240 (providee, provider) = p.split(':')
241 if __preferred.has_key(providee) and __preferred[providee] != provider:
242 oe.error("conflicting preferences for %s: both %s and %s specified" % (providee, provider, __preferred[providee]))
243 __preferred[providee] = provider
245 for f in make.pkgdata.keys():
248 pn = oe.data.getVar('PN', d, 1)
249 for p in pn_provides[pn]:
250 if p in all_depends or p.startswith('virtual/'):
254 __world_target.add(pn)
256 def myProgressCallback( x, y, f ):
257 sys.stdout.write("\rNOTE: Parsing .oe files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
264 if __name__ == "__main__":
266 make.options, args = handle_options( sys.argv )
268 _depcmds = { "clean": None,
272 if not make.options.cmd:
273 make.options.cmd = "build"
275 if make.options.cmd in _depcmds:
276 depcmd=_depcmds[make.options.cmd]
278 depcmd=make.options.cmd
284 for f in make.options.file:
286 make.cfg = oe.parse.handle(f, make.cfg)
288 oe.fatal("Unable to open %s" % f)
291 make.cfg = oe.parse.handle("conf/oe.conf", make.cfg)
293 oe.fatal("Unable to open oe.conf")
295 if not oe.data.getVar("BUILDNAME", make.cfg):
296 oe.data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), make.cfg)
298 buildname = oe.data.getVar("BUILDNAME", make.cfg)
302 if not pkgs_to_build:
304 pkgs_to_build.extend(args)
305 if not pkgs_to_build:
306 oepkgs = oe.data.getVar('OEPKGS', make.cfg, 1)
308 pkgs_to_build = oepkgs.split()
309 if not pkgs_to_build:
310 print "Nothing to build. Use 'oemake world' to build everything."
313 __stats["attempt"] = 0
314 __stats["success"] = 0
319 make.collect_oefiles( myProgressCallback )
323 if 'world' in pkgs_to_build:
324 pkgs_to_build.remove('world')
325 for t in __world_target:
326 pkgs_to_build.append(t)
328 oe.event.fire(oe.event.BuildStarted(buildname, pkgs_to_build, make.cfg))
330 for k in pkgs_to_build:
331 if buildPackage(k) == 0:
332 oe.error("Build of " + k + " failed")
333 if make.options.abort:
336 oe.event.fire(oe.event.BuildCompleted(buildname, pkgs_to_build, make.cfg))
338 print "Build statistics:"
339 print " Attempted builds: %d" % __stats["attempt"]
340 if __stats["fail"] != 0:
341 print " Failed builds: %d" % __stats["fail"]
342 if __stats["deps"] != 0:
343 print " Dependencies not satisfied: %d" % __stats["deps"]
344 if __stats["fail"] != 0 or __stats["deps"] != 0:
348 except KeyboardInterrupt:
349 print "\nNOTE: KeyboardInterrupt - Build not completed."