• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- Python -*-
2# Copyright 2008 Google Inc. All Rights Reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met:
7#
8#     * Redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer.
10#     * Redistributions in binary form must reproduce the above
11# copyright notice, this list of conditions and the following disclaimer
12# in the documentation and/or other materials provided with the
13# distribution.
14#     * Neither the name of Google Inc. nor the names of its
15# contributors may be used to endorse or promote products derived from
16# this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30
31"""Builds the Google Test (gtest) lib. This has been tested on Windows,
32Linux, Mac OS X, and Cygwin.  The compilation settings from your project
33will be used, with some specific flags required for gtest added.
34
35You should be able to call this file from more or less any SConscript
36file.
37
38You can optionally set a variable on the construction environment to
39have the unit test executables copied to your output directory.  The
40variable should be env['EXE_OUTPUT'].
41
42Another optional variable is env['LIB_OUTPUT'].  If set, the generated
43libraries are copied to the folder indicated by the variable.
44
45If you place the gtest sources within your own project's source
46directory, you should be able to call this SConscript file simply as
47follows:
48
49# -- cut here --
50# Build gtest library; first tell it where to copy executables.
51env['EXE_OUTPUT'] = '#/mybuilddir/mybuildmode'  # example, optional
52env['LIB_OUTPUT'] = '#/mybuilddir/mybuildmode/lib'
53env.SConscript('whateverpath/gtest/scons/SConscript')
54# -- cut here --
55
56If on the other hand you place the gtest sources in a directory
57outside of your project's source tree, you would use a snippet similar
58to the following:
59
60# -- cut here --
61
62# The following assumes that $BUILD_DIR refers to the root of the
63# directory for your current build mode, e.g. "#/mybuilddir/mybuildmode"
64
65# Build gtest library; as it is outside of our source root, we need to
66# tell SCons that the directory it will refer to as
67# e.g. $BUILD_DIR/gtest is actually on disk in original form as
68# ../../gtest (relative to your project root directory).  Recall that
69# SCons by default copies all source files into the build directory
70# before building.
71gtest_dir = env.Dir('$BUILD_DIR/gtest')
72
73# Modify this part to point to gtest relative to the current
74# SConscript or SConstruct file's directory.  The ../.. path would
75# be different per project, to locate the base directory for gtest.
76gtest_dir.addRepository(env.Dir('../../gtest'))
77
78# Tell the gtest SCons file where to copy executables.
79env['EXE_OUTPUT'] = '$BUILD_DIR'  # example, optional
80
81# Call the gtest SConscript to build gtest.lib and unit tests.  The
82# location of the library should end up as
83# '$BUILD_DIR/gtest/scons/gtest.lib'
84env.SConscript(env.File('scons/SConscript', gtest_dir))
85
86# -- cut here --
87"""
88
89
90__author__ = 'joi@google.com (Joi Sigurdsson)'
91
92
93import os
94
95############################################################
96# Environments for building the targets, sorted by name.
97
98Import('env', 'EnvCreator')
99
100env = EnvCreator.Create(env)
101
102# Note: The relative paths in SConscript files are relative to the location
103# of the SConscript file itself. To make a path relative to the location of
104# the main SConstruct file, prepend the path with the # sign.
105#
106# But if a project uses variant builds without source duplication, the above
107# rule gets muddied a bit. In that case the paths must be counted from the
108# location of the copy of the SConscript file in scons/build/<config>/scons.
109#
110# Include paths to gtest headers are relative to either the gtest
111# directory or the 'include' subdirectory of it, and this SConscript
112# file is one directory deeper than the gtest directory.
113env.Prepend(CPPPATH = ['..', '../include'])
114
115env_use_own_tuple = EnvCreator.Create(env, EnvCreator.UseOwnTuple)
116env_less_optimized = EnvCreator.Create(env, EnvCreator.LessOptimized)
117env_with_threads = EnvCreator.Create(env, EnvCreator.WithThreads)
118# The following environments are used to compile gtest_unittest.cc, which
119# triggers a warning  in all but the most recent GCC versions when compiling
120# the EXPECT_EQ(NULL, ptr) statement.
121env_warning_ok = EnvCreator.Create(env, EnvCreator.WarningOk)
122env_with_exceptions = EnvCreator.Create(env_warning_ok,
123                                        EnvCreator.WithExceptions)
124env_without_rtti = EnvCreator.Create(env_warning_ok, EnvCreator.NoRtti)
125
126############################################################
127# Helpers for creating build targets.
128
129# Caches object file targets built by GtestObject to allow passing the
130# same source file with the same environment twice into the function as a
131# convenience.
132_all_objects = {}
133
134def GtestObject(build_env, source):
135  """Returns a target to build an object file from the given .cc source file."""
136
137  object_name = os.path.basename(source).rstrip('.cc') + build_env['OBJ_SUFFIX']
138  if object_name not in _all_objects:
139    _all_objects[object_name] = build_env.Object(target=object_name,
140                                                 source=source)
141  return _all_objects[object_name]
142
143
144def GtestStaticLibraries(build_env):
145  """Builds static libraries for gtest and gtest_main in build_env.
146
147  Args:
148    build_env: An environment in which to build libraries.
149
150  Returns:
151    A pair (gtest library, gtest_main library) built in the given environment.
152  """
153
154  gtest_object = GtestObject(build_env, '../src/gtest-all.cc')
155  gtest_main_object = GtestObject(build_env, '../src/gtest_main.cc')
156
157  return (build_env.StaticLibrary(target='gtest' + build_env['OBJ_SUFFIX'],
158                                  source=[gtest_object]),
159          build_env.StaticLibrary(target='gtest_main' + build_env['OBJ_SUFFIX'],
160                                  source=[gtest_object, gtest_main_object]))
161
162
163def GtestBinary(build_env, target, gtest_libs, sources):
164  """Creates a target to build a binary (either test or sample).
165
166  Args:
167    build_env:  The SCons construction environment to use to build.
168    target:     The basename of the target's main source file, also used as the
169                target name.
170    gtest_libs: The gtest library or the list of libraries to link.
171    sources:    A list of source files in the target.
172  """
173  srcs = []  # The object targets corresponding to sources.
174  for src in sources:
175    if type(src) is str:
176      srcs.append(GtestObject(build_env, src))
177    else:
178      srcs.append(src)
179
180  if not gtest_libs:
181    gtest_libs = []
182  elif type(gtest_libs) != type(list()):
183    gtest_libs = [gtest_libs]
184  binary = build_env.Program(target=target, source=srcs, LIBS=gtest_libs)
185  if 'EXE_OUTPUT' in build_env.Dictionary():
186    build_env.Install('$EXE_OUTPUT', source=[binary])
187
188
189def GtestTest(build_env, target, gtest_libs, additional_sources=None):
190  """Creates a target to build the given test.
191
192  Args:
193    build_env:  The SCons construction environment to use to build.
194    target:     The basename of the target test .cc file.
195    gtest_libs: The gtest library or the list of libraries to use.
196    additional_sources: A list of additional source files in the target.
197  """
198
199  GtestBinary(build_env, target, gtest_libs,
200              ['../test/%s.cc' % target] + (additional_sources or []))
201
202
203def GtestSample(build_env, target, additional_sources=None):
204  """Creates a target to build the given sample.
205
206  Args:
207    build_env:  The SCons construction environment to use to build.
208    target:     The basename of the target sample .cc file.
209    gtest_libs: The gtest library or the list of libraries to use.
210    additional_sources: A list of additional source files in the target.
211  """
212  GtestBinary(build_env, target, gtest_main,
213              ['../samples/%s.cc' % target] + (additional_sources or []))
214
215
216############################################################
217# Object and library targets.
218
219# gtest.lib to be used by most apps (if you have your own main function).
220# gtest_main.lib can be used if you just want a basic main function; it is also
221# used by some tests for Google Test itself.
222gtest, gtest_main = GtestStaticLibraries(env)
223gtest_ex, gtest_main_ex = GtestStaticLibraries(env_with_exceptions)
224gtest_no_rtti, gtest_main_no_rtti = GtestStaticLibraries(env_without_rtti)
225gtest_use_own_tuple, gtest_use_own_tuple_main = GtestStaticLibraries(
226    env_use_own_tuple)
227
228# Install the libraries if needed.
229if 'LIB_OUTPUT' in env.Dictionary():
230  env.Install('$LIB_OUTPUT', source=[gtest, gtest_main,
231                                     gtest_ex, gtest_main_ex,
232                                     gtest_no_rtti, gtest_main_no_rtti,
233                                     gtest_use_own_tuple,
234                                     gtest_use_own_tuple_main])
235
236############################################################
237# Test targets using the standard environment.
238
239GtestTest(env, 'gtest-filepath_test', gtest_main)
240GtestTest(env, 'gtest-message_test', gtest_main)
241GtestTest(env, 'gtest-options_test', gtest_main)
242GtestTest(env, 'gtest_environment_test', gtest)
243GtestTest(env, 'gtest_main_unittest', gtest_main)
244GtestTest(env, 'gtest_no_test_unittest', gtest)
245GtestTest(env, 'gtest_pred_impl_unittest', gtest_main)
246GtestTest(env, 'gtest_prod_test', gtest_main,
247          additional_sources=['../test/production.cc'])
248GtestTest(env, 'gtest_repeat_test', gtest)
249GtestTest(env, 'gtest_sole_header_test', gtest_main)
250GtestTest(env, 'gtest-test-part_test', gtest_main)
251GtestTest(env, 'gtest-typed-test_test', gtest_main,
252          additional_sources=['../test/gtest-typed-test2_test.cc'])
253GtestTest(env, 'gtest-param-test_test', gtest,
254          additional_sources=['../test/gtest-param-test2_test.cc'])
255GtestTest(env, 'gtest_color_test_', gtest)
256GtestTest(env, 'gtest-linked_ptr_test', gtest_main)
257GtestTest(env, 'gtest-port_test', gtest_main)
258GtestTest(env, 'gtest_break_on_failure_unittest_', gtest)
259GtestTest(env, 'gtest_filter_unittest_', gtest)
260GtestTest(env, 'gtest_help_test_', gtest_main)
261GtestTest(env, 'gtest_list_tests_unittest_', gtest)
262GtestTest(env, 'gtest_throw_on_failure_test_', gtest)
263GtestTest(env, 'gtest_xml_outfile1_test_', gtest_main)
264GtestTest(env, 'gtest_xml_outfile2_test_', gtest_main)
265GtestTest(env, 'gtest_xml_output_unittest_', gtest)
266GtestTest(env, 'gtest-unittest-api_test', gtest)
267GtestTest(env, 'gtest-listener_test', gtest)
268GtestTest(env, 'gtest_shuffle_test_', gtest)
269
270############################################################
271# Tests targets using custom environments.
272
273GtestTest(env_warning_ok, 'gtest_unittest', gtest_main)
274GtestTest(env_with_exceptions, 'gtest_output_test_', gtest_ex)
275GtestTest(env_with_exceptions, 'gtest_throw_on_failure_ex_test', gtest_ex)
276GtestTest(env_with_threads, 'gtest-death-test_test', gtest_main)
277GtestTest(env_less_optimized, 'gtest_env_var_test_', gtest)
278GtestTest(env_less_optimized, 'gtest_uninitialized_test_', gtest)
279GtestTest(env_use_own_tuple, 'gtest-tuple_test', gtest_use_own_tuple_main)
280GtestBinary(env_use_own_tuple,
281            'gtest_use_own_tuple_test',
282            gtest_use_own_tuple_main,
283            ['../test/gtest-param-test_test.cc',
284             '../test/gtest-param-test2_test.cc'])
285GtestBinary(env_with_exceptions, 'gtest_ex_unittest', gtest_main_ex,
286            ['../test/gtest_unittest.cc'])
287GtestBinary(env_without_rtti, 'gtest_no_rtti_test', gtest_main_no_rtti,
288            ['../test/gtest_unittest.cc'])
289
290############################################################
291# Sample targets.
292
293# Use the GTEST_BUILD_SAMPLES build variable to control building of samples.
294# In your SConstruct file, add
295#   vars = Variables()
296#   vars.Add(BoolVariable('GTEST_BUILD_SAMPLES', 'Build samples', False))
297#   my_environment = Environment(variables = vars, ...)
298# Then, in the command line use GTEST_BUILD_SAMPLES=true to enable them.
299if env.get('GTEST_BUILD_SAMPLES', False):
300  GtestSample(env, 'sample1_unittest',
301              additional_sources=['../samples/sample1.cc'])
302  GtestSample(env, 'sample2_unittest',
303              additional_sources=['../samples/sample2.cc'])
304  GtestSample(env, 'sample3_unittest')
305  GtestSample(env, 'sample4_unittest',
306              additional_sources=['../samples/sample4.cc'])
307  GtestSample(env, 'sample5_unittest',
308              additional_sources=['../samples/sample1.cc'])
309  GtestSample(env, 'sample6_unittest')
310  GtestSample(env, 'sample7_unittest')
311  GtestSample(env, 'sample8_unittest')
312  GtestSample(env, 'sample9_unittest')
313  GtestSample(env, 'sample10_unittest')
314
315# These exports are used by Google Mock.
316gtest_exports = {'gtest': gtest,
317                 'gtest_ex': gtest_ex,
318                 'gtest_no_rtti': gtest_no_rtti,
319                 'gtest_use_own_tuple': gtest_use_own_tuple,
320                 'EnvCreator': EnvCreator,
321                 'GtestObject': GtestObject,
322                 'GtestBinary': GtestBinary,
323                 'GtestTest': GtestTest}
324# Makes the gtest_exports dictionary available to the invoking SConstruct.
325Return('gtest_exports')
326