Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / tools / clang / scripts / update.py
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Windows can't run .sh files, so this is a Python implementation of
7 update.sh. This script should replace update.sh on all platforms eventually."""
8
9 import os
10 import re
11 import subprocess
12 import sys
13
14 # Do NOT CHANGE this if you don't know what you're doing -- see
15 # https://code.google.com/p/chromium/wiki/UpdatingClang
16 # Reverting problematic clang rolls is safe, though.
17 # Note: this revision is only used for Windows. Other platforms use update.sh.
18 LLVM_WINDOWS_REVISION = '201604'
19
20 # Path constants. (All of these should be absolute paths.)
21 THIS_DIR = os.path.abspath(os.path.dirname(__file__))
22 CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..'))
23 LLVM_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm')
24 LLVM_BUILD_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build',
25                               'Release+Asserts')
26 CLANG_DIR = os.path.join(LLVM_DIR, 'tools', 'clang')
27 COMPILER_RT_DIR = os.path.join(LLVM_DIR, 'projects', 'compiler-rt')
28 STAMP_FILE = os.path.join(LLVM_BUILD_DIR, 'cr_build_revision')
29
30 LLVM_REPO_URL='https://llvm.org/svn/llvm-project'
31 if 'LLVM_REPO_URL' in os.environ:
32   LLVM_REPO_URL = os.environ['LLVM_REPO_URL']
33
34
35 def ReadStampFile():
36   """Return the contents of the stamp file, or '' if it doesn't exist."""
37   try:
38     with open(STAMP_FILE, 'r') as f:
39       return f.read();
40   except IOError:
41     return ''
42
43
44 def WriteStampFile(s):
45   """Write s to the stamp file."""
46   if not os.path.exists(LLVM_BUILD_DIR):
47     os.makedirs(LLVM_BUILD_DIR)
48   with open(STAMP_FILE, 'w') as f:
49     f.write(s)
50
51
52 def DeleteFiles(dir, pattern):
53   """Delete all files in dir matching pattern."""
54   n = 0
55   regex = re.compile(r'^' + pattern + r'$')
56   for root, _, files in os.walk(dir):
57     for f in files:
58       if regex.match(f):
59         os.remove(os.path.join(root, f))
60         n += 1
61   return n
62
63
64 def ClobberChromiumBuildFiles():
65   """Clobber Chomium build files."""
66   print 'Clobbering Chromium build files...'
67   n = 0
68   dirs = [
69     os.path.join(CHROMIUM_DIR, 'out/Debug'),
70     os.path.join(CHROMIUM_DIR, 'out/Release'),
71   ]
72   for d in dirs:
73     if not os.path.exists(d):
74       continue
75     n += DeleteFiles(d, r'.*\.o')
76     n += DeleteFiles(d, r'.*\.obj')
77     n += DeleteFiles(d, r'stamp.untar')
78   print 'Removed %d files.' % (n)
79
80
81 def RunCommand(command, tries=1):
82   """Run a command, possibly with multiple retries."""
83   for i in range(0, tries):
84     print 'Running %s (try #%d)' % (str(command), i + 1)
85     if subprocess.call(command, shell=True) == 0:
86       return
87     print 'Failed.'
88   sys.exit(1)
89
90
91 def Checkout(name, url, dir):
92   """Checkout the SVN module at url into dir. Use name for the log message."""
93   print "Checking out %s r%s into '%s'" % (name, LLVM_WINDOWS_REVISION, dir)
94   RunCommand(['svn', 'checkout', '--force',
95               url + '@' + LLVM_WINDOWS_REVISION, dir], tries=2)
96
97
98 vs_version = None
99 def GetVSVersion():
100   global vs_version
101   if not vs_version:
102     # TODO(hans): Find a less hacky way to find the MSVS installation.
103     sys.path.append(os.path.join(CHROMIUM_DIR, 'tools', 'gyp', 'pylib'))
104     import gyp.MSVSVersion
105     # We request VS 2013 because Clang won't build with 2010, and 2013 will be
106     # the default for Chromium soon anyway.
107     vs_version = gyp.MSVSVersion.SelectVisualStudioVersion('2013')
108   return vs_version
109
110
111 def UpdateClang():
112   print 'Updating Clang to %s...' % (LLVM_WINDOWS_REVISION)
113   if ReadStampFile() == LLVM_WINDOWS_REVISION:
114     print 'Already up to date.'
115     return 0
116
117   ClobberChromiumBuildFiles()
118
119   # Reset the stamp file in case the build is unsuccessful.
120   WriteStampFile('')
121
122   Checkout('LLVM', LLVM_REPO_URL + '/llvm/trunk', LLVM_DIR)
123   Checkout('Clang', LLVM_REPO_URL + '/cfe/trunk', CLANG_DIR)
124   Checkout('compiler-rt', LLVM_REPO_URL + '/compiler-rt/trunk', COMPILER_RT_DIR)
125
126   if not os.path.exists(LLVM_BUILD_DIR):
127     os.makedirs(LLVM_BUILD_DIR)
128   os.chdir(LLVM_BUILD_DIR)
129
130   if not re.search(r'cmake', os.environ['PATH'], flags=re.IGNORECASE):
131     # If CMake is not on the path, try looking in a standard location.
132     os.environ['PATH'] += os.pathsep + 'C:\\Program Files (x86)\\CMake 2.8\\bin'
133
134   RunCommand(GetVSVersion().SetupScript('x64') +
135              ['&&', 'cmake', '-GNinja', '-DCMAKE_BUILD_TYPE=Release',
136               '-DLLVM_ENABLE_ASSERTIONS=ON', LLVM_DIR])
137
138   RunCommand(GetVSVersion().SetupScript('x64') + ['&&', 'ninja', 'all'])
139
140   WriteStampFile(LLVM_WINDOWS_REVISION)
141   print 'Clang update was successful.'
142   return 0
143
144
145 def main():
146   if not sys.platform in ['win32', 'cygwin']:
147     # For non-Windows, fall back to update.sh.
148     # TODO(hans): Make update.py replace update.sh completely.
149
150     # This script is called by gclient. gclient opens its hooks subprocesses
151     # with (stdout=subprocess.PIPE, stderr=subprocess.STDOUT) and then does
152     # custom output processing that breaks printing '\r' characters for
153     # single-line updating status messages as printed by curl and wget.
154     # Work around this by setting stderr of the update.sh process to stdin (!):
155     # gclient doesn't redirect stdin, and while stdin itself is read-only, a
156     # dup()ed sys.stdin is writable, try
157     #   fd2 = os.dup(sys.stdin.fileno()); os.write(fd2, 'hi')
158     # TODO: Fix gclient instead, http://crbug.com/95350
159     return subprocess.call(
160         [os.path.join(os.path.dirname(__file__), 'update.sh')] +  sys.argv[1:],
161         stderr=os.fdopen(os.dup(sys.stdin.fileno())))
162
163   if not re.search('clang=1', os.environ.get('GYP_DEFINES', '')):
164     print 'Skipping Clang update (clang=1 was not set in GYP_DEFINES).'
165     return 0
166
167   return UpdateClang()
168
169
170 if __name__ == '__main__':
171   sys.exit(main())