Output what file oemake is parsing..
[bitbake.git] / bin / oemake
1 #!/usr/bin/env python
2
3 import string, sys, os
4 sys.path.append('/usr/share/oe')
5 from oe import *
6 import oe
7
8 class PkgBase(event.Event):
9         """Base class for package events"""
10
11         def __init__(self, t, d = {}):
12                 self.pkg = t
13                 self.data = d
14
15         def getPkg(self):
16                 return self._pkg
17
18         def setPkg(self, pkg):
19                 self._pkg = pkg
20
21         pkg = property(getPkg, setPkg, None, "pkg property")
22
23         def getData(self):
24                 return self._data
25
26         def setData(self, data):
27                 self._data = data
28
29         data = property(getData, setData, None, "data property")
30
31 class BuildBase(event.Event):
32         """Base class for oemake run events"""
33
34         def __init__(self, n, p, c):
35                 self.name = n
36                 self.pkgs = p
37                 self.cfg = c
38
39         def getPkgs(self):
40                 return self._pkgs
41
42         def setPkgs(self, pkgs):
43                 self._pkgs = pkgs
44
45         pkgs = property(getPkgs, setPkgs, None, "pkgs property")
46
47         def getName(self):
48                 return self._name
49
50         def setName(self, name):
51                 self._name = name
52
53         name = property(getName, setName, None, "name property")
54
55         def getCfg(self):
56                 return self._cfg
57
58         def setCfg(self, cfg):
59                 self._cfg = cfg
60
61         cfg = property(getCfg, setCfg, None, "cfg property")
62
63 class DepBase(PkgBase):
64         """Base class for dependency events"""
65
66         def __init__(self, t, data, d):
67                 self.dep = d
68                 PkgBase.__init__(self, t, data)
69
70         def getDep(self):
71                 return self._dep
72
73         def setDep(self, dep):
74                 self._dep = dep
75
76         dep = property(getDep, setDep, None, "dep property")
77         
78 class PkgStarted(PkgBase):
79         """Package build started"""
80
81 class PkgFailed(PkgBase):
82         """Package build failed"""
83
84 class PkgSucceeded(PkgBase):
85         """Package build succeeded"""
86
87 class BuildStarted(BuildBase):
88         """oemake build run started"""
89
90 class BuildCompleted(BuildBase):
91         """oemake build run completed"""
92
93 class UnsatisfiedDep(DepBase):
94         """Unsatisfied Dependency"""
95
96 class RecursiveDep(DepBase):
97         """Recursive Dependency"""
98
99 class MultipleProviders(PkgBase):
100         """Multiple Providers"""
101
102 __build_cache_fail = []
103 __build_cache = []
104 def build(graph, item):
105         if item in __build_cache:
106                 return 1
107         if item in __build_cache_fail:
108                 return 0
109         fn = pkgs[item][1]
110         if fn is None:
111                 return 1
112         command = cmd
113         debug(1, "oebuild %s %s" % (command, fn))
114         event.fire(PkgStarted(item, pkgdata[fn]))
115         opts = ""
116         if force:
117                 opts += " --force"
118         ret = os.system("oebuild %s %s %s" % (opts, command, fn))
119         if ret == 0:
120                 event.fire(PkgSucceeded(item, pkgdata[fn]))
121                 __build_cache.append(item)
122                 return 1
123         else:
124                 event.fire(PkgFailed(item, pkgdata[fn]))
125                 __build_cache_fail.append(item)
126                 return 0
127
128 def usage():
129         print "Usage: oemake [options] [package ...]"
130         print ""
131         print "Builds specified packages, expecting that the .oe files"
132         print "it has to work from are in OEFILES"
133         print "Default packages are all packages in OEFILES."
134         print "Default OEFILES are the .oe files in the current directory."
135         print "Example: oemake glibc"
136         print "Example: oemake ncurses-5.3"
137         print ""
138         print "  %s\t\t%s" % ("-v, --version", "output version information and exit")
139         print "  %s\t\t%s" % ("-c [arg], --cmd [arg]", "specify command to pass to oebuild")
140         print "  %s\t\t%s" % ("-a, --abort", "abort build if any package build fails")
141         print "  %s\t\t%s" % ("-f, --force", "force run of specified cmd, regardless of status")
142         sys.exit(0)
143
144 __version__ = 1.1
145 def version():
146         print "OpenEmbedded Build Infrastructure Core version %s" % oe.__version__
147         print "OEMake version %s" % __version__
148
149 def get_oefiles():
150         """Get default oefiles"""
151         dirs = os.listdir(os.getcwd())
152         oefiles = []
153         for f in dirs:
154                 (root, ext) = os.path.splitext(f)
155                 if ext == ".oe":
156                         oefiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
157         return oefiles
158
159 def get_oefile():
160         """Get default oefile"""
161         oefiles = get_oefiles()
162         if len(oefiles):
163                 return oefiles[0]
164         else:
165                 return None
166
167 def load_oefile(oefile, cfgdata):
168         oepath = data.getVar('OEPATH', cfg)
169         topdir = data.getVar('TOPDIR', cfg)
170         if not topdir:
171                 topdir = os.path.abspath(os.getcwd())
172                 # set topdir to here
173                 data.setVar('TOPDIR', topdir, cfg)
174         oefile = os.path.abspath(oefile)
175         oefile_loc = os.path.abspath(os.path.dirname(oefile))
176         # expand tmpdir to include this topdir
177         data.setVar('TMPDIR', data.getVar('TMPDIR', cfg, 1) or "", cfg)
178         # add topdir to oepath
179         oepath += ":%s" % topdir
180         # set topdir to location of .oe file
181         topdir = oefile_loc
182         #data.setVar('TOPDIR', topdir, cfg)
183         # add that topdir to oepath
184         oepath += ":%s" % topdir
185         # go there
186         oldpath = os.path.abspath(os.getcwd())
187         os.chdir(topdir)
188         data.setVar('OEPATH', oepath, cfg)
189         from copy import deepcopy
190         oe = deepcopy(cfgdata)
191         try:
192                 parse.handle(oefile, oe) # read .oe data
193                 os.chdir(oldpath)
194                 return oe
195         except IOError, OSError:
196                 os.chdir(oldpath)
197                 return None
198
199 import getopt
200 try:
201         (opts, args) = getopt.getopt(sys.argv[1:], 'vc:fa', [ 'version', 'cmd=', 'abort', 'force' ])
202 except getopt.GetoptError:
203         usage()
204
205 # handle opts
206 optsonly = [ opt for (opt,val) in opts]
207 cmd = None
208
209 def getopthash(l):
210         h = {}
211         for (opt, val) in l:
212                 h[opt] = val
213         return h
214
215 opthash = getopthash(opts)
216
217 if opthash.has_key('--version') or opthash.has_key('-v'):
218         version()
219         sys.exit(0)
220
221 if opthash.has_key('--abort') or opthash.has_key('-a'):
222         abort = 1
223 else:
224         abort = 0
225
226 if opthash.has_key('--force') or opthash.has_key('-f'):
227         force = 1
228 else:
229         force = 0
230
231 if opthash.has_key('--cmd'):
232         cmd = opthash['--cmd']
233 if opthash.has_key('-c'):
234         cmd = opthash['-c']
235
236 _depcmds = { "clean": None,
237              "mrproper": None,
238              "build": "stage" }
239
240 if not cmd:
241         cmd = "build"
242
243 if _depcmds.has_key(cmd):
244         depcmd=_depcmds[cmd]
245 else:
246         depcmd=cmd
247
248 pkgdata = {}
249 pkgs = {}
250 cfg = {}
251 graph = digraph()
252
253 try:
254         cfg = parse.handle("conf/oe.conf", cfg) # Read configuration
255 except IOError:
256         fatal("Unable to open oe.conf")
257
258 if not data.getVar("BUILDNAME", cfg):
259         data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), cfg)
260
261 buildname = data.getVar("BUILDNAME", cfg)
262
263 # grab oefiles
264 files = string.split(data.getVar("OEFILES", cfg, 1) or "")
265 data.setVar("OEFILES", string.join(files), cfg)
266
267 if not len(files):
268         files = get_oefiles()
269
270 if not len(files):
271         usage()
272
273 import glob
274 for f in files:
275         globbed = glob.glob(f) or [ f ]
276         if globbed:
277                 if [ f ] != globbed:
278                         files += globbed
279                         continue
280         # read a file's metadata
281         try:
282                 from copy import deepcopy
283                 debug(1, "oemake: parsing %s" % f)
284                 pkgdata[f] = load_oefile(f, cfg)
285                 deps = None
286                 if pkgdata[f] is not None:
287                         # allow metadata files to add items to OEFILES
288                         #data.update_data(pkgdata[f])
289                         addoefiles = data.getVar('OEFILES', pkgdata[f]) or None
290                         if addoefiles:
291                                 for aof in string.split(addoefiles):
292                                         if not files.count(aof):
293                                                 if not os.path.isabs(aof):
294                                                         aof = os.path.join(os.path.dirname(f),aof)
295                                                 files.append(aof)
296                         for var in pkgdata[f].keys():
297                                 if data.getVarFlag(var, "handler", pkgdata[f]) and data.getVar(var, pkgdata[f]):
298                                         event.register(data.getVar(var, pkgdata[f]))
299                         depstr = data.getVar("DEPENDS", pkgdata[f], 1)
300                         if depstr is not None:
301                                 deps = depstr.split()
302                         pkg = []
303                         pkg.append(data.getVar('CATEGORY', pkgdata[f], 1))
304                         pkg.append(data.getVar('PN', pkgdata[f], 1))
305                         pkg.append(data.getVar('PV', pkgdata[f], 1))
306                         pkg.append(data.getVar('PR', pkgdata[f], 1))
307                         root = "%s/%s-%s-%s" % (pkg[0], pkg[1], pkg[2], pkg[3])
308                         provides = []
309                         providestr = data.getVar("PROVIDES", pkgdata[f], 1)
310                         if providestr is not None:
311                                 provides += providestr.split()
312                         for provide in provides:
313                                 pkgs[provide] = [[root], None]
314                         pkgs[root] = [deps, f]
315         except IOError:
316                 print "error opening %s" % f
317                 pass
318
319 # add every provide relationship to the dependency graph, depending
320 # on all the packages that provide it
321
322 global __tokill
323 global __unsatisfied
324 __tokill = []
325 __unsatisfied = []
326
327 for pkg in pkgs.keys():
328         graph.addnode(pkg, None)
329
330 for pkg in pkgs.keys():
331         (deps, fn) = pkgs[pkg]
332         if depcmd is not None:
333                 if deps is not None:
334                         for d in deps:
335                                 if not graph.hasnode(d):
336                                         def killitem(graph, item):
337                                                 global __tokill
338                                                 __tokill.append(item)
339                                         graph.walkup(pkg, killitem)
340                                         __unsatisfied.append([pkg, d])
341                                         break
342                                 graph.addnode(pkg, d)
343
344 for u in __unsatisfied:
345         event.fire(UnsatisfiedDep(u[0], pkgdata[pkgs[u[0]][1]], u[1]))
346
347 for k in __tokill:
348         def reallykillitem(graph, item):
349                 graph.delnode(item)
350         graph.walkup(k, reallykillitem)
351
352 event.fire(BuildStarted(buildname, graph.okeys, cfg))
353
354 pkgs_to_build = None
355 if args:
356         if not pkgs_to_build:
357                 pkgs_to_build = []
358         pkgs_to_build.extend(args)
359 if not pkgs_to_build:
360         oepkgs = data.getVar('OEPKGS', cfg, 1)
361         if oepkgs:
362                 pkgs_to_build = string.split(oepkgs)
363 if not pkgs_to_build:
364         pkgs_to_build = graph.okeys
365 debug(1, "building: %s" % pkgs_to_build)
366
367 for k in pkgs_to_build:
368         if pkgs.has_key(k):
369                 ret = graph.walkdown(k, build)
370                 if abort and not ret:
371                         oe.fatal("Build of %s failed, aborting." % k)
372         else:
373                 oe.error("Unable to build %s: no .oe file provides it." % k)
374                 if abort:
375                         sys.exit(1)
376 event.fire(BuildCompleted(buildname, graph.okeys, cfg))