Import patch tmpfile
[vuplus_bitbake] / bin / oemake
1 #!/usr/bin/env python
2
3 import sys, os, getopt, glob, copy, os.path, re, sets
4 sys.path.append('/usr/share/oe')
5 import oe
6 from oe import make
7 from sets import Set
8
9 try:
10     import itertools
11 except ImportError: # itertools appears in Python 2.3
12     from utils import itertools
13 try:
14     import optparse
15 except ImportError: # optparse appears in Python 2.3
16     from utils import optparse
17 parsespin = itertools.cycle( r'|/-\-' )
18
19 __version__ = 1.1
20 __build_cache_fail = []
21 __build_cache = []
22 __building_list = []
23 __build_path = []
24
25 __preferred = {}
26 __world_target = Set()
27
28 __stats = {}
29
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 ...]
33
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.""" )
38
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 )
41
42         parser.add_option( "-f", "--force", help = "force run of specified cmd, regardless of stamp status",
43                            action = "store_true", dest = "force", default = False )
44
45
46         parser.add_option( "-c", "--cmd", help = "specify command to pass to oebuild",
47                            action = "store", dest = "cmd", default = "build" )
48
49         parser.add_option( "-r", "--read", help = "read the specified file before oe.conf",
50                            action = "append", dest = "file", default = [] )
51
52         parser.add_option( "-v", "--verbose", help = "output more chit-chat to the terminal",
53                            action = "store_true", dest = "verbose", default = False )
54
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 )
57
58         options, args = parser.parse_args( args )
59         return options, args[1:]
60
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)))
65             return False
66
67         __building_list.append(fn)
68
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)
73
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)))
78
79         try:
80                 failed = False
81                 
82                 for d in depends_list:
83                         if buildPackage(d) == 0:
84                                 failed = True
85                                 if make.options.abort:
86                                         break
87
88                 if failed:
89                         oe.error("dependency %s (for %s) not satisfied" % (d,item))
90                         __stats["deps"] += 1
91                         return False
92
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]))
96                 try:
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)
102                         return True
103                 except oe.build.FuncFailed:
104                         __stats["fail"] += 1
105                         oe.error("task stack execution failed")
106                         oe.event.fire(oe.event.PkgFailed(item, make.pkgdata[fn]))
107                         __build_cache_fail.append(fn)
108                         return False
109                 except oe.build.EventException:
110                         __stats["fail"] += 1
111                         (type, value, traceback) = sys.exc_info()
112                         e = value.event
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)
116                         return False
117         finally:
118                 __building_list.remove(fn)
119                 __build_path.remove(pathstr)
120                 
121
122 def buildPackage(item):
123         fn = None
124         
125         if not providers.has_key(item):
126             oe.error("Nothing provides %s" % item)
127             return 0
128
129         all_p = providers[item]
130
131         for p in all_p:
132             if p in __build_cache:
133                 return 1
134
135         versions = {}
136         for p in all_p:
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):
142                 versions[pn] = []
143             versions[pn].append(((pv, pr), p))
144
145         # find the latest version of each provider
146         preferred_versions = {}
147         for p in versions.keys():
148             latest = None
149             latest_f = None
150             for (v, _fn) in versions[p]:
151                 if (latest is None) or (make.vercmp(latest, v) < 0):
152                     latest = v
153                     latest_f = _fn
154             preferred_versions[p] = (latest, latest_f)
155             
156         # build a new list with just the latest version of everything
157         eligible = []
158         for p in preferred_versions.keys():
159             (v, f) = preferred_versions[p]
160             eligible.append(f)
161
162         for p in eligible:
163             if p in __build_cache_fail:
164                 oe.debug(1, "rejecting already-failed %s" % p)
165                 eligible.remove(p)
166
167         if len(eligible) == 0:
168             oe.error("no eligible providers for %s" % item)
169             return 0
170
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
173         for p in all_p:
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)
186                 else:
187                         extra_chat = ""
188                 if make.options.verbose:
189                         oe.note("selecting already-staged %s to satisfy %s%s" % (pn, item, extra_chat))
190                 eligible.remove(fn)
191                 eligible = [fn] + eligible
192                 break
193
194         if __preferred.has_key(item):
195                 for p in eligible:
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))
201                                 eligible.remove(p)
202                                 eligible = [p] + eligible
203                                 break
204                 
205         # run through the list until we find one that we can build
206         for fn in eligible:
207                 oe.debug(2, "selecting %s to satisfy %s" % (fn, item))
208                 if try_build(fn, item):
209                         return 1
210
211         oe.note("no buildable providers for %s" % item)
212         return 0
213
214
215 def build_depgraph():
216     all_depends = Set()
217     pn_provides = {}
218     
219     for f in make.pkgdata.keys():
220         d = make.pkgdata[f]
221         
222         pn = oe.data.getVar('PN', d, 1)
223
224         deps = (oe.data.getVar("DEPENDS", d, 1) or "").split()
225         provides = Set([pn] + (oe.data.getVar("PROVIDES", d, 1) or "").split())
226
227         for dep in deps:
228             all_depends.add(dep)
229
230         if not pn_provides.has_key(pn):
231             pn_provides[pn] = Set()
232         pn_provides[pn] |= provides
233         
234         for provide in provides:
235             if not providers.has_key(provide):
236                 providers[provide] = []
237             providers[provide].append(f)
238
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
244
245     for f in make.pkgdata.keys():
246         d = make.pkgdata[f]
247         terminal = True
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/'):
251                 terminal = False
252                 break
253         if terminal:
254             __world_target.add(pn)
255
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 ) )
258     sys.stdout.flush()
259
260 #
261 # main
262 #
263
264 if __name__ == "__main__":
265
266     make.options, args = handle_options( sys.argv )
267
268     _depcmds = { "clean": None,
269                 "mrproper": None,
270                 "build": "stage" }
271
272     if not make.options.cmd:
273             make.options.cmd = "build"
274
275     if make.options.cmd in _depcmds:
276             depcmd=_depcmds[make.options.cmd]
277     else:
278             depcmd=make.options.cmd
279
280     make.pkgdata = {}
281     make.cfg = {}
282     providers = {}
283
284     for f in make.options.file:
285         try:
286             make.cfg = oe.parse.handle(f, make.cfg)
287         except IOError:
288             oe.fatal("Unable to open %s" % f)
289
290     try:
291         make.cfg = oe.parse.handle("conf/oe.conf", make.cfg)
292     except IOError:
293         oe.fatal("Unable to open oe.conf")
294
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)
297
298     buildname = oe.data.getVar("BUILDNAME", make.cfg)
299
300     pkgs_to_build = None
301     if args:
302         if not pkgs_to_build:
303             pkgs_to_build = []
304         pkgs_to_build.extend(args)
305     if not pkgs_to_build:
306         oepkgs = oe.data.getVar('OEPKGS', make.cfg, 1)
307         if oepkgs:
308             pkgs_to_build = oepkgs.split()
309     if not pkgs_to_build:
310         print "Nothing to build. Use 'oemake world' to build everything."
311         sys.exit(0)
312
313     __stats["attempt"] = 0
314     __stats["success"] = 0
315     __stats["fail"] = 0
316     __stats["deps"] = 0
317
318     try:
319         make.collect_oefiles( myProgressCallback )
320         print
321         build_depgraph()
322
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)
327
328         oe.event.fire(oe.event.BuildStarted(buildname, pkgs_to_build, make.cfg))
329
330         for k in pkgs_to_build:
331             if buildPackage(k) == 0:
332                 oe.error("Build of " + k + " failed")
333                 if make.options.abort:
334                         sys.exit(1)
335
336         oe.event.fire(oe.event.BuildCompleted(buildname, pkgs_to_build, make.cfg))
337
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:
345             sys.exit(1)
346         sys.exit(0)
347
348     except KeyboardInterrupt:
349         print "\nNOTE: KeyboardInterrupt - Build not completed."