Add a //nogncheck anntation to GN include checker
The include checker will now skip includes annotated with "// nogncheck" which allows some edge cases to be worked around while still running the check pass on the rest of the includes.
This also updates the reference docs to the latest version.
Review URL: https://codereview.chromium.org/1217093007
Cr-Original-Commit-Position: refs/heads/master@{#337499}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 20982dc0654c13678837bdb4c08e1bcc94248fcf
diff --git a/tools/gn/c_include_iterator.cc b/tools/gn/c_include_iterator.cc
index 25eba9d..9e719c7 100644
--- a/tools/gn/c_include_iterator.cc
+++ b/tools/gn/c_include_iterator.cc
@@ -105,6 +105,11 @@
return type;
}
+// Returns true if this line has a "nogncheck" comment associated with it.
+bool HasNoCheckAnnotation(const base::StringPiece& line) {
+ return line.find("nogncheck") != base::StringPiece::npos;
+}
+
} // namespace
const int CIncludeIterator::kMaxNonIncludeLines = 10;
@@ -129,7 +134,7 @@
base::StringPiece include_contents;
int begin_char;
IncludeType type = ExtractInclude(line, &include_contents, &begin_char);
- if (type == INCLUDE_USER) {
+ if (type == INCLUDE_USER && !HasNoCheckAnnotation(line)) {
// Only count user includes for now.
*out = include_contents;
*location = LocationRange(
diff --git a/tools/gn/c_include_iterator_unittest.cc b/tools/gn/c_include_iterator_unittest.cc
index c5b9714..11fa991 100644
--- a/tools/gn/c_include_iterator_unittest.cc
+++ b/tools/gn/c_include_iterator_unittest.cc
@@ -29,6 +29,8 @@
buffer.append("\n");
buffer.append(" #include \"foo/baz.h\"\n"); // Leading whitespace
buffer.append("#include \"la/deda.h\"\n");
+ // Line annotated with "// nogncheck"
+ buffer.append("#include \"should_be_skipped.h\" // nogncheck\n");
buffer.append("#import \"weird_mac_import.h\"\n");
buffer.append("\n");
buffer.append("void SomeCode() {\n");
@@ -52,9 +54,11 @@
EXPECT_EQ("la/deda.h", contents);
EXPECT_TRUE(RangeIs(range, 8, 11, 20)) << range.begin().Describe(true);
+ // The line annotated with "nogncheck" should be skipped.
+
EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
EXPECT_EQ("weird_mac_import.h", contents);
- EXPECT_TRUE(RangeIs(range, 9, 10, 28)) << range.begin().Describe(true);
+ EXPECT_TRUE(RangeIs(range, 10, 10, 28)) << range.begin().Describe(true);
EXPECT_FALSE(iter.GetNextIncludeString(&contents, &range));
}
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md
index c55f42e..ad3ac85 100644
--- a/tools/gn/docs/reference.md
+++ b/tools/gn/docs/reference.md
@@ -1011,6 +1011,7 @@
```
Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
defines, include_dirs, ldflags, lib_dirs, libs
+ precompiled_header, precompiled_source
```
@@ -1209,6 +1210,7 @@
```
Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
defines, include_dirs, ldflags, lib_dirs, libs
+ precompiled_header, precompiled_source
Deps: data_deps, deps, forward_dependent_configs_from, public_deps
Dependent configs: all_dependent_configs, public_configs
General: check_includes, configs, data, inputs, output_name,
@@ -1920,6 +1922,7 @@
```
Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
defines, include_dirs, ldflags, lib_dirs, libs
+ precompiled_header, precompiled_source
Deps: data_deps, deps, forward_dependent_configs_from, public_deps
Dependent configs: all_dependent_configs, public_configs
General: check_includes, configs, data, inputs, output_name,
@@ -1960,6 +1963,7 @@
```
Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
defines, include_dirs, ldflags, lib_dirs, libs
+ precompiled_header, precompiled_source
Deps: data_deps, deps, forward_dependent_configs_from, public_deps
Dependent configs: all_dependent_configs, public_configs
General: check_includes, configs, data, inputs, output_name,
@@ -1983,6 +1987,7 @@
```
Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
defines, include_dirs, ldflags, lib_dirs, libs
+ precompiled_header, precompiled_source
Deps: data_deps, deps, forward_dependent_configs_from, public_deps
Dependent configs: all_dependent_configs, public_configs
General: check_includes, configs, data, inputs, output_name,
@@ -2292,6 +2297,20 @@
Posix systems:
output_prefix = "lib"
+ precompiled_header_type [string]
+ Valid for: "cc", "cxx", "objc", "objcxx"
+
+ Type of precompiled headers. If undefined or the empty string,
+ precompiled headers will not be used for this tool. Otherwise
+ use "msvc" which is the only currently supported value.
+
+ For precompiled headers to be used for a given target, the
+ target (or a config applied to it) must also specify a
+ "precompiled_header" and, for "msvc"-style headers, a
+ "precompiled_source" value.
+
+ See "gn help precompiled_header" for more.
+
restat [boolean]
Valid for: all tools (optional, defaults to false)
@@ -2332,6 +2351,7 @@
```
### **Expansions for tool variables**
+
```
All paths are relative to the root build directory, which is the
current directory for running all tools. These expansions are
@@ -3242,6 +3262,30 @@
```
+### **Controlling includes individually**
+
+```
+ If only certain includes are problematic, you can annotate them
+ individually rather than disabling header checking on an entire
+ target. Add the string "nogncheck" to the include line:
+
+ #include "foo/something_weird.h" // nogncheck (bug 12345)
+
+ It is good form to include a reference to a bug (if the include is
+ improper, or some other comment expressing why the header checker
+ doesn't work for this particular case.
+
+ The most common reason to need "nogncheck" is conditional includes.
+ The header checker does not understand the preprocessor, so may flag
+ some includes as improper even if the dependencies and #defines are
+ always matched correctly:
+
+ #if defined(ENABLE_DOOM_MELON)
+ #include "doom_melon/beam_controller.h" // nogncheck
+ #endif
+
+```
+
### **Example**
```
@@ -3772,6 +3816,77 @@
```
+## **precompiled_header**: [string] Header file to precompile.
+
+```
+ Precompiled headers will be used when a target specifies this
+ value, or a config applying to this target specifies this value.
+ In addition, the tool corresponding to the source files must also
+ specify precompiled headers (see "gn help tool"). The tool
+ will also specify what type of precompiled headers to use.
+
+ The precompiled header/source variables can be specified on a target
+ or a config, but must be the same for all configs applying to a given
+ target since a target can only have one precompiled header.
+
+```
+
+### **MSVC precompiled headers**
+
+```
+ When using MSVC-style precompiled headers, the "precompiled_header"
+ value is a string corresponding to the header. This is NOT a path
+ to a file that GN recognises, but rather the exact string that appears
+ in quotes after an #include line in source code. The compiler will
+ match this string against includes or forced includes (/FI).
+
+ MSVC also requires a source file to compile the header with. This must
+ be specified by the "precompiled_source" value. In contrast to the
+ header value, this IS a GN-style file name, and tells GN which source
+ file to compile to make the .pch file used for subsequent compiles.
+
+ If you use both C and C++ sources, the precompiled header and source
+ file will be compiled using both tools. You will want to make sure
+ to wrap C++ includes in __cplusplus #ifdefs so the file will compile
+ in C mode.
+
+ For example, if the toolchain specifies MSVC headers:
+
+ toolchain("vc_x64") {
+ ...
+ tool("cxx") {
+ precompiled_header_type = "msvc"
+ ...
+
+ You might make a config like this:
+
+ config("use_precompiled_headers") {
+ precompiled_header = "build/precompile.h"
+ precompiled_source = "//build/precompile.cc"
+
+ # Either your source files should #include "build/precompile.h"
+ # first, or you can do this to force-include the header.
+ cflags = [ "/FI$precompiled_header" ]
+ }
+
+ And then define a target that uses the config:
+
+ executable("doom_melon") {
+ configs += [ ":use_precompiled_headers" ]
+ ...
+
+
+
+```
+## **precompiled_source**: [file name] Source file to precompile.
+
+```
+ The source file that goes along with the precompiled_header when
+ using "msvc"-style precompiled headers. It will be implicitly added
+ to the sources of the target. See "gn help precompiled_header".
+
+
+```
## **public**: Declare public header files for a target.
```
diff --git a/tools/gn/variables.cc b/tools/gn/variables.cc
index 472554a..0f3ede7 100644
--- a/tools/gn/variables.cc
+++ b/tools/gn/variables.cc
@@ -442,6 +442,27 @@
" This does not affect other targets that depend on the current target,\n"
" it just skips checking the includes of the current target's files.\n"
"\n"
+ "Controlling includes individually\n"
+ "\n"
+ " If only certain includes are problematic, you can annotate them\n"
+ " individually rather than disabling header checking on an entire\n"
+ " target. Add the string \"nogncheck\" to the include line:\n"
+ "\n"
+ " #include \"foo/something_weird.h\" // nogncheck (bug 12345)\n"
+ "\n"
+ " It is good form to include a reference to a bug (if the include is\n"
+ " improper, or some other comment expressing why the header checker\n"
+ " doesn't work for this particular case.\n"
+ "\n"
+ " The most common reason to need \"nogncheck\" is conditional includes.\n"
+ " The header checker does not understand the preprocessor, so may flag\n"
+ " some includes as improper even if the dependencies and #defines are\n"
+ " always matched correctly:\n"
+ "\n"
+ " #if defined(ENABLE_DOOM_MELON)\n"
+ " #include \"doom_melon/beam_controller.h\" // nogncheck\n"
+ " #endif\n"
+ "\n"
"Example\n"
"\n"
" source_set(\"busted_includes\") {\n"