Update oebuild and oemake usage information
[bitbake.git] / bin / oemake
1 #!/usr/bin/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         ret = os.system("oebuild %s %s" % (command, fn))
116         if ret == 0:
117                 event.fire(PkgSucceeded(item, pkgdata[fn]))
118                 __build_cache.append(item)
119                 return 1
120         else:
121                 event.fire(PkgFailed(item, pkgdata[fn]))
122                 __build_cache_fail.append(item)
123                 return 0
124
125 def usage():
126         print "Usage: oemake [options] [oefile ...]"
127 #       print "Run TASK on OEFILE or standard input if OEFILE is -."
128         print "Run OEBuild's build task on a set of oe files, following"
129         print "inter-package dependencies."
130         print "Also obtains .oe files to build from the OEFILES environment variable."
131         print "Default OEFILES is the oefiles in the current directory."
132         print "Example: oemake content/glibc-2.3.1.oe content/patcher-1.0.oe"
133         print ""
134         print "  %s\t\t%s" % ("-v, --version", "output version information and exit")
135         print "  %s\t\t%s" % ("-c [arg], --cmd [arg]", "specify command to pass to oebuild")
136         sys.exit(0)
137
138 __version__ = 1.0
139 def version():
140         print "OpenEmbedded Build Infrastructure Core version %s" % oe.__version__
141         print "OEMake version %s" % __version__
142
143 def get_oefiles():
144         """Get default oefiles"""
145         dirs = os.listdir(os.getcwd())
146         oefiles = []
147         for f in dirs:
148                 (root, ext) = os.path.splitext(f)
149                 if ext == ".oe":
150                         oefiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
151         return oefiles
152
153 def get_oefile():
154         """Get default oefile"""
155         oefiles = get_oefiles()
156         if len(oefiles):
157                 return oefiles[0]
158         else:
159                 return None
160
161
162 import getopt
163 try:
164         (opts, args) = getopt.getopt(sys.argv[1:], 'vc:', [ 'version', 'cmd=' ])
165 except getopt.GetoptError:
166         usage()
167
168 # handle opts
169 optsonly = [ opt for (opt,val) in opts]
170 cmd = None
171
172 def getopthash(l):
173         h = {}
174         for (opt, val) in l:
175                 h[opt] = val
176         return h
177
178 opthash = getopthash(opts)
179
180 if opthash.has_key('--version') or opthash.has_key('-v'):
181         version()
182         sys.exit(0)
183
184 if opthash.has_key('--cmd'):
185         cmd = opthash['--cmd']
186 if opthash.has_key('-c'):
187         cmd = opthash['-c']
188
189 _depcmds = { "clean": None,
190              "mrproper": None,
191              "build": "stage", }
192
193 if not cmd:
194         cmd = "build"
195
196 if _depcmds.has_key(cmd):
197         depcmd=_depcmds[cmd]
198 else:
199         depcmd=cmd
200
201 pkgdata = {}
202 pkgs = {}
203 cfg = {}
204 graph = digraph()
205
206 try:
207         cfg = parse.handle("conf/oe.conf", cfg) # Read configuration
208 except IOError:
209         fatal("Unable to open oe.conf")
210
211 if not data.getVar("BUILDNAME", cfg):
212         data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), cfg)
213
214 buildname = data.getVar("BUILDNAME", cfg)
215
216 # grab oefiles
217 files = string.split(data.getVar("OEFILES", cfg, 1) or "")
218 files += args
219 data.setVar("OEFILES", string.join(files), cfg)
220
221 if not len(files):
222         files = get_oefiles()
223
224 if not len(files):
225         usage()
226
227 #set_automatic_vars(sys.argv[2], )                      # Deduce per-package environment variables
228
229 #pkg = [ "pkgname", "depends", "provides" ]
230
231 import glob
232 for f in files:
233         globbed = glob.glob(f) or [ f ]
234         if globbed:
235                 if [ f ] != globbed:
236                         files += globbed
237                         continue
238         # read a file's metadata
239         try:
240                 from copy import deepcopy
241                 pkgdata[f] = parse.handle(f, deepcopy(cfg))
242                 deps = None
243                 if pkgdata[f] is not None:
244                         # allow metadata files to add items to OEFILES
245                         data.update_data(pkgdata[f])
246                         addoefiles = data.getVar('OEFILES', pkgdata[f]) or None
247                         if addoefiles:
248                                 for aof in string.split(addoefiles):
249                                         if not files.count(aof):
250                                                 if not os.path.isabs(aof):
251                                                         aof = os.path.join(os.path.dirname(f),aof)
252                                                 files.append(aof)
253                         for var in pkgdata[f].keys():
254                                 if data.getVarFlag(var, "handler", pkgdata[f]) and data.getVar(var, pkgdata[f]):
255                                         event.register(data.getVar(var, pkgdata[f]))
256                         depstr = data.getVar("DEPENDS", pkgdata[f], 1)
257                         if depstr is not None:
258                                 deps = depstr.split()
259                         pkg = []
260                         pkg.append(data.getVar('CATEGORY', pkgdata[f], 1))
261                         pkg.append(data.getVar('PN', pkgdata[f], 1))
262                         pkg.append(data.getVar('PV', pkgdata[f], 1))
263                         pkg.append(data.getVar('PR', pkgdata[f], 1))
264                         root = "%s/%s-%s-%s" % (pkg[0], pkg[1], pkg[2], pkg[3])
265                         provides = []
266                         # w/ category
267                         provides.append("%s/%s-%s" % (pkg[0], pkg[1], pkg[2]))
268                         provides.append("%s/%s" % (pkg[0], pkg[1]))
269                         # w/o category
270                         provides.append("%s" % pkg[1])
271                         provides.append("%s-%s" % (pkg[1], pkg[2]))
272                         provides.append("%s-%s-%s" % (pkg[1], pkg[2], pkg[3]))
273                         providestr = data.getVar("PROVIDES", pkgdata[f])
274                         if providestr is not None:
275                                 provides += providestr.split()
276                         for provide in provides:
277                                 pkgs[provide] = [[root], None]
278                         pkgs[root] = [deps, f]
279         except IOError:
280                 print "error opening %s" % f
281                 pass
282
283 # add every provide relationship to the dependency graph, depending
284 # on all the packages that provide it
285
286 global __tokill
287 global __unsatisfied
288 __tokill = []
289 __unsatisfied = []
290
291 for pkg in pkgs.keys():
292         graph.addnode(pkg, None)
293
294 for pkg in pkgs.keys():
295         (deps, fn) = pkgs[pkg]
296         if _depcmds[cmd] is not None:
297                 if deps is not None:
298                         for d in deps:
299                                 if not graph.hasnode(d):
300                                         def killitem(graph, item):
301                                                 global __tokill
302                                                 __tokill.append(item)
303                                         graph.walkup(pkg, killitem)
304                                         __unsatisfied.append([pkg, d])
305                                         break
306                                 graph.addnode(pkg, d)
307
308 for u in __unsatisfied:
309         event.fire(UnsatisfiedDep(u[0], pkgdata[pkgs[u[0]][1]], u[1]))
310
311 for k in __tokill:
312         def reallykillitem(graph, item):
313                 graph.delnode(item)
314         graph.walkup(k, reallykillitem)
315
316 event.fire(BuildStarted(buildname, graph.okeys, cfg))
317
318 for k in graph.okeys:
319         graph.walkdown(k, build)
320
321 event.fire(BuildCompleted(buildname, graph.okeys, cfg))