xref: /aosp_15_r20/external/cronet/build/nocompile.gni (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1# Copyright 2011 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5# This file is meant to be included into an target to create a unittest that
6# invokes a set of no-compile tests.  A no-compile test is a test that asserts
7# a particular construct will not compile.
8#
9# Usage:
10#
11# 1. Create a GN target:
12#
13#    import("//build/nocompile.gni")
14#
15#    nocompile_source_set("base_nocompile_tests") {
16#      sources = [
17#        "functional/one_not_equal_two_nocompile.nc",
18#      ]
19#      deps = [
20#        ":base"
21#      ]
22#    }
23#
24#    Note that by convention, nocompile tests use the `.nc` extension rather
25#    than the standard `.cc` extension: this is because the expectation lines
26#    often exceed 80 characters, which would make clang-format unhappy.
27#
28# 2. Add a dep from a related test binary to the nocompile source set:
29#
30#    test("base_unittests") {
31#      ...
32#      deps += [ ":base_nocompile_tests" ]
33#    }
34#
35# 3. Populate the .nc file with test cases. Expected compile failures should be
36#    annotated with a comment of the form:
37#
38#    // expected-error {{<expected error string here>}}
39#
40#    For example:
41#
42#    void OneDoesNotEqualTwo() {
43#      static_assert(1 == 2);  // expected-error {{static assertion failed due to requirement '1 == 2'}}
44#    }
45#
46#    The verification logic is built as part of clang; full documentation is at
47#    https://clang.llvm.org/doxygen/classclang_1_1VerifyDiagnosticConsumer.html.
48#
49# Also see:
50#   http://dev.chromium.org/developers/testing/no-compile-tests
51#
52import("//build/config/clang/clang.gni")
53if (is_win) {
54  import("//build/toolchain/win/win_toolchain_data.gni")
55}
56
57declare_args() {
58  enable_nocompile_tests = is_clang && !is_nacl
59}
60
61if (enable_nocompile_tests) {
62  template("nocompile_source_set") {
63    action_foreach(target_name) {
64      testonly = true
65
66      script = "//tools/nocompile/wrapper.py"
67      sources = invoker.sources
68      if (defined(invoker.deps)) {
69        deps = invoker.deps
70      }
71
72      # An action is not a compiler, so configs is empty until it is explicitly
73      # set.
74      configs = default_compiler_configs
75      if (defined(invoker.configs)) {
76        configs += invoker.configs
77      }
78
79      # Disable the checks that the Chrome style plugin normally enforces to
80      # reduce the amount of boilerplate needed in nocompile tests.
81      configs -= [ "//build/config/clang:find_bad_constructs" ]
82
83      if (is_win) {
84        result_path =
85            "$target_out_dir/$target_name/{{source_name_part}}_placeholder.obj"
86      } else {
87        result_path =
88            "$target_out_dir/$target_name/{{source_name_part}}_placeholder.o"
89      }
90      rebased_obj_path = rebase_path(result_path, root_build_dir)
91
92      depfile = "${result_path}.d"
93      rebased_depfile_path = rebase_path(depfile, root_build_dir)
94      outputs = [ result_path ]
95
96      if (is_win) {
97        if (host_os == "win") {
98          cxx = "clang-cl.exe"
99        } else {
100          cxx = "clang-cl"
101        }
102      } else {
103        cxx = "clang++"
104      }
105
106      args = []
107
108      if (is_win) {
109        # ninja normally parses /showIncludes output, but the depsformat
110        # variable can only be set in compiler tools, not for custom actions.
111        # Unfortunately, this means the clang wrapper needs to generate the
112        # depfile itself.
113        args += [ "--generate-depfile" ]
114      }
115
116      args += [
117        rebase_path("$clang_base_path/bin/$cxx", root_build_dir),
118        "{{source}}",
119        rebased_obj_path,
120        rebased_depfile_path,
121        "--",
122        "{{cflags}}",
123        "{{cflags_cc}}",
124        "{{defines}}",
125        "{{include_dirs}}",
126
127        # No need to generate an object file for nocompile tests.
128        "-Xclang",
129        "-fsyntax-only",
130
131        # Enable clang's VerifyDiagnosticConsumer:
132        # https://clang.llvm.org/doxygen/classclang_1_1VerifyDiagnosticConsumer.html
133        "-Xclang",
134        "-verify",
135
136        # But don't require expected-note comments since that is not the
137        # primary point of the nocompile tests.
138        "-Xclang",
139        "-verify-ignore-unexpected=note",
140
141        # Disable the error limit so that nocompile tests do not need to be
142        # arbitrarily split up when they hit the default error limit.
143        "-ferror-limit=0",
144
145        # So funny characters don't show up in error messages.
146        "-fno-color-diagnostics",
147
148        # Always treat warnings as errors.
149        "-Werror",
150      ]
151
152      if (!is_win) {
153        args += [
154          # On non-Windows platforms, clang can generate the depfile.
155          "-MMD",
156          "-MF",
157          rebased_depfile_path,
158          "-MT",
159          rebased_obj_path,
160
161          # Non-Windows clang uses file extensions to determine how to treat
162          # various inputs, so explicitly tell it to treat all inputs (even
163          # those with weird extensions like .nc) as C++ source files.
164          "-x",
165          "c++",
166        ]
167      } else {
168        # For some reason, the Windows includes are not part of the default
169        # compiler configs. Set it explicitly here, since things like libc++
170        # depend on the VC runtime.
171        if (target_cpu == "x86") {
172          win_toolchain_data = win_toolchain_data_x86
173        } else if (target_cpu == "x64") {
174          win_toolchain_data = win_toolchain_data_x64
175        } else if (target_cpu == "arm64") {
176          win_toolchain_data = win_toolchain_data_arm64
177        } else {
178          error("Unsupported target_cpu, add it to win_toolchain_data.gni")
179        }
180        args += win_toolchain_data.include_flags_imsvc_list
181        args += [ "/showIncludes:user" ]
182      }
183
184      # Note: for all platforms, the depfile only lists user includes, and not
185      # system includes. If system includes change, the compiler flags are
186      # expected to artificially change in some way to invalidate and force the
187      # nocompile tests to run again.
188    }
189  }
190}
191