https://bugs.gentoo.org/929221 https://github.com/ninja-build/ninja/issues/2447 https://github.com/ninja-build/ninja/commit/afcd4a146fb82843f6ff695f89504ce4ca65ddfd From afcd4a146fb82843f6ff695f89504ce4ca65ddfd Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Sun, 12 May 2024 23:45:28 +0200 Subject: [PATCH] configure.py: Support --gtest-source-dir to build tests. Allow the Ninja build plan generated by configure.py to build `ninja_test` by compiling GoogleTest from source if the path to the library if passed through the new option `--gtest-source-dir` or the GTEST_SOURCE_DIR environment variable. For simplicity, probing for an installed version of the library, and linking to it, is not supported (use the CMake build for this). This also removes the obsolete `--gtest-dir` option. Fixes #2447 --- configure.py | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/configure.py b/configure.py index f9e49f9cdf..2b16618c43 100755 --- a/configure.py +++ b/configure.py @@ -223,7 +223,10 @@ def _run_command(self, cmdline: str) -> None: parser.add_option('--profile', metavar='TYPE', choices=profilers, help='enable profiling (' + '/'.join(profilers) + ')',) -parser.add_option('--with-gtest', metavar='PATH', help='ignored') +parser.add_option('--gtest-source-dir', metavar='PATH', + help='Path to GoogleTest source directory. If not provided ' + + 'GTEST_SOURCE_DIR will be probed in the environment. ' + + 'Tests will not be built without a value.') parser.add_option('--with-python', metavar='EXE', help='use EXE as the Python interpreter', default=os.path.basename(sys.executable)) @@ -435,6 +438,7 @@ def shell_escape(str: str) -> str: if 'LDFLAGS' in configure_env: ldflags.append(configure_env['LDFLAGS']) n.variable('ldflags', ' '.join(shell_escape(flag) for flag in ldflags)) + n.newline() if platform.is_msvc(): @@ -592,6 +596,83 @@ def has_re2c() -> bool: # build.ninja file. n = ninja_writer +# Build the ninja_test executable only if the GTest source directory +# is provided explicitly. Either from the environment with GTEST_SOURCE_DIR +# or with the --gtest-source-dir command-line option. +# +# Do not try to look for an installed binary version, and link against it +# because doing so properly is platform-specific (use the CMake build for +# this). +if options.gtest_source_dir: + gtest_src_dir = options.gtest_source_dir +else: + gtest_src_dir = os.environ.get('GTEST_SOURCE_DIR') + +if gtest_src_dir: + # Verify GoogleTest source directory, and add its include directory + # to the global include search path (even for non-test sources) to + # keep the build plan generation simple. + gtest_all_cc = os.path.join(gtest_src_dir, 'googletest', 'src', 'gtest-all.cc') + if not os.path.exists(gtest_all_cc): + print('ERROR: Missing GoogleTest source file: %s' % gtest_all_cc) + sys.exit(1) + + n.comment('Tests all build into ninja_test executable.') + + # Test-specific version of cflags, must include the GoogleTest + # include directory. Also GoogleTest can only build with a C++14 compiler. + test_cflags = [f.replace('std=c++11', 'std=c++14') for f in cflags] + test_cflags.append('-I' + os.path.join(gtest_src_dir, 'googletest', 'include')) + + test_variables = [('cflags', test_cflags)] + if platform.is_msvc(): + test_variables += [('pdb', 'ninja_test.pdb')] + + test_names = [ + 'build_log_test', + 'build_test', + 'clean_test', + 'clparser_test', + 'depfile_parser_test', + 'deps_log_test', + 'disk_interface_test', + 'dyndep_parser_test', + 'edit_distance_test', + 'graph_test', + 'json_test', + 'lexer_test', + 'manifest_parser_test', + 'ninja_test', + 'state_test', + 'string_piece_util_test', + 'subprocess_test', + 'test', + 'util_test', + ] + if platform.is_windows(): + test_names += [ + 'includes_normalize_test', + 'msvc_helper_test', + ] + + objs = [] + for name in test_names: + objs += cxx(name, variables=test_variables) + + # Build GTest as a monolithic source file. + # This requires one extra include search path, so replace the + # value of 'cflags' in our list. + gtest_all_variables = test_variables[1:] + [ + ('cflags', test_cflags + ['-I' + os.path.join(gtest_src_dir, 'googletest') ]), + ] + # Do not use cxx() directly to ensure the object file is under $builddir. + objs += n.build(built('gtest_all' + objext), 'cxx', gtest_all_cc, variables=gtest_all_variables) + + ninja_test = n.build(binary('ninja_test'), 'link', objs, implicit=ninja_lib, + variables=[('libs', libs)]) + n.newline() + all_targets += ninja_test + n.comment('Ancillary executables.') if platform.is_aix() and '-maix64' not in ldflags: