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",
32 sys
.path
.append('build')
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
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',
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")
110 m
= re
.search(r
'Format Version (\d+)\.', line
)
112 solution_version
= int(m
.group(1))
114 print "FAILURE: Unknown solution version in %s" % solution
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
)
122 compiler_version
= int(m
.group(1))
124 print "FAILURE: Unknown cl.exe version."
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):
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'"
150 def CleanTargets(self
, targets
, options
):
151 """Cleans the targets."""
152 solution
= self
.GetSolutionPath()
153 self
.Execute(['devenv.com',
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',
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',
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',
193 def Dobuild(self
, targets
, options
):
194 """Builds the specifed targets."""
195 solution
= self
.GetSolutionPath()
196 self
.Execute(['hammer',
199 # Use "o3d" for chrome only build?
200 base_name
= "o3d_all"
202 def __init__(self
, args
):
206 modes
= ["build", "presubmit", "selenium", "unit_tests"]
207 versions
= ["Debug", "Release"]
209 parser
= OptionParser()
211 "--list-targets", action
="store_true",
212 help="lists all available targets.")
214 "--no-execute", action
="store_true", default
=False,
215 help="just prints commands that would get executed.")
217 "--verbose", action
="store_true",
218 help="prints more output.")
220 "--targets", action
="append",
221 help="targets to build separated by commas.")
223 "--clean", action
="store_true",
224 help="cleans the targets.")
226 "--rebuild", action
="store_true",
227 help="cleans, then builds targets")
229 "--version", choices
=versions
, default
="Debug",
230 help="version to build. Versions are '%s'. Default='Debug' " %
231 "', '".join(versions
))
233 "--mode", choices
=modes
, default
="build",
234 help="mode to use. Valid modes are '%s'. Default='build' " %
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"
246 self
.Log("mode:", options
.mode
)
248 targets
= options
.targets
250 # flatten the targets.
251 targets
= sum([t
.split(",") for t
in targets
], [])
255 # Create a platform specific builder.
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
)
263 print "ERROR: Unknown platform."
267 if options
.clean
or options
.rebuild
:
268 builder
.CleanTargets(targets
, options
)
269 if not options
.rebuild
:
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."""
281 def Execute(self
, args
):
282 """Executes an external program if execute is true."""
284 self
.Log(" ".join(args
))
285 if subprocess
.call(args
) > 0:
286 raise RuntimeError("FAILED: " + " ".join(args
))
294 if __name__
== "__main__":