Adapt oemake to follow deps, and keep a cache of packages that we already attempted...
[bitbake.git] / bin / oemake
1 #!/usr/bin/python
2
3 import string, sys, os
4 from oe import *
5
6 class PkgFailed(event.Event):
7         """Package build failed"""
8         type = "PkgFailed"
9
10 class PkgSucceeded(event.Event):
11         """Package build succeeded"""
12         type = "PkgSucceeded"
13
14 def getParents(graph, item):
15         if not graph.hasnode(item):
16                 return None
17         return graph.dict[item][1]
18
19 def follow(graph, item, callback):
20         if not graph.hasnode(item):
21                 return 0
22         keycount = graph.dict[item][0]
23         if keycount != 0 and depcmd is not None:
24                 command=depcmd
25         else:
26                 command=cmd
27         parents = getParents(graph, item)
28         if parents is not None:
29                 for p in parents:
30                         ret = follow(graph, p, callback)
31                         if ret == 0:
32                                 return 0
33         return callback(item, command)
34
35 def addToBuild(data, graph, item):
36         if not graph.hasnode(item):
37                 return 0
38         keycount = graph.dict[item][0]
39         if keycount != 0 and depcmd is not None:
40                 command=depcmd
41         else:
42                 command=cmd
43         parents = getParents(graph, item)
44         if parents is not None:
45                 for p in parents:
46                         addToBuild(data, graph, p)
47         if not [item, command] in data:
48                 data.append([item, command])
49         return 1
50
51 _depcmds = { "clean": None,
52             "mrproper": None, }
53
54 cmd="package"
55
56 if _depcmds.has_key(cmd):
57         depcmd=depcmds[cmd]
58 else:
59         depcmd="stage"
60
61 pkgdata = {}
62 pkgs = {}
63 cfg = {}
64 graph = digraph()
65
66 parse.init(".conf", cfg)
67 data.setVarFlag("OEFILES", "inherit", "1", cfg)
68 data.setVarFlag("OEDIR", "inherit", "1", cfg)
69 data.setVarFlag("OEPATH", "inherit", "1", cfg)
70 data.setVarFlag("PATH", "inherit", "1", cfg)
71 data.inheritFromOS(1, cfg)
72
73 try:
74         cfg = parse.handle("conf/oe.conf", cfg) # Read configuration
75 except IOError:
76         fatal("Unable to open oe.conf")
77
78 oefiles = data.getVar("OEFILES", cfg)
79 if oefiles is not None:
80         files = oefiles.split()
81 else:
82         fatal("OEFILES not defined")
83
84 #set_automatic_vars(sys.argv[2], )                      # Deduce per-package environment variables
85
86 #pkg = [ "pkgname", "depends", "provides" ]
87
88 for f in files:
89         # read a file's metadata
90         (root, ext) = os.path.splitext(f)
91         try:
92                 from copy import copy
93                 pkgdata[f] = parse.handle(f, copy(cfg))
94                 deps = None
95                 if pkgdata[f] is not None:
96                         depstr = data.getVar("DEPENDS", pkgdata[f])
97                         if depstr is not None:
98                                 deps = depstr.split()
99                         provides = data.getVar("PROVIDES", pkgdata[f])
100                         if provides is not None:
101                                 provides = provides.split()
102                                 for provide in provides:
103                                         pkgs[provide] = [[root], None]
104                         pkgs[root] = [deps, f]
105 #               if pkgdata[f] is not None:
106 #                       data.emit_env(sys.__stdout__, pkgdata[f])
107         except IOError:
108                 print "error opening %s" % f
109                 pass
110
111 # default provides.. a package provides itself, with and without
112 # version and revision
113
114 # add every provide relationship to the dependency graph, depending
115 # on all the packages that provide it
116
117 for pkg in pkgs.keys():
118 #       print "graph.addnode(%s, %s)" % (pkg, None)
119         graph.addnode(pkg, None)
120
121 for pkg in pkgs.keys():
122         (deps, fn) = pkgs[pkg]
123         if deps is not None:
124                 for d in deps:
125 #                       print "graph.addnode(%s, %s)" % (pkg, d)
126                         graph.addnode(pkg, d)
127         
128 # Then, start the build for that package.  Note that because
129 # we've already loaded the files, we may as well spawn the build
130 # directly.. so lets abstract the task handling bits into a
131 # module that both oebuild and oemake can utilize.
132
133 data = []
134 for k in graph.okeys:
135         addToBuild(data, graph, k)
136
137 __build_cache_fail = []
138 __build_cache = []
139 def build(item, command):
140         if item in __build_cache:
141                 return 1
142         if item in __build_cache_fail:
143                 return 0
144         fn = pkgs[item][1]
145         if fn is None:
146                 return 1
147         note("oebuild %s %s" % (command, fn))
148         ret = os.system("oebuild %s %s" % (command, fn))
149         if ret == 0:
150                 __build_cache.append(item)
151                 return 1
152         else:
153                 __build_cache_fail.append(item)
154                 return 0
155         
156 for k in graph.okeys:
157         follow(graph, k, build)
158
159 #for d in data:
160 #       (pkg, step) = d 
161 #       if pkgs[pkg][1] is not None:
162 #               note("oebuild %s %s" % (step, pkgs[pkg][1]))
163 #               os.system("oebuild %s %s" % (step, pkgs[pkg][1]))