@ -3,171 +3,85 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Author: mpcomplete
#
# This script updates and does a clean build of chrome for you.
# Usage: python chrome-update.py C:\path\to\chrome\trunk
#
# It assumes the following:
# - You have gclient.bat and devenv.com in your path (use the wrapper batch
# file to ensure this).
import sys
import os
import subprocess
import httplib
import re
import shutil
import optparse
import subprocess
import sys
import urllib
def Message ( str ) :
""" Prints a status message. """
print " [chrome-update] " , str
IS_WIN = sys . platform . startswith ( ' win ' )
BASE_URL = ' http://src.chromium.org/svn/trunk/tools/buildbot/scripts/ '
COMPILE_URL = BASE_URL + ' slave/compile.py '
UTILS_URL = BASE_URL + ' common/chromium_utils.py '
def FixupPath ( path ) :
""" Returns the OS-ified version of a windows path. """
return os . path . sep . join ( path . split ( " \\ " ) )
def GetRevision ( ) :
def Fetch ( url , file ) :
if not os . path . exists ( file ) :
urllib . urlretrieve ( url , file )
def GetLastestRevision ( ) :
""" Returns the revision number of the last build that was archived, or
None on failure . """
HOST = " build.chromium.org "
PATH = " /buildbot/continuous/LATEST/REVISION "
EXPR = r " ( \ d+) "
connection = httplib . HTTPConnection ( HOST )
connection . request ( " GET " , PATH )
response = connection . getresponse ( )
text = response . read ( )
match = re . search ( EXPR , text )
if match :
return int ( match . group ( 1 ) )
url = ' http://build.chromium.org/buildbot/continuous/ '
if sys . platform . startswith ( ' win ' ) :
url + = ' win/ '
elif sys . platform . startswith ( ' linux ' ) :
url + = ' linux/ '
elif sys . platform . startswith ( ' darwin ' ) :
url + = ' mac/ '
else :
# This path is actually win.
pass
url + = ' LATEST/REVISION '
text = urllib . urlopen ( url ) . read ( )
if text :
match = re . search ( r " ( \ d+) " , text )
if match :
return int ( match . group ( 1 ) )
return None
def SetRevisionForUpdate ( chrome_root ) :
""" Prepares environment so gclient syncs to a good revision, if possible. """
# Find a buildable revision.
rev = GetRevision ( )
if rev == None :
Message ( " WARNING: Failed to find a buildable revision. Syncing to trunk. " )
return " trunk "
# Read the .gclient file.
gclient_file = chrome_root + FixupPath ( " \\ .gclient " )
if not os . path . exists ( gclient_file ) :
Message ( " WARNING: Failed to find .gclient file. Syncing to trunk. " )
return " trunk "
scope = { }
execfile ( gclient_file , scope )
solutions = scope [ " solutions " ]
# Edit the url of the chrome 'src' solution, unless the user wants a
# specific revision.
for solution in solutions :
if solution [ " name " ] == " src " :
splitter = solution [ " url " ] . split ( " @ " )
if len ( splitter ) == 1 :
solution [ " url " ] = splitter [ 0 ] + " @ " + str ( rev )
else :
rev = int ( splitter [ 1 ] )
break
# Write out the new .gclient file.
gclient_override = gclient_file + " -update-chrome "
f = open ( gclient_override , " w " )
f . write ( " solutions = " + str ( solutions ) )
f . close ( )
# Set the env var that the gclient tool looks for.
os . environ [ " GCLIENT_FILE " ] = gclient_override
return rev
def DoUpdate ( chrome_root ) :
""" gclient sync to the latest build. """
# gclient sync
rev = SetRevisionForUpdate ( chrome_root )
cmd = [ " gclient.bat " , " sync " ]
Message ( " Updating to %s : %s " % ( rev , cmd ) )
sys . stdout . flush ( )
return subprocess . call ( cmd , cwd = chrome_root )
def DoClean ( chrome_root , type ) :
""" Clean our build dir. """
# rm -rf src/chrome/Debug
rv = [ 0 ]
def onError ( func , path , excinfo ) :
Message ( " Couldn ' t remove ' %s ' : %s " % ( path , excinfo ) )
rv [ 0 ] = [ 1 ]
build_path = chrome_root + FixupPath ( " \\ src \\ chrome \\ " + type )
Message ( " Cleaning: %s " % build_path )
shutil . rmtree ( build_path , False , onError )
return rv [ 0 ]
def DoBuild ( chrome_root , chrome_sln , clean , type ) :
""" devenv /build what we just checked out. """
if clean :
rv = DoClean ( chrome_root , type )
if rv != 0 :
Message ( " WARNING: Clean failed. Doing a build without clean. " )
# devenv chrome.sln /build Debug
cmd = [ " devenv.com " , chrome_sln , " /build " , type ]
Message ( " Building: %s " % cmd )
sys . stdout . flush ( )
return subprocess . call ( cmd , cwd = chrome_root )
def Main ( ) :
parser = optparse . OptionParser ( )
parser . add_option ( " " , " --clean " , action = " store_true " , default = False ,
help = " wipe Debug output directory before building " )
parser . add_option ( " " , " --solution " , default = " src \\ chrome \\ chrome.sln " ,
help = " path to the .sln file to build (absolute, or "
" relative to chrome trunk " )
parser . add_option ( " " , " --release " , action = " store_true " , default = False ,
help = " build the release configuration in addition of the "
" debug configuration. " )
parser . add_option ( " " , " --nosync " , action = " store_true " , default = False ,
help = " doesn ' t sync before building " )
parser . add_option ( " " , " --print-latest " , action = " store_true " , default = False ,
help = " print the latest buildable revision and exit " )
options , args = parser . parse_args ( None )
if options . print_latest :
print GetRevision ( ) or " HEAD "
sys . exit ( 0 )
if not args :
Message ( " Usage: %s <path \\ to \\ chrome \\ root> [options] " % sys . argv [ 0 ] )
sys . exit ( 1 )
chrome_root = args [ 0 ]
cmd = [ " gclient " , " sync " ]
rev = GetLastestRevision ( )
if rev :
cmd . extend ( [ ' --revision ' , ' src@ %d ' % rev ] )
return subprocess . call ( cmd , cwd = chrome_root , shell = IS_WIN )
def DoBuild ( chrome_root , args ) :
""" Download compile.py and run it. """
compile = os . path . join ( chrome_root , ' compile.py ' )
Fetch ( COMPILE_URL , compile )
Fetch ( UTILS_URL , os . path . join ( chrome_root , ' chromium_utils.py ' ) )
cmd = [ ' python ' , compile ] + args
return subprocess . call ( cmd , cwd = chrome_root , shell = IS_WIN )
def Main ( args ) :
if len ( args ) < 3 :
print ( ' Usage: chrome-update.py <path> [options] ' )
print ( ' See options from compile.py at ' )
print ( ' %s ' % COMPILE_URL )
print ( ' \n For more example, see the compile steps on the waterfall ' )
return 1
chrome_root = args [ 1 ]
if not os . path . isdir ( chrome_root ) :
Message ( " Path to chrome root ( %s ) not found. " % repr ( chrome_root ) )
sys . exit ( 1 )
if not options . nosync :
rv = DoUpdate ( chrome_root )
if rv != 0 :
Message ( " Update Failed. Bailing. " )
sys . exit ( rv )
print ( ' Path to chrome root ( %s ) not found. ' % chrome_root )
return 1
chrome_sln = FixupPath ( options . solution )
rv = DoBuild ( chrome_root , chrome_sln , options . clean , " Debug " )
rv = DoUpdate ( chrome_root )
if rv != 0 :
Message ( " Debug build failed. Sad face :( " )
print ( ' Update Failed. Bailing. ' )
return rv
if options . release :
rv = DoBuild ( chrome_root , chrome_sln , options . clean , " Release " )
if rv != 0 :
Message ( " Release build failed. Sad face :( " )
if rv != 0 :
sys . exit ( rv )
DoBuild ( chrome_root , args [ 2 : ] )
print ( ' Success! ' )
return 0
Message ( " Success! " )
if __name__ == " __main__ " :
Main( )
sys . exit ( Main ( sys . argv ) )