blob: 1440f29ef06f86d3f8e993c2abdba321a70ee158 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001From afcd4a146fb82843f6ff695f89504ce4ca65ddfd Mon Sep 17 00:00:00 2001
2From: David 'Digit' Turner <digit+github@google.com>
3Date: Sun, 12 May 2024 23:45:28 +0200
4Subject: [PATCH] configure.py: Support --gtest-source-dir to build tests.
5
6Allow the Ninja build plan generated by configure.py to
7build `ninja_test` by compiling GoogleTest from source if
8the path to the library if passed through the new option
9`--gtest-source-dir` or the GTEST_SOURCE_DIR environment
10variable.
11
12For simplicity, probing for an installed version of the
13library, and linking to it, is not supported (use the
14CMake build for this).
15
16This also removes the obsolete `--gtest-dir` option.
17
18+ Update README.md
19
20Fixes #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: