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