OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 Google Inc. All rights reserved. | 2 # Copyright (c) 2012 Google Inc. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 | 6 |
7 """Argument-less script to select what to run on the buildbots.""" | 7 """Argument-less script to select what to run on the buildbots.""" |
8 | 8 |
9 | 9 |
10 import filecmp | |
10 import os | 11 import os |
11 import shutil | 12 import shutil |
12 import subprocess | 13 import subprocess |
13 import sys | 14 import sys |
14 | 15 |
15 | 16 |
16 if sys.platform in ['win32', 'cygwin']: | 17 if sys.platform in ['win32', 'cygwin']: |
17 EXE_SUFFIX = '.exe' | 18 EXE_SUFFIX = '.exe' |
18 else: | 19 else: |
19 EXE_SUFFIX = '' | 20 EXE_SUFFIX = '' |
20 | 21 |
21 | 22 |
22 BUILDBOT_DIR = os.path.dirname(os.path.abspath(__file__)) | 23 BUILDBOT_DIR = os.path.dirname(os.path.abspath(__file__)) |
23 TRUNK_DIR = os.path.dirname(BUILDBOT_DIR) | 24 TRUNK_DIR = os.path.dirname(BUILDBOT_DIR) |
24 ROOT_DIR = os.path.dirname(TRUNK_DIR) | 25 ROOT_DIR = os.path.dirname(TRUNK_DIR) |
25 ANDROID_DIR = os.path.join(ROOT_DIR, 'android') | 26 ANDROID_DIR = os.path.join(ROOT_DIR, 'android') |
26 CMAKE_DIR = os.path.join(ROOT_DIR, 'cmake') | 27 CMAKE_DIR = os.path.join(ROOT_DIR, 'cmake') |
27 CMAKE_BIN_DIR = os.path.join(CMAKE_DIR, 'bin') | 28 CMAKE_BIN_DIR = os.path.join(CMAKE_DIR, 'bin') |
28 OUT_DIR = os.path.join(TRUNK_DIR, 'out') | 29 OUT_DIR = os.path.join(TRUNK_DIR, 'out') |
29 | 30 |
30 | 31 |
31 def CallSubProcess(*args, **kwargs): | 32 def CallSubProcess(*args, **kwargs): |
32 """Wrapper around subprocess.call which treats errors as build exceptions.""" | 33 """Wrapper around subprocess.call which treats errors as build exceptions.""" |
33 retcode = subprocess.call(*args, **kwargs) | 34 with open(os.devnull) as devnull_fd: |
35 retcode = subprocess.call(stdin=devnull_fd, *args, **kwargs) | |
34 if retcode != 0: | 36 if retcode != 0: |
35 print '@@@STEP_EXCEPTION@@@' | 37 print '@@@STEP_EXCEPTION@@@' |
36 sys.exit(1) | 38 sys.exit(1) |
37 | 39 |
38 | 40 |
39 def PrepareCmake(): | 41 def PrepareCmake(): |
40 """Build CMake 2.8.8 since the version in Precise is 2.8.7.""" | 42 """Build CMake 2.8.8 since the version in Precise is 2.8.7.""" |
41 if os.environ['BUILDBOT_CLOBBER'] == '1': | 43 if os.environ['BUILDBOT_CLOBBER'] == '1': |
42 print '@@@BUILD_STEP Clobber CMake checkout@@@' | 44 print '@@@BUILD_STEP Clobber CMake checkout@@@' |
43 shutil.rmtree(CMAKE_DIR) | 45 shutil.rmtree(CMAKE_DIR) |
44 | 46 |
45 # We always build CMake 2.8.8, so no need to do anything | 47 # We always build CMake 2.8.8, so no need to do anything |
46 # if the directory already exists. | 48 # if the directory already exists. |
47 if os.path.isdir(CMAKE_DIR): | 49 if os.path.isdir(CMAKE_DIR): |
48 return | 50 return |
49 | 51 |
50 print '@@@BUILD_STEP Initialize CMake checkout@@@' | 52 print '@@@BUILD_STEP Initialize CMake checkout@@@' |
51 os.mkdir(CMAKE_DIR) | 53 os.mkdir(CMAKE_DIR) |
52 CallSubProcess(['git', 'config', '--global', 'user.name', 'trybot']) | |
53 CallSubProcess(['git', 'config', '--global', | |
54 'user.email', 'chrome-bot@google.com']) | |
55 CallSubProcess(['git', 'config', '--global', 'color.ui', 'false']) | |
56 | 54 |
57 print '@@@BUILD_STEP Sync CMake@@@' | 55 print '@@@BUILD_STEP Sync CMake@@@' |
58 CallSubProcess( | 56 CallSubProcess( |
59 ['git', 'clone', | 57 ['git', 'clone', |
60 '--depth', '1', | 58 '--depth', '1', |
61 '--single-branch', | 59 '--single-branch', |
62 '--branch', 'v2.8.8', | 60 '--branch', 'v2.8.8', |
63 '--', | 61 '--', |
64 'git://cmake.org/cmake.git', | 62 'git://cmake.org/cmake.git', |
65 CMAKE_DIR], | 63 CMAKE_DIR], |
66 cwd=CMAKE_DIR) | 64 cwd=CMAKE_DIR) |
67 | 65 |
68 print '@@@BUILD_STEP Build CMake@@@' | 66 print '@@@BUILD_STEP Build CMake@@@' |
69 CallSubProcess( | 67 CallSubProcess( |
70 ['/bin/bash', 'bootstrap', '--prefix=%s' % CMAKE_DIR], | 68 ['/bin/bash', 'bootstrap', '--prefix=%s' % CMAKE_DIR], |
71 cwd=CMAKE_DIR) | 69 cwd=CMAKE_DIR) |
72 | 70 |
73 CallSubProcess( ['make', 'cmake'], cwd=CMAKE_DIR) | 71 CallSubProcess( ['make', 'cmake'], cwd=CMAKE_DIR) |
74 | 72 |
75 | 73 |
76 _ANDROID_SETUP = 'source build/envsetup.sh && lunch full-eng' | 74 _ANDROID_SETUP = 'source build/envsetup.sh && lunch full-eng' |
77 | 75 |
78 | 76 |
79 def PrepareAndroidTree(): | 77 def PrepareAndroidTree(): |
80 """Prepare an Android tree to run 'android' format tests.""" | 78 """Prepare an Android tree to run 'android' format tests.""" |
81 if os.environ['BUILDBOT_CLOBBER'] == '1': | 79 if os.environ['BUILDBOT_CLOBBER'] == '1': |
82 print '@@@BUILD_STEP Clobber Android checkout@@@' | 80 print '@@@BUILD_STEP Clobber Android checkout@@@' |
83 shutil.rmtree(ANDROID_DIR) | 81 shutil.rmtree(ANDROID_DIR) |
84 | 82 |
85 # The release of Android we use is static, so there's no need to do anything | 83 # (Re)create the directory so that the following steps will succeed. |
86 # if the directory already exists. | 84 if not os.path.isdir(ANDROID_DIR): |
87 if os.path.isdir(ANDROID_DIR): | 85 os.mkdir(ANDROID_DIR) |
86 | |
87 # We use a manifest from the gyp project listing pinned revisions of AOSP to | |
88 # use, to ensure that we test against a stable target. This needs to be | |
89 # updated to pick up new build system changes sometimes, so we must test if | |
90 # it has changed. | |
91 manifest_filename = 'aosp_manifest.xml' | |
92 gyp_manifest = os.path.join(BUILDBOT_DIR, manifest_filename) | |
93 android_manifest = os.path.join(ANDROID_DIR, '.repo', 'manifests', | |
94 manifest_filename) | |
95 manifest_is_current = (os.path.isfile(android_manifest) and | |
96 filecmp.cmp(gyp_manifest, android_manifest)) | |
97 if not manifest_is_current: | |
98 # It's safe to repeat these steps, so just do them again to make sure we are | |
99 # in a good state. | |
100 print '@@@BUILD_STEP Initialize Android checkout@@@' | |
101 CallSubProcess( | |
102 ['repo', 'init', | |
103 '-u', 'https://android.googlesource.com/platform/manifest', | |
104 '-b', 'master', | |
105 '-g', 'all,-notdefault,-device,-darwin,-mips,-x86'], | |
106 cwd=ANDROID_DIR) | |
107 shutil.copy(gyp_manifest, android_manifest) | |
108 | |
109 print '@@@BUILD_STEP Sync Android@@@' | |
110 CallSubProcess(['repo', 'sync', '-j4', '-m', manifest_filename], | |
111 cwd=ANDROID_DIR) | |
112 | |
113 # If we already built the system image successfully and didn't sync to a new | |
114 # version of the source, skip running the build again as it's expensive even | |
115 # when there's nothing to do. | |
116 system_img = os.path.join(ANDROID_DIR, 'out', 'target', 'product', 'generic', | |
117 'system.img') | |
118 if manifest_is_current and os.path.isfile(system_img): | |
88 return | 119 return |
89 | 120 |
90 print '@@@BUILD_STEP Initialize Android checkout@@@' | |
91 os.mkdir(ANDROID_DIR) | |
92 CallSubProcess(['git', 'config', '--global', 'user.name', 'trybot']) | |
93 CallSubProcess(['git', 'config', '--global', | |
94 'user.email', 'chrome-bot@google.com']) | |
95 CallSubProcess(['git', 'config', '--global', 'color.ui', 'false']) | |
96 CallSubProcess( | |
97 ['repo', 'init', | |
98 '-u', 'https://android.googlesource.com/platform/manifest', | |
99 '-b', 'android-4.2.1_r1', | |
100 '-g', 'all,-notdefault,-device,-darwin,-mips,-x86'], | |
101 cwd=ANDROID_DIR) | |
102 | |
103 print '@@@BUILD_STEP Sync Android@@@' | |
104 CallSubProcess(['repo', 'sync', '-j4'], cwd=ANDROID_DIR) | |
105 | |
106 print '@@@BUILD_STEP Build Android@@@' | 121 print '@@@BUILD_STEP Build Android@@@' |
107 CallSubProcess( | 122 CallSubProcess( |
108 ['/bin/bash', | 123 ['/bin/bash', |
109 '-c', '%s && make -j4' % _ANDROID_SETUP], | 124 '-c', '%s && make -j4' % _ANDROID_SETUP], |
110 cwd=ANDROID_DIR) | 125 cwd=ANDROID_DIR) |
111 | 126 |
112 | 127 |
113 def StartAndroidEmulator(): | 128 def StartAndroidEmulator(): |
114 """Start an android emulator from the built android tree.""" | 129 """Start an android emulator from the built android tree.""" |
115 print '@@@BUILD_STEP Start Android emulator@@@' | 130 print '@@@BUILD_STEP Start Android emulator@@@' |
116 android_host_bin = '$ANDROID_HOST_OUT/bin' | 131 |
132 CallSubProcess(['/bin/bash', '-c', | |
bradn
2014/08/22 16:13:32
Rather than going thru /bin/bash you can add the a
| |
133 '%s && adb kill-server ' % _ANDROID_SETUP], | |
134 cwd=ANDROID_DIR) | |
135 | |
136 # If taskset is available, use it to force adbd to run only on one core, as, | |
137 # sadly, it improves its reliability (see crbug.com/268450). | |
138 adbd_wrapper = '' | |
139 with open(os.devnull, 'w') as devnull_fd: | |
140 if subprocess.call(['which', 'taskset'], stdout=devnull_fd) == 0: | |
141 adbd_wrapper = 'taskset -c 0' | |
142 CallSubProcess(['/bin/bash', '-c', | |
bradn
2014/08/22 16:13:32
same
| |
143 '%s && %s adb start-server ' % (_ANDROID_SETUP, adbd_wrapper)], | |
144 cwd=ANDROID_DIR) | |
145 | |
117 subprocess.Popen( | 146 subprocess.Popen( |
118 ['/bin/bash', '-c', | 147 ['/bin/bash', '-c', |
bradn
2014/08/22 16:13:32
same
| |
119 '%s && %s/emulator -no-window' % (_ANDROID_SETUP, android_host_bin)], | 148 '%s && emulator -no-window' % _ANDROID_SETUP], |
120 cwd=ANDROID_DIR) | 149 cwd=ANDROID_DIR) |
121 CallSubProcess( | 150 CallSubProcess( |
122 ['/bin/bash', '-c', | 151 ['/bin/bash', '-c', |
123 '%s && %s/adb wait-for-device' % (_ANDROID_SETUP, android_host_bin)], | 152 '%s && adb wait-for-device' % _ANDROID_SETUP], |
124 cwd=ANDROID_DIR) | 153 cwd=ANDROID_DIR) |
125 | 154 |
126 | 155 |
127 def StopAndroidEmulator(): | 156 def StopAndroidEmulator(): |
128 """Stop all android emulators.""" | 157 """Stop all android emulators.""" |
129 print '@@@BUILD_STEP Stop Android emulator@@@' | 158 print '@@@BUILD_STEP Stop Android emulator@@@' |
130 # If this fails, it's because there is no emulator running. | 159 # If this fails, it's because there is no emulator running. |
131 subprocess.call(['pkill', 'emulator.*']) | 160 subprocess.call(['pkill', 'emulator.*']) |
132 | 161 |
133 | 162 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 # TODO(bradnelson): once the annotator supports a postscript (section for | 243 # TODO(bradnelson): once the annotator supports a postscript (section for |
215 # after the build proper that could be used for cumulative failures), | 244 # after the build proper that could be used for cumulative failures), |
216 # use that instead of this. This isolates the final return value so | 245 # use that instead of this. This isolates the final return value so |
217 # that it isn't misattributed to the last stage. | 246 # that it isn't misattributed to the last stage. |
218 print '@@@BUILD_STEP failures@@@' | 247 print '@@@BUILD_STEP failures@@@' |
219 sys.exit(retcode) | 248 sys.exit(retcode) |
220 | 249 |
221 | 250 |
222 if __name__ == '__main__': | 251 if __name__ == '__main__': |
223 GypBuild() | 252 GypBuild() |
OLD | NEW |