b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | From afcd4a146fb82843f6ff695f89504ce4ca65ddfd Mon Sep 17 00:00:00 2001 |
| 2 | From: David 'Digit' Turner <digit+github@google.com> |
| 3 | Date: Sun, 12 May 2024 23:45:28 +0200 |
| 4 | Subject: [PATCH] configure.py: Support --gtest-source-dir to build tests. |
| 5 | |
| 6 | Allow the Ninja build plan generated by configure.py to |
| 7 | build `ninja_test` by compiling GoogleTest from source if |
| 8 | the path to the library if passed through the new option |
| 9 | `--gtest-source-dir` or the GTEST_SOURCE_DIR environment |
| 10 | variable. |
| 11 | |
| 12 | For simplicity, probing for an installed version of the |
| 13 | library, and linking to it, is not supported (use the |
| 14 | CMake build for this). |
| 15 | |
| 16 | This also removes the obsolete `--gtest-dir` option. |
| 17 | |
| 18 | + Update README.md |
| 19 | |
| 20 | Fixes #2447 |
| 21 | --- |
| 22 | README.md | 13 ++++++++ |
| 23 | configure.py | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++- |
| 24 | 2 files changed, 95 insertions(+), 1 deletion(-) |
| 25 | |
| 26 | --- a/README.md |
| 27 | +++ b/README.md |
| 28 | @@ -34,6 +34,19 @@ via CMake. For more details see |
| 29 | This will generate the `ninja` binary and a `build.ninja` file you can now use |
| 30 | to build Ninja with itself. |
| 31 | |
| 32 | +If you have a GoogleTest source directory, you can build the tests |
| 33 | +by passing its path with `--gtest-source-dir=PATH` option, or the |
| 34 | +`GTEST_SOURCE_DIR` environment variable, e.g.: |
| 35 | + |
| 36 | +``` |
| 37 | +./configure.py --bootstrap --gtest-source-dir=/path/to/googletest |
| 38 | +./ninja all # build ninja_test and other auxiliary binaries |
| 39 | +./ninja_test` # run the unit-test suite. |
| 40 | +``` |
| 41 | + |
| 42 | +Use the CMake build below if you want to use a preinstalled binary |
| 43 | +version of the library. |
| 44 | + |
| 45 | ### CMake |
| 46 | |
| 47 | ``` |
| 48 | --- a/configure.py |
| 49 | +++ b/configure.py |
| 50 | @@ -213,7 +213,10 @@ parser.add_option('--debug', action='sto |
| 51 | parser.add_option('--profile', metavar='TYPE', |
| 52 | choices=profilers, |
| 53 | help='enable profiling (' + '/'.join(profilers) + ')',) |
| 54 | -parser.add_option('--with-gtest', metavar='PATH', help='ignored') |
| 55 | +parser.add_option('--gtest-source-dir', metavar='PATH', |
| 56 | + help='Path to GoogleTest source directory. If not provided ' + |
| 57 | + 'GTEST_SOURCE_DIR will be probed in the environment. ' + |
| 58 | + 'Tests will not be built without a value.') |
| 59 | parser.add_option('--with-python', metavar='EXE', |
| 60 | help='use EXE as the Python interpreter', |
| 61 | default=os.path.basename(sys.executable)) |
| 62 | @@ -425,6 +428,7 @@ n.variable('cflags', ' '.join(shell_esca |
| 63 | if 'LDFLAGS' in configure_env: |
| 64 | ldflags.append(configure_env['LDFLAGS']) |
| 65 | n.variable('ldflags', ' '.join(shell_escape(flag) for flag in ldflags)) |
| 66 | + |
| 67 | n.newline() |
| 68 | |
| 69 | if platform.is_msvc(): |
| 70 | @@ -582,6 +586,83 @@ if options.bootstrap: |
| 71 | # build.ninja file. |
| 72 | n = ninja_writer |
| 73 | |
| 74 | +# Build the ninja_test executable only if the GTest source directory |
| 75 | +# is provided explicitly. Either from the environment with GTEST_SOURCE_DIR |
| 76 | +# or with the --gtest-source-dir command-line option. |
| 77 | +# |
| 78 | +# Do not try to look for an installed binary version, and link against it |
| 79 | +# because doing so properly is platform-specific (use the CMake build for |
| 80 | +# this). |
| 81 | +if options.gtest_source_dir: |
| 82 | + gtest_src_dir = options.gtest_source_dir |
| 83 | +else: |
| 84 | + gtest_src_dir = os.environ.get('GTEST_SOURCE_DIR') |
| 85 | + |
| 86 | +if gtest_src_dir: |
| 87 | + # Verify GoogleTest source directory, and add its include directory |
| 88 | + # to the global include search path (even for non-test sources) to |
| 89 | + # keep the build plan generation simple. |
| 90 | + gtest_all_cc = os.path.join(gtest_src_dir, 'googletest', 'src', 'gtest-all.cc') |
| 91 | + if not os.path.exists(gtest_all_cc): |
| 92 | + print('ERROR: Missing GoogleTest source file: %s' % gtest_all_cc) |
| 93 | + sys.exit(1) |
| 94 | + |
| 95 | + n.comment('Tests all build into ninja_test executable.') |
| 96 | + |
| 97 | + # Test-specific version of cflags, must include the GoogleTest |
| 98 | + # include directory. Also GoogleTest can only build with a C++14 compiler. |
| 99 | + test_cflags = [f.replace('std=c++11', 'std=c++14') for f in cflags] |
| 100 | + test_cflags.append('-I' + os.path.join(gtest_src_dir, 'googletest', 'include')) |
| 101 | + |
| 102 | + test_variables = [('cflags', test_cflags)] |
| 103 | + if platform.is_msvc(): |
| 104 | + test_variables += [('pdb', 'ninja_test.pdb')] |
| 105 | + |
| 106 | + test_names = [ |
| 107 | + 'build_log_test', |
| 108 | + 'build_test', |
| 109 | + 'clean_test', |
| 110 | + 'clparser_test', |
| 111 | + 'depfile_parser_test', |
| 112 | + 'deps_log_test', |
| 113 | + 'disk_interface_test', |
| 114 | + 'dyndep_parser_test', |
| 115 | + 'edit_distance_test', |
| 116 | + 'graph_test', |
| 117 | + 'json_test', |
| 118 | + 'lexer_test', |
| 119 | + 'manifest_parser_test', |
| 120 | + 'ninja_test', |
| 121 | + 'state_test', |
| 122 | + 'string_piece_util_test', |
| 123 | + 'subprocess_test', |
| 124 | + 'test', |
| 125 | + 'util_test', |
| 126 | + ] |
| 127 | + if platform.is_windows(): |
| 128 | + test_names += [ |
| 129 | + 'includes_normalize_test', |
| 130 | + 'msvc_helper_test', |
| 131 | + ] |
| 132 | + |
| 133 | + objs = [] |
| 134 | + for name in test_names: |
| 135 | + objs += cxx(name, variables=test_variables) |
| 136 | + |
| 137 | + # Build GTest as a monolithic source file. |
| 138 | + # This requires one extra include search path, so replace the |
| 139 | + # value of 'cflags' in our list. |
| 140 | + gtest_all_variables = test_variables[1:] + [ |
| 141 | + ('cflags', test_cflags + ['-I' + os.path.join(gtest_src_dir, 'googletest') ]), |
| 142 | + ] |
| 143 | + # Do not use cxx() directly to ensure the object file is under $builddir. |
| 144 | + objs += n.build(built('gtest_all' + objext), 'cxx', gtest_all_cc, variables=gtest_all_variables) |
| 145 | + |
| 146 | + ninja_test = n.build(binary('ninja_test'), 'link', objs, implicit=ninja_lib, |
| 147 | + variables=[('libs', libs)]) |
| 148 | + n.newline() |
| 149 | + all_targets += ninja_test |
| 150 | + |
| 151 | n.comment('Ancillary executables.') |
| 152 | |
| 153 | if platform.is_aix() and '-maix64' not in ldflags: |