Merge lp:~steve-mcintyre/linaro-chromiumos/python-rewrite into lp:linaro-chromiumos
- python-rewrite
- Merge into trunk
Proposed by
Steve McIntyre
Status: | Merged |
---|---|
Merged at revision: | 14 |
Proposed branch: | lp:~steve-mcintyre/linaro-chromiumos/python-rewrite |
Merge into: | lp:linaro-chromiumos |
Diff against target: |
350 lines (+278/-53) 4 files modified
remote/run_build (+0/-14) remote/run_build.py (+59/-0) remote/setup_build (+0/-39) remote/setup_build.py (+219/-0) |
To merge this branch: | bzr merge lp:~steve-mcintyre/linaro-chromiumos/python-rewrite |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Loïc Minier | Pending | ||
Review via email: mp+54250@code.launchpad.net |
Commit message
Description of the change
Rewrite in python.
Adding more features for better control of what we're building and where.
To post a comment you must log in.
- 14. By Steve McIntyre
-
Add creation of the top-level work area, using sudo to make sure it succeeds.
Revision history for this message
Loïc Minier (lool) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === removed file 'remote/run_build' | |||
2 | --- remote/run_build 2011-03-09 17:35:56 +0000 | |||
3 | +++ remote/run_build 1970-01-01 00:00:00 +0000 | |||
4 | @@ -1,14 +0,0 @@ | |||
5 | 1 | #!/bin/sh | ||
6 | 2 | |||
7 | 3 | set -e | ||
8 | 4 | |||
9 | 5 | ./setup_board --board x86-generic | ||
10 | 6 | ./build_packages --board x86-generic | ||
11 | 7 | |||
12 | 8 | # <wait a long time> | ||
13 | 9 | |||
14 | 10 | ./build_image --board x86-generic --noenable_rootfs_verification | ||
15 | 11 | |||
16 | 12 | # <wait a long time> | ||
17 | 13 | # Success? | ||
18 | 14 | |||
19 | 15 | 0 | ||
20 | === added file 'remote/run_build.py' | |||
21 | --- remote/run_build.py 1970-01-01 00:00:00 +0000 | |||
22 | +++ remote/run_build.py 2011-03-23 14:06:22 +0000 | |||
23 | @@ -0,0 +1,59 @@ | |||
24 | 1 | #!/usr/bin/python | ||
25 | 2 | # | ||
26 | 3 | # Simple wrapper build script for Chromium OS builds | ||
27 | 4 | # | ||
28 | 5 | # Copyright (C) 2011 Linaro | ||
29 | 6 | # | ||
30 | 7 | # GPL v2+ | ||
31 | 8 | |||
32 | 9 | import os | ||
33 | 10 | import getopt | ||
34 | 11 | import sys | ||
35 | 12 | import warnings | ||
36 | 13 | import errno | ||
37 | 14 | import shutil | ||
38 | 15 | |||
39 | 16 | options = {} | ||
40 | 17 | options['logdir'] = '' | ||
41 | 18 | options['board-type'] = 'x86-generic' | ||
42 | 19 | options['nousepkg'] = False | ||
43 | 20 | |||
44 | 21 | try: | ||
45 | 22 | opts, args = getopt.getopt(sys.argv[1:], "", | ||
46 | 23 | ["logdir=", | ||
47 | 24 | "board-type=", | ||
48 | 25 | "nousepkg="]) | ||
49 | 26 | except getopt.GetoptError, err: | ||
50 | 27 | # print help information and exit: | ||
51 | 28 | print str(err) # will print something like "option -a not recognized" | ||
52 | 29 | usage() | ||
53 | 30 | sys.exit(2) | ||
54 | 31 | |||
55 | 32 | for o, a in opts: | ||
56 | 33 | options[o[2:]] = a | ||
57 | 34 | |||
58 | 35 | |||
59 | 36 | if not options['logdir'] == '': | ||
60 | 37 | os.environ['PORT_LOGDIR'] = options['logdir'] | ||
61 | 38 | try: | ||
62 | 39 | os.environ['FEATURES'] = os.environ['FEATURES'] + ' binpkg-logs' | ||
63 | 40 | except: | ||
64 | 41 | os.environ['FEATURES'] = 'binpkg-logs' | ||
65 | 42 | os.system('sudo rm -rf %s'% options['logdir']) | ||
66 | 43 | os.system('sudo mkdir %s' % options['logdir']) | ||
67 | 44 | |||
68 | 45 | build_options = '' | ||
69 | 46 | build_options += ' --board=%s' % options['board-type'] | ||
70 | 47 | if options['nousepkg']: | ||
71 | 48 | build_options += ' --nousepkg' | ||
72 | 49 | |||
73 | 50 | os.system('./setup_board --force %s' % build_options) | ||
74 | 51 | os.system('./build_packages %s' % build_options) | ||
75 | 52 | |||
76 | 53 | # <wait a long time> | ||
77 | 54 | image_options = ' --noenable_rootfs_verification ' | ||
78 | 55 | image_options += ' --board=%s' % options['board-type'] | ||
79 | 56 | os.system('./build_image %s' % image_options) | ||
80 | 57 | |||
81 | 58 | # <wait a long time> | ||
82 | 59 | # Success? | ||
83 | 0 | 60 | ||
84 | === removed file 'remote/setup_build' | |||
85 | --- remote/setup_build 2011-03-09 17:35:56 +0000 | |||
86 | +++ remote/setup_build 1970-01-01 00:00:00 +0000 | |||
87 | @@ -1,39 +0,0 @@ | |||
88 | 1 | #!/bin/sh | ||
89 | 2 | |||
90 | 3 | set -e | ||
91 | 4 | |||
92 | 5 | MANIFEST=$1 | ||
93 | 6 | if [ "$MANIFEST"x = "" ] ; then | ||
94 | 7 | MANIFEST=http://git.chromium.org/git/manifest | ||
95 | 8 | fi | ||
96 | 9 | |||
97 | 10 | BASEDIR=`dirname $0` | ||
98 | 11 | WDIR=/mnt/chromeos | ||
99 | 12 | |||
100 | 13 | # Basic setup | ||
101 | 14 | export LC_ALL=C | ||
102 | 15 | sudo apt-get update | ||
103 | 16 | sudo apt-get install git subversion build-essential | ||
104 | 17 | |||
105 | 18 | # Make working directory | ||
106 | 19 | if [ ! -d $WDIR ] ; then | ||
107 | 20 | sudo mkdir $WDIR | ||
108 | 21 | sudo chown ubuntu: $WDIR | ||
109 | 22 | fi | ||
110 | 23 | |||
111 | 24 | # Grab basic stuff | ||
112 | 25 | cd $WDIR | ||
113 | 26 | svn co http://src.chromium.org/svn/trunk/tools/depot_tools | ||
114 | 27 | export PATH=$PATH:$PWD/depot_tools | ||
115 | 28 | |||
116 | 29 | # Start grabbing source | ||
117 | 30 | repo init -u $MANIFEST | ||
118 | 31 | repo sync | ||
119 | 32 | |||
120 | 33 | # Set up the working chroot | ||
121 | 34 | /mnt/chromeos/src/scripts/make_chroot --chroot=chroot-x86 | ||
122 | 35 | cp $BASEDIR/run_build chroot-x86/src/scripts | ||
123 | 36 | |||
124 | 37 | # Now chroot into it and do stuff | ||
125 | 38 | script -c "/mnt/chromeos/src/scripts/enter_chroot.sh --chroot=chroot-x86 -- ./run_build" cros-build.log | ||
126 | 39 | |||
127 | 40 | 0 | ||
128 | === added file 'remote/setup_build.py' | |||
129 | --- remote/setup_build.py 1970-01-01 00:00:00 +0000 | |||
130 | +++ remote/setup_build.py 2011-03-23 14:06:22 +0000 | |||
131 | @@ -0,0 +1,219 @@ | |||
132 | 1 | #!/usr/bin/python | ||
133 | 2 | # | ||
134 | 3 | # Simple setup script for Chromium OS builds | ||
135 | 4 | # | ||
136 | 5 | # Copyright (C) 2011 Linaro | ||
137 | 6 | # | ||
138 | 7 | # GPL v2+ | ||
139 | 8 | |||
140 | 9 | import os | ||
141 | 10 | import getopt | ||
142 | 11 | import sys | ||
143 | 12 | import warnings | ||
144 | 13 | import errno | ||
145 | 14 | import shutil | ||
146 | 15 | |||
147 | 16 | # Set defaults for options | ||
148 | 17 | options = {} | ||
149 | 18 | options['build-name'] = 'build' | ||
150 | 19 | options['board-type'] = 'x86-generic' | ||
151 | 20 | options['use-network'] = True | ||
152 | 21 | options['working-dir'] = '' | ||
153 | 22 | #options['toolchain'] = 'default' | ||
154 | 23 | options['manifest'] = 'http://git.chromium.org/git/manifest' | ||
155 | 24 | options['nousepkg'] = False | ||
156 | 25 | options['build-script'] = 'run_build.py' | ||
157 | 26 | |||
158 | 27 | commands = 'create_tree get_source create_chroot build'.split() | ||
159 | 28 | |||
160 | 29 | def usage(): | ||
161 | 30 | print "%s\n" % sys.argv[0] | ||
162 | 31 | print "usage:\n" | ||
163 | 32 | print " setup_build.py [options] <command>\n" | ||
164 | 33 | print " options include:\n" | ||
165 | 34 | print " --working-dir=<name>" | ||
166 | 35 | print " specify a base location for a working directory" | ||
167 | 36 | print " (default is \"%s\")" % options['working-dir'] | ||
168 | 37 | print " --build-name=<name>" | ||
169 | 38 | print " specify a name to use for this build" | ||
170 | 39 | print " (default is \"%s\")" % options['build-name'] | ||
171 | 40 | print " --board-type=<board>" | ||
172 | 41 | print " specify the target board/platform" | ||
173 | 42 | print " (default is \"%s\")" % options['board-type'] | ||
174 | 43 | print " --use-network=<true|false>" | ||
175 | 44 | print " should network access be allowed during the build?" | ||
176 | 45 | print " (default is %s)" % options['use-network'] | ||
177 | 46 | print " --toolchain=<toolchain>" | ||
178 | 47 | print " choice of toolchain. Not yet implemented." | ||
179 | 48 | print " --manifest=<manifest URL>" | ||
180 | 49 | print " specify the manifest file to use" | ||
181 | 50 | print " (default is \"%s\")" % options['manifest'] | ||
182 | 51 | print " --nousepkg=<true|false>" | ||
183 | 52 | print " force building of everything from source" | ||
184 | 53 | print " needed if --use-network==true or if using a new toolchain" | ||
185 | 54 | print " (default is \"%s\")" % options['nousepkg'] | ||
186 | 55 | |||
187 | 56 | print "commands:\n" | ||
188 | 57 | print " create_tree" | ||
189 | 58 | print " create a working tree; necessary for other commands to run" | ||
190 | 59 | print " get_source" | ||
191 | 60 | print " download / update source code" | ||
192 | 61 | print " create_chroot" | ||
193 | 62 | print " create a chroot; necessary for later commands to run" | ||
194 | 63 | print " build" | ||
195 | 64 | print " build Chromium OS" | ||
196 | 65 | |||
197 | 66 | |||
198 | 67 | def do_install_depot_tools(options, tree_dir): | ||
199 | 68 | os.chdir(tree_dir) | ||
200 | 69 | os.system('svn co http://src.chromium.org/svn/trunk/tools/depot_tools') | ||
201 | 70 | |||
202 | 71 | def do_create_logdir(options, tree_dir): | ||
203 | 72 | logdir = os.path.join(tree_dir, 'logs') | ||
204 | 73 | if not os.path.exists(logdir): | ||
205 | 74 | os.mkdir(logdir) | ||
206 | 75 | |||
207 | 76 | def do_create_tree(options, tree_dir): | ||
208 | 77 | print 'do_create_tree' | ||
209 | 78 | |||
210 | 79 | if os.path.exists(tree_dir): | ||
211 | 80 | print 'do_create_tree: tree %s already exists. Abort.' % tree_dir | ||
212 | 81 | return errno.EEXIST | ||
213 | 82 | |||
214 | 83 | os.makedirs(tree_dir, 0755) | ||
215 | 84 | os.system('sudo apt-get update') | ||
216 | 85 | os.system('sudo apt-get install -y git subversion build-essential') | ||
217 | 86 | do_install_depot_tools(options, tree_dir) | ||
218 | 87 | do_create_logdir(options, tree_dir) | ||
219 | 88 | |||
220 | 89 | def do_get_source(options, tree_dir): | ||
221 | 90 | print 'do_get_source' | ||
222 | 91 | |||
223 | 92 | if not os.path.exists(tree_dir): | ||
224 | 93 | print 'do_get_source: tree %s does not exist. Abort.' % tree_dir | ||
225 | 94 | return errno.ENOENT | ||
226 | 95 | |||
227 | 96 | basedir = os.path.dirname(os.path.realpath(sys.argv[0])) | ||
228 | 97 | |||
229 | 98 | do_create_logdir(options, tree_dir) | ||
230 | 99 | os.chdir(tree_dir) | ||
231 | 100 | # Needs the "echo" piped in here to stop "repo init" asking | ||
232 | 101 | # awkward interactive questions that you can't pass on the command | ||
233 | 102 | # line. | ||
234 | 103 | cmdline = 'script -c "' | ||
235 | 104 | cmdline += 'echo | repo init -u %s' % options['manifest'] | ||
236 | 105 | cmdline += '" logs/repo-init.log' | ||
237 | 106 | os.system(cmdline) | ||
238 | 107 | |||
239 | 108 | cmdline = 'script -c "' | ||
240 | 109 | cmdline += 'repo sync' | ||
241 | 110 | cmdline += '" logs/repo-sync.log' | ||
242 | 111 | os.system(cmdline) | ||
243 | 112 | |||
244 | 113 | # Copy in our script to do the actual build work inside the chroot | ||
245 | 114 | build_script = os.path.join(basedir, options['build-script']) | ||
246 | 115 | os.chmod(build_script, 0755) | ||
247 | 116 | shutil.copy(build_script, './src/scripts') | ||
248 | 117 | |||
249 | 118 | def do_create_chroot(options, tree_dir): | ||
250 | 119 | print 'do_create_chroot' | ||
251 | 120 | |||
252 | 121 | if not os.path.exists(tree_dir): | ||
253 | 122 | print 'do_create_chroot: tree %s does not exist. Abort.' % tree_dir | ||
254 | 123 | return errno.ENOENT | ||
255 | 124 | |||
256 | 125 | do_create_logdir(options, tree_dir) | ||
257 | 126 | os.chdir(tree_dir) | ||
258 | 127 | cmdline = 'script -c "' | ||
259 | 128 | cmdline += './src/scripts/make_chroot' | ||
260 | 129 | if options['nousepkg']: | ||
261 | 130 | cmdline += ' --nousepkg' | ||
262 | 131 | cmdline += '" logs/create-chroot.log' | ||
263 | 132 | os.system(cmdline) | ||
264 | 133 | |||
265 | 134 | def do_build(options, tree_dir): | ||
266 | 135 | print 'do_build' | ||
267 | 136 | |||
268 | 137 | if not os.path.exists(tree_dir): | ||
269 | 138 | print 'do_build: tree %s does not exist. Abort.' % tree_dir | ||
270 | 139 | return errno.ENOENT | ||
271 | 140 | |||
272 | 141 | chroot_path = os.path.join(tree_dir, 'chroot') | ||
273 | 142 | if not os.path.exists(chroot_path): | ||
274 | 143 | print 'do_build: chroot %s does not exist. Abort.' % chroot_path | ||
275 | 144 | return errno.ENOENT | ||
276 | 145 | |||
277 | 146 | do_create_logdir(options, tree_dir) | ||
278 | 147 | os.chdir(tree_dir) | ||
279 | 148 | |||
280 | 149 | cmdline = 'script -c "' | ||
281 | 150 | cmdline += './src/scripts/enter_chroot.sh -- ./%s' % options['build-script'] | ||
282 | 151 | if options['nousepkg']: | ||
283 | 152 | cmdline += ' --nousepkg=True' | ||
284 | 153 | cmdline += ' --board-type=%s' % options['board-type'] | ||
285 | 154 | cmdline += ' --logdir=/var/log/saved-logs' | ||
286 | 155 | cmdline += '" logs/cros-build.log' | ||
287 | 156 | os.system(cmdline) | ||
288 | 157 | |||
289 | 158 | cmdline = 'tar c -C chroot/var/log --lzma -f logs/build-logs.tar.lzma saved-logs' | ||
290 | 159 | os.system(cmdline) | ||
291 | 160 | |||
292 | 161 | try: | ||
293 | 162 | opts, args = getopt.getopt(sys.argv[1:], "", | ||
294 | 163 | ["help", | ||
295 | 164 | "working-dir=", | ||
296 | 165 | "build-name=", | ||
297 | 166 | "board-type=", | ||
298 | 167 | "use-network=", | ||
299 | 168 | "toolchain=", | ||
300 | 169 | "nousepkg=", | ||
301 | 170 | "manifest="]) | ||
302 | 171 | except getopt.GetoptError, err: | ||
303 | 172 | # print help information and exit: | ||
304 | 173 | print str(err) # will print something like "option -a not recognized" | ||
305 | 174 | usage() | ||
306 | 175 | sys.exit(2) | ||
307 | 176 | |||
308 | 177 | for o, a in opts: | ||
309 | 178 | if o in ("--help"): | ||
310 | 179 | usage() | ||
311 | 180 | sys.exit(0) | ||
312 | 181 | else: | ||
313 | 182 | options[o[2:]] = a | ||
314 | 183 | |||
315 | 184 | if options['working-dir'] == '': | ||
316 | 185 | print 'Need to specify a working dir. Abort.' | ||
317 | 186 | usage() | ||
318 | 187 | sys.exit(2) | ||
319 | 188 | |||
320 | 189 | if args == []: | ||
321 | 190 | print "Not asked to do anything" | ||
322 | 191 | usage() | ||
323 | 192 | sys.exit(0) | ||
324 | 193 | |||
325 | 194 | for command in args: | ||
326 | 195 | if not command in (commands): | ||
327 | 196 | print "Unknown command %s" % command | ||
328 | 197 | usage() | ||
329 | 198 | sys.exit(2) | ||
330 | 199 | |||
331 | 200 | if not os.path.exists(options['working-dir']): | ||
332 | 201 | # Create working dir area; likely to be on a separate filesystem | ||
333 | 202 | # somewhere, so let's make this as simple as possible using sudo. | ||
334 | 203 | os.system('sudo mkdir -p -m 0755 %s' % options['working-dir']) | ||
335 | 204 | os.system('sudo chown %s: %s' % (os.environ['LOGNAME'], options['working-dir'])) | ||
336 | 205 | |||
337 | 206 | tree_dir = os.path.join(options['working-dir'], options['build-name']) | ||
338 | 207 | depot_tools_dir = os.path.join(tree_dir, 'depot_tools') | ||
339 | 208 | os.environ['LC_ALL'] = 'C' | ||
340 | 209 | os.environ['PATH'] = os.environ['PATH'] + os.pathsep + depot_tools_dir | ||
341 | 210 | |||
342 | 211 | if 'create_tree' in args: | ||
343 | 212 | err = do_create_tree(options, tree_dir) | ||
344 | 213 | if 'get_source' in args: | ||
345 | 214 | err = do_get_source(options, tree_dir) | ||
346 | 215 | if 'create_chroot' in args: | ||
347 | 216 | err = do_create_chroot(options, tree_dir) | ||
348 | 217 | if 'build' in args: | ||
349 | 218 | err = do_build(options, tree_dir) | ||
350 | 219 |
I submitted a branch based on yours for you to merge, as I felt it was simpler to show the changes in commits rather than explain them, then ask you to do them, then review them etc. These were all very simple changes, and overall your code was really good, thanks! See https:/ /code.launchpad .net/~lool/ linaro- chromiumos/ python- rewrite/ +merge/ 54551 for the mp.
There is one major issue with the new Python code: usage of os.system() is unchecked, which means we don't fail the run when any command fails. This really must be fixed; with the new run() wrapper I introduced, it should be simpler to add this in a single place.
Other things I had in mind: chromiumos- build frontend
- we should have a place to share code between the scripts
- we should move them out of remote and kill my linaro-
- (low priority) getopt doesn't integrate too nicely with Python in my experience, there are nicer ways to handle flags, but it works with getopt so we can keep it for now
- create_logdir() feels a bit specific; I think we should have an ensure_dir() thin wrapper around os.isdir() + os.makedirs(), and we should setup logdir early; perhaps it's easier to just expose it as an option; this would also allow merging logged_run() with run()
- I think we should use stderr consistently for our own output, but I'm open to discuss this
- the run() interface should take an array of commands rather than a command string; this is nicer to deal with when preparing commands before running them