Home | History | Annotate | Download | only in scons
      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,
     32 Linux, Mac OS X, and Cygwin.  The compilation settings from your project
     33 will be used, with some specific flags required for gtest added.
     34 
     35 You should be able to call this file from more or less any SConscript
     36 file.
     37 
     38 You can optionally set a variable on the construction environment to
     39 have the unit test executables copied to your output directory.  The
     40 variable should be env['EXE_OUTPUT'].
     41 
     42 Another optional variable is env['LIB_OUTPUT'].  If set, the generated
     43 libraries are copied to the folder indicated by the variable.
     44 
     45 If you place the gtest sources within your own project's source
     46 directory, you should be able to call this SConscript file simply as
     47 follows:
     48 
     49 # -- cut here --
     50 # Build gtest library; first tell it where to copy executables.
     51 env['EXE_OUTPUT'] = '#/mybuilddir/mybuildmode'  # example, optional
     52 env['LIB_OUTPUT'] = '#/mybuilddir/mybuildmode/lib'
     53 env.SConscript('whateverpath/gtest/scons/SConscript')
     54 # -- cut here --
     55 
     56 If on the other hand you place the gtest sources in a directory
     57 outside of your project's source tree, you would use a snippet similar
     58 to 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.
     71 gtest_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.
     76 gtest_dir.addRepository(env.Dir('../../gtest'))
     77 
     78 # Tell the gtest SCons file where to copy executables.
     79 env['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'
     84 env.SConscript(env.File('scons/SConscript', gtest_dir))
     85 
     86 # -- cut here --
     87 """
     88 
     89 
     90 __author__ = 'joi (a] google.com (Joi Sigurdsson)'
     91 
     92 
     93 import os
     94 
     95 ############################################################
     96 # Environments for building the targets, sorted by name.
     97 
     98 Import('env', 'EnvCreator')
     99 
    100 env = 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.
    113 env.Prepend(CPPPATH = ['..', '../include'])
    114 
    115 env_use_own_tuple = EnvCreator.Create(env, EnvCreator.UseOwnTuple)
    116 env_less_optimized = EnvCreator.Create(env, EnvCreator.LessOptimized)
    117 env_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.
    121 env_warning_ok = EnvCreator.Create(env, EnvCreator.WarningOk)
    122 env_with_exceptions = EnvCreator.Create(env_warning_ok,
    123                                         EnvCreator.WithExceptions)
    124 env_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 
    134 def 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 
    144 def 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 
    163 def 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 
    189 def 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 
    203 def 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.
    222 gtest, gtest_main = GtestStaticLibraries(env)
    223 gtest_ex, gtest_main_ex = GtestStaticLibraries(env_with_exceptions)
    224 gtest_no_rtti, gtest_main_no_rtti = GtestStaticLibraries(env_without_rtti)
    225 gtest_use_own_tuple, gtest_use_own_tuple_main = GtestStaticLibraries(
    226     env_use_own_tuple)
    227 
    228 # Install the libraries if needed.
    229 if '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 
    239 GtestTest(env, 'gtest-filepath_test', gtest_main)
    240 GtestTest(env, 'gtest-message_test', gtest_main)
    241 GtestTest(env, 'gtest-options_test', gtest_main)
    242 GtestTest(env, 'gtest_environment_test', gtest)
    243 GtestTest(env, 'gtest_main_unittest', gtest_main)
    244 GtestTest(env, 'gtest_no_test_unittest', gtest)
    245 GtestTest(env, 'gtest_pred_impl_unittest', gtest_main)
    246 GtestTest(env, 'gtest_prod_test', gtest_main,
    247           additional_sources=['../test/production.cc'])
    248 GtestTest(env, 'gtest_repeat_test', gtest)
    249 GtestTest(env, 'gtest_sole_header_test', gtest_main)
    250 GtestTest(env, 'gtest-test-part_test', gtest_main)
    251 GtestTest(env, 'gtest-typed-test_test', gtest_main,
    252           additional_sources=['../test/gtest-typed-test2_test.cc'])
    253 GtestTest(env, 'gtest-param-test_test', gtest,
    254           additional_sources=['../test/gtest-param-test2_test.cc'])
    255 GtestTest(env, 'gtest_color_test_', gtest)
    256 GtestTest(env, 'gtest-linked_ptr_test', gtest_main)
    257 GtestTest(env, 'gtest-port_test', gtest_main)
    258 GtestTest(env, 'gtest_break_on_failure_unittest_', gtest)
    259 GtestTest(env, 'gtest_filter_unittest_', gtest)
    260 GtestTest(env, 'gtest_help_test_', gtest_main)
    261 GtestTest(env, 'gtest_list_tests_unittest_', gtest)
    262 GtestTest(env, 'gtest_throw_on_failure_test_', gtest)
    263 GtestTest(env, 'gtest_xml_outfile1_test_', gtest_main)
    264 GtestTest(env, 'gtest_xml_outfile2_test_', gtest_main)
    265 GtestTest(env, 'gtest_xml_output_unittest_', gtest)
    266 GtestTest(env, 'gtest-unittest-api_test', gtest)
    267 GtestTest(env, 'gtest-listener_test', gtest)
    268 GtestTest(env, 'gtest_shuffle_test_', gtest)
    269 
    270 ############################################################
    271 # Tests targets using custom environments.
    272 
    273 GtestTest(env_warning_ok, 'gtest_unittest', gtest_main)
    274 GtestTest(env_with_exceptions, 'gtest_output_test_', gtest_ex)
    275 GtestTest(env_with_exceptions, 'gtest_throw_on_failure_ex_test', gtest_ex)
    276 GtestTest(env_with_threads, 'gtest-death-test_test', gtest_main)
    277 GtestTest(env_less_optimized, 'gtest_env_var_test_', gtest)
    278 GtestTest(env_less_optimized, 'gtest_uninitialized_test_', gtest)
    279 GtestTest(env_use_own_tuple, 'gtest-tuple_test', gtest_use_own_tuple_main)
    280 GtestBinary(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'])
    285 GtestBinary(env_with_exceptions, 'gtest_ex_unittest', gtest_main_ex,
    286             ['../test/gtest_unittest.cc'])
    287 GtestBinary(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.
    299 if 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.
    316 gtest_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.
    325 Return('gtest_exports')
    326