WebKit Roll 56306:56312.
[chromium-blink-merge.git] / o3d / gypbuild.py
blob86ff0cd609096b73727f554ac76e85e6299bebcf
1 #! /usr/bin/env python
2 # Copyright 2009 Google Inc.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 # Builds a particlar platform so the user does not have to know platform
17 # specific build commands for every single platform.
19 # TODO(gman): Add help.
20 # TODO(gman): Add cross platform modes like "debug", "opt", "test", "docs"
21 # TODO(gman): Add cross platform switches like "-clean" and "-rebuild".
22 # TODO(gman): Add cross platform options like "-verbose".
23 # TODO(gman): Add cross platform options like "-presubmit", "-selenium",
24 # "-unit_tests"
26 import os
27 import os.path
28 import sys
29 import re
30 import subprocess
31 import platform
32 sys.path.append('build')
33 import is_admin
34 from optparse import OptionParser
37 class GypBuilder(object):
38 """A class to help build gyp projects in a cross platform way"""
40 class Builder(object):
41 """Base Class for building."""
43 def __init__(self, builder):
44 self.builder = builder
46 def Log(self, *args):
47 """Prints something if verbose is true."""
48 self.builder.Log(args)
50 def Execute(self, args):
51 """Executes an external program if execute is true."""
52 self.builder.Execute(args)
54 def Dopresubmit(self, targets, options):
55 """Builds and runs both the unit tests and selenium."""
56 self.Dounit_tests(targets, options)
57 self.Doselenium(targets, options)
59 def Doselenium(self, targets, options):
60 """Builds and runs the selenium tests."""
61 print "selenium not yet implemented."
63 def Dounit_tests(self, targets, options):
64 """Builds and runs the unit tests."""
65 print "unit_tests not yet implemented."
67 def CleanTargets(self, targets, options):
68 """Cleans the targets."""
69 print "clean not implemented for this platform."
72 class OSXBuilder(Builder):
73 """Class for building on OSX."""
75 def __init__(self, builder):
76 GypBuilder.Builder.__init__(self, builder)
78 def GetSolutionPath(self):
79 """Gets the solution path."""
80 return '%s.xcodeproj' % GypBuilder.base_name
82 def CleanTargets(self, targets, options):
83 """Cleans the specifed targets."""
84 solution = self.GetSolutionPath()
85 self.Execute(['xcodebuild',
86 '-project', solution,
87 'clean'])
89 def Dobuild(self, targets, options):
90 """Builds the specifed targets."""
91 solution = self.GetSolutionPath()
92 self.Execute(['xcodebuild',
93 '-project', solution])
95 class WinBuilder(Builder):
96 """Class for building on Windows."""
98 def __init__(self, builder):
99 GypBuilder.Builder.__init__(self, builder)
101 def GetSolutionPath(self):
102 """Gets the solution path."""
103 return os.path.abspath('%s.sln' % GypBuilder.base_name)
105 def CheckVisualStudioVersionVsSolution(self, solution):
106 """Checks the solution matches the cl version."""
107 f = open(solution, "r")
108 line = f.readline()
109 f.close()
110 m = re.search(r'Format Version (\d+)\.', line)
111 if m:
112 solution_version = int(m.group(1))
113 else:
114 print "FAILURE: Unknown solution version in %s" % solution
115 sys.exit(1)
117 output = subprocess.Popen(['cl.exe'],
118 stdout=subprocess.PIPE,
119 stderr=subprocess.PIPE).communicate()[1]
120 m = re.search(r'Compiler Version (\d+)\.', output)
121 if m:
122 compiler_version = int(m.group(1))
123 else:
124 print "FAILURE: Unknown cl.exe version."
125 sys.exit(1)
127 # Compiler Solution
128 # Visual Studio .NET 2005 14 9
129 # Visual Studio .NET 2008 15 10
130 # Visual Studio .NET 2010 ?? ??
131 if (compiler_version - 14) > (solution_version - 9):
132 vs_map = {
133 14: '2005',
134 15: '2008',
135 16: '2010',
137 sln_map = {
138 9: '2005',
139 10: '2008',
140 11: '2010',
142 vs_version = vs_map[compiler_version]
143 print ("ERROR: solution (%s) version does not match "
144 "Visual Studio version (%s)" %
145 (sln_map[solution_version], vs_version))
146 print "You should 'set GYP_MSVS_VERSION=auto'"
147 print "and run 'gclient runhooks --force'"
148 sys.exit(1)
150 def CleanTargets(self, targets, options):
151 """Cleans the targets."""
152 solution = self.GetSolutionPath()
153 self.Execute(['devenv.com',
154 solution,
155 '/clean',
156 options.version])
158 def Dobuild(self, targets, options):
159 """Builds the specifed targets."""
160 solution = self.GetSolutionPath()
161 if not is_admin.IsAdmin():
162 print ("WARNING: selenium_ie will not run unless you run as admin "
163 "or turn off UAC.\nAfter switching to admin run "
164 "'gclient runhooks --force'")
165 self.CheckVisualStudioVersionVsSolution(solution)
166 self.Execute(['devenv.com',
167 solution,
168 '/build',
169 options.version])
170 # TODO(gman): Should I check for devenv and if it does not exist
171 # use msbuild? Msbuild is significantly slower than devenv.
172 #self.Execute(['msbuild',
173 # solution,
174 # '/p:Configuration=%s' % options.version])
176 class LinuxBuilder(Builder):
177 """Class for building on Linux."""
179 def __init__(self, builder):
180 GypBuilder.Builder.__init__(self, builder)
182 def GetSolutionPath(self):
183 """Gets the solution path."""
184 return '%s_main.scons' % GypBuilder.base_name
186 def CleanTargets(self, targets, options):
187 """Cleans the targets."""
188 solution = self.GetSolutionPath()
189 self.Execute(['hammer',
190 '-f', solution,
191 '--clean'])
193 def Dobuild(self, targets, options):
194 """Builds the specifed targets."""
195 solution = self.GetSolutionPath()
196 self.Execute(['hammer',
197 '-f', solution])
199 # Use "o3d" for chrome only build?
200 base_name = "o3d_all"
202 def __init__(self, args):
203 self.execute = True
204 self.verbose = False
206 modes = ["build", "presubmit", "selenium", "unit_tests"]
207 versions = ["Debug", "Release"]
209 parser = OptionParser()
210 parser.add_option(
211 "--list-targets", action="store_true",
212 help="lists all available targets.")
213 parser.add_option(
214 "--no-execute", action="store_true", default=False,
215 help="just prints commands that would get executed.")
216 parser.add_option(
217 "--verbose", action="store_true",
218 help="prints more output.")
219 parser.add_option(
220 "--targets", action="append",
221 help="targets to build separated by commas.")
222 parser.add_option(
223 "--clean", action="store_true",
224 help="cleans the targets.")
225 parser.add_option(
226 "--rebuild", action="store_true",
227 help="cleans, then builds targets")
228 parser.add_option(
229 "--version", choices=versions, default="Debug",
230 help="version to build. Versions are '%s'. Default='Debug' " %
231 "', '".join(versions))
232 parser.add_option(
233 "--mode", choices=modes, default="build",
234 help="mode to use. Valid modes are '%s'. Default='build' " %
235 "', '".join(modes))
237 (options, args) = parser.parse_args(args=args)
239 self.verbose = options.verbose
240 self.execute = not options.no_execute
242 if options.list_targets:
243 print "Not yet implemented"
244 sys.exit(0)
246 self.Log("mode:", options.mode)
248 targets = options.targets
249 if targets:
250 # flatten the targets.
251 targets = sum([t.split(",") for t in targets], [])
253 os.chdir("build")
255 # Create a platform specific builder.
256 if os.name == 'nt':
257 builder = self.WinBuilder(self)
258 elif platform.system() == 'Darwin':
259 builder = self.OSXBuilder(self)
260 elif platform.system() == 'Linux':
261 builder = self.LinuxBuilder(self)
262 else:
263 print "ERROR: Unknown platform."
264 sys.exit(1)
266 # clean if asked.
267 if options.clean or options.rebuild:
268 builder.CleanTargets(targets, options)
269 if not options.rebuild:
270 return
272 # call a Do method based on the mode.
273 func = getattr(builder, "Do%s" % options.mode)
274 func(targets, options)
276 def Log(self, *args):
277 """Prints something if verbose is true."""
278 if self.verbose:
279 print args
281 def Execute(self, args):
282 """Executes an external program if execute is true."""
283 if self.execute:
284 self.Log(" ".join(args))
285 if subprocess.call(args) > 0:
286 raise RuntimeError("FAILED: " + " ".join(args))
287 else:
288 print " ".join(args)
291 def main(args):
292 GypBuilder(args[1:])
294 if __name__ == "__main__":
295 main(sys.argv)