Delete: doc/DIRSnVARS
[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] [package ...]"
127         print ""
128         print "Builds specified packages, expecting that the .oe files"
129         print "it has to work from are in OEFILES"
130         print "Default packages are all packages in OEFILES."
131         print "Default OEFILES are the .oe files in the current directory."
132         print "Example: oemake glibc"
133         print "Example: oemake ncurses-5.3"
134         print ""
135         print "  %s\t\t%s" % ("-v, --version", "output version information and exit")
136         print "  %s\t\t%s" % ("-c [arg], --cmd [arg]", "specify command to pass to oebuild")
137         sys.exit(0)
138
139 __version__ = 1.1
140 def version():
141         print "OpenEmbedded Build Infrastructure Core version %s" % oe.__version__
142         print "OEMake version %s" % __version__
143
144 def get_oefiles():
145         """Get default oefiles"""
146         dirs = os.listdir(os.getcwd())
147         oefiles = []
148         for f in dirs:
149                 (root, ext) = os.path.splitext(f)
150                 if ext == ".oe":
151                         oefiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
152         return oefiles
153
154 def get_oefile():
155         """Get default oefile"""
156         oefiles = get_oefiles()
157         if len(oefiles):
158                 return oefiles[0]
159         else:
160                 return None
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 data.setVar("OEFILES", string.join(files), cfg)
219
220 if not len(files):
221         files = get_oefiles()
222
223 if not len(files):
224         usage()
225
226 import glob
227 for f in files:
228         globbed = glob.glob(f) or [ f ]
229         if globbed:
230                 if [ f ] != globbed:
231                         files += globbed
232                         continue
233         # read a file's metadata
234         try:
235                 from copy import deepcopy
236                 pkgdata[f] = parse.handle(f, deepcopy(cfg))
237                 deps = None
238                 if pkgdata[f] is not None:
239                         # allow metadata files to add items to OEFILES
240                         data.update_data(pkgdata[f])
241                         addoefiles = data.getVar('OEFILES', pkgdata[f]) or None
242                         if addoefiles:
243                                 for aof in string.split(addoefiles):
244                                         if not files.count(aof):
245                                                 if not os.path.isabs(aof):
246                                                         aof = os.path.join(os.path.dirname(f),aof)
247                                                 files.append(aof)
248                         for var in pkgdata[f].keys():
249                                 if data.getVarFlag(var, "handler", pkgdata[f]) and data.getVar(var, pkgdata[f]):
250                                         event.register(data.getVar(var, pkgdata[f]))
251                         depstr = data.getVar("DEPENDS", pkgdata[f], 1)
252                         if depstr is not None:
253                                 deps = depstr.split()
254                         pkg = []
255                         pkg.append(data.getVar('CATEGORY', pkgdata[f], 1))
256                         pkg.append(data.getVar('PN', pkgdata[f], 1))
257                         pkg.append(data.getVar('PV', pkgdata[f], 1))
258                         pkg.append(data.getVar('PR', pkgdata[f], 1))
259                         root = "%s/%s-%s-%s" % (pkg[0], pkg[1], pkg[2], pkg[3])
260                         provides = []
261                         # w/ category
262                         provides.append("%s/%s-%s" % (pkg[0], pkg[1], pkg[2]))
263                         provides.append("%s/%s" % (pkg[0], pkg[1]))
264                         # w/o category
265                         provides.append("%s" % pkg[1])
266                         provides.append("%s-%s" % (pkg[1], pkg[2]))
267                         provides.append("%s-%s-%s" % (pkg[1], pkg[2], pkg[3]))
268                         providestr = data.getVar("PROVIDES", pkgdata[f], 1)
269                         if providestr is not None:
270                                 provides += providestr.split()
271                         for provide in provides:
272                                 pkgs[provide] = [[root], None]
273                         pkgs[root] = [deps, f]
274         except IOError:
275                 print "error opening %s" % f
276                 pass
277
278 # add every provide relationship to the dependency graph, depending
279 # on all the packages that provide it
280
281 global __tokill
282 global __unsatisfied
283 __tokill = []
284 __unsatisfied = []
285
286 for pkg in pkgs.keys():
287         graph.addnode(pkg, None)
288
289 for pkg in pkgs.keys():
290         (deps, fn) = pkgs[pkg]
291         if _depcmds[cmd] is not None:
292                 if deps is not None:
293                         for d in deps:
294                                 if not graph.hasnode(d):
295                                         def killitem(graph, item):
296                                                 global __tokill
297                                                 __tokill.append(item)
298                                         graph.walkup(pkg, killitem)
299                                         __unsatisfied.append([pkg, d])
300                                         break
301                                 graph.addnode(pkg, d)
302
303 for u in __unsatisfied:
304         event.fire(UnsatisfiedDep(u[0], pkgdata[pkgs[u[0]][1]], u[1]))
305
306 for k in __tokill:
307         def reallykillitem(graph, item):
308                 graph.delnode(item)
309         graph.walkup(k, reallykillitem)
310
311 event.fire(BuildStarted(buildname, graph.okeys, cfg))
312 packages = args or graph.okeys
313
314 for k in packages:
315         if pkgs.has_key(k):
316                 graph.walkdown(k, build)
317         else:
318                 oe.error("Unable to build %s: no .oe file provides it." % k)
319
320 event.fire(BuildCompleted(buildname, graph.okeys, cfg))