X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Ftools%2Fclang%2Fscripts%2Fupdate.py;h=d23eb41d680acf7c44c845c9b45c3d2a395d4f1e;hb=ff3e2503a20db9193d323c1d19c38c68004dec4a;hp=bdc781f715b53de86777adf4f1a3967ecc7833c6;hpb=7338fba38ba696536d1cc9d389afd716a6ab2fe6;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/tools/clang/scripts/update.py b/src/tools/clang/scripts/update.py index bdc781f..d23eb41 100755 --- a/src/tools/clang/scripts/update.py +++ b/src/tools/clang/scripts/update.py @@ -3,31 +3,168 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Windows can't run .sh files, so this is a small python wrapper around -update.sh. -""" +"""Windows can't run .sh files, so this is a Python implementation of +update.sh. This script should replace update.sh on all platforms eventually.""" import os +import re import subprocess import sys +# Do NOT CHANGE this if you don't know what you're doing -- see +# https://code.google.com/p/chromium/wiki/UpdatingClang +# Reverting problematic clang rolls is safe, though. +# Note: this revision is only used for Windows. Other platforms use update.sh. +LLVM_WINDOWS_REVISION = '201604' + +# Path constants. (All of these should be absolute paths.) +THIS_DIR = os.path.abspath(os.path.dirname(__file__)) +CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..')) +LLVM_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm') +LLVM_BUILD_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build', + 'Release+Asserts') +CLANG_DIR = os.path.join(LLVM_DIR, 'tools', 'clang') +COMPILER_RT_DIR = os.path.join(LLVM_DIR, 'projects', 'compiler-rt') +STAMP_FILE = os.path.join(LLVM_BUILD_DIR, 'cr_build_revision') + +LLVM_REPO_URL='https://llvm.org/svn/llvm-project' +if 'LLVM_REPO_URL' in os.environ: + LLVM_REPO_URL = os.environ['LLVM_REPO_URL'] + + +def ReadStampFile(): + """Return the contents of the stamp file, or '' if it doesn't exist.""" + try: + with open(STAMP_FILE, 'r') as f: + return f.read(); + except IOError: + return '' + + +def WriteStampFile(s): + """Write s to the stamp file.""" + if not os.path.exists(LLVM_BUILD_DIR): + os.makedirs(LLVM_BUILD_DIR) + with open(STAMP_FILE, 'w') as f: + f.write(s) + + +def DeleteFiles(dir, pattern): + """Delete all files in dir matching pattern.""" + n = 0 + regex = re.compile(r'^' + pattern + r'$') + for root, _, files in os.walk(dir): + for f in files: + if regex.match(f): + os.remove(os.path.join(root, f)) + n += 1 + return n + + +def ClobberChromiumBuildFiles(): + """Clobber Chomium build files.""" + print 'Clobbering Chromium build files...' + n = 0 + dirs = [ + os.path.join(CHROMIUM_DIR, 'out/Debug'), + os.path.join(CHROMIUM_DIR, 'out/Release'), + ] + for d in dirs: + if not os.path.exists(d): + continue + n += DeleteFiles(d, r'.*\.o') + n += DeleteFiles(d, r'.*\.obj') + n += DeleteFiles(d, r'stamp.untar') + print 'Removed %d files.' % (n) + + +def RunCommand(command, tries=1): + """Run a command, possibly with multiple retries.""" + for i in range(0, tries): + print 'Running %s (try #%d)' % (str(command), i + 1) + if subprocess.call(command, shell=True) == 0: + return + print 'Failed.' + sys.exit(1) + + +def Checkout(name, url, dir): + """Checkout the SVN module at url into dir. Use name for the log message.""" + print "Checking out %s r%s into '%s'" % (name, LLVM_WINDOWS_REVISION, dir) + RunCommand(['svn', 'checkout', '--force', + url + '@' + LLVM_WINDOWS_REVISION, dir], tries=2) + + +vs_version = None +def GetVSVersion(): + global vs_version + if not vs_version: + # TODO(hans): Find a less hacky way to find the MSVS installation. + sys.path.append(os.path.join(CHROMIUM_DIR, 'tools', 'gyp', 'pylib')) + import gyp.MSVSVersion + # We request VS 2013 because Clang won't build with 2010, and 2013 will be + # the default for Chromium soon anyway. + vs_version = gyp.MSVSVersion.SelectVisualStudioVersion('2013') + return vs_version + + +def UpdateClang(): + print 'Updating Clang to %s...' % (LLVM_WINDOWS_REVISION) + if ReadStampFile() == LLVM_WINDOWS_REVISION: + print 'Already up to date.' + return 0 + + ClobberChromiumBuildFiles() + + # Reset the stamp file in case the build is unsuccessful. + WriteStampFile('') + + Checkout('LLVM', LLVM_REPO_URL + '/llvm/trunk', LLVM_DIR) + Checkout('Clang', LLVM_REPO_URL + '/cfe/trunk', CLANG_DIR) + Checkout('compiler-rt', LLVM_REPO_URL + '/compiler-rt/trunk', COMPILER_RT_DIR) + + if not os.path.exists(LLVM_BUILD_DIR): + os.makedirs(LLVM_BUILD_DIR) + os.chdir(LLVM_BUILD_DIR) + + if not re.search(r'cmake', os.environ['PATH'], flags=re.IGNORECASE): + # If CMake is not on the path, try looking in a standard location. + os.environ['PATH'] += os.pathsep + 'C:\\Program Files (x86)\\CMake 2.8\\bin' + + RunCommand(GetVSVersion().SetupScript('x64') + + ['&&', 'cmake', '-GNinja', '-DCMAKE_BUILD_TYPE=Release', + '-DLLVM_ENABLE_ASSERTIONS=ON', LLVM_DIR]) + + RunCommand(GetVSVersion().SetupScript('x64') + ['&&', 'ninja', 'all']) + + WriteStampFile(LLVM_WINDOWS_REVISION) + print 'Clang update was successful.' + return 0 + def main(): - if sys.platform in ['win32', 'cygwin']: + if not sys.platform in ['win32', 'cygwin']: + # For non-Windows, fall back to update.sh. + # TODO(hans): Make update.py replace update.sh completely. + + # This script is called by gclient. gclient opens its hooks subprocesses + # with (stdout=subprocess.PIPE, stderr=subprocess.STDOUT) and then does + # custom output processing that breaks printing '\r' characters for + # single-line updating status messages as printed by curl and wget. + # Work around this by setting stderr of the update.sh process to stdin (!): + # gclient doesn't redirect stdin, and while stdin itself is read-only, a + # dup()ed sys.stdin is writable, try + # fd2 = os.dup(sys.stdin.fileno()); os.write(fd2, 'hi') + # TODO: Fix gclient instead, http://crbug.com/95350 + return subprocess.call( + [os.path.join(os.path.dirname(__file__), 'update.sh')] + sys.argv[1:], + stderr=os.fdopen(os.dup(sys.stdin.fileno()))) + + if not re.search('clang=1', os.environ.get('GYP_DEFINES', '')): + print 'Skipping Clang update (clang=1 was not set in GYP_DEFINES).' return 0 - # This script is called by gclient. gclient opens its hooks subprocesses with - # (stdout=subprocess.PIPE, stderr=subprocess.STDOUT) and then does custom - # output processing that breaks printing '\r' characters for single-line - # updating status messages as printed by curl and wget. - # Work around this by setting stderr of the update.sh process to stdin (!): - # gclient doesn't redirect stdin, and while stdin itself is read-only, a - # dup()ed sys.stdin is writable, try - # fd2 = os.dup(sys.stdin.fileno()); os.write(fd2, 'hi') - # TODO: Fix gclient instead, http://crbug.com/95350 - return subprocess.call( - [os.path.join(os.path.dirname(__file__), 'update.sh')] + sys.argv[1:], - stderr=os.fdopen(os.dup(sys.stdin.fileno()))) + return UpdateClang() if __name__ == '__main__':