Chromium Code Reviews| 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 |