|
| 1 | +--- |
| 2 | +title: "/external (External headers diagnostics)" |
| 3 | +description: "The Microsoft C++ compiler /external headers diagnostic options syntax and usage." |
| 4 | +ms.date: 05/14/2021 |
| 5 | +f1_keywords: ["/external", "/external:anglebrackets", "/external:env:", "/external:I", "/external:W0", "/external:W1", "/external:W2", "/external:W3", "/external:W4", "/external:templates-", "/experimental:external"] |
| 6 | +helpviewer_keywords: ["/external compiler option [C++]", "-external compiler option [C++]", "external compiler option [C++]"] |
| 7 | +--- |
| 8 | +# `/external` (External headers diagnostics) |
| 9 | + |
| 10 | +The **`/external`** compiler options let you specify compiler diagnostic behavior for certain header files. "External" headers are the natural complement of "Just my code": Header files such as system files or third-party library files that you can't or don't intend to change. Since you aren't going to change these files, you may decide it isn't useful to see diagnostic messages from the compiler about them. The `/external` compiler options give you control over these warnings. |
| 11 | + |
| 12 | +The **`/external`** compiler options are available starting in Visual Studio 2017 version 15.6. The **`/external`** options require you also set the **`/experimental:external`** compiler option. |
| 13 | + |
| 14 | +## Syntax |
| 15 | + |
| 16 | +Use external header options: |
| 17 | +> **`/experimental:external`** |
| 18 | +
|
| 19 | +Specify external headers: |
| 20 | +> **`/external:anglebrackets`**\ |
| 21 | +> **`/external:env:`**_`var`_\ |
| 22 | +> **`/external:I`** *`path`* |
| 23 | +
|
| 24 | +Specify diagnostics behavior: |
| 25 | +> **`/external:W`**_`n`_\ |
| 26 | +> **`/external:templates-`** |
| 27 | +
|
| 28 | +### Arguments |
| 29 | + |
| 30 | +**`/experimental:external`**\ |
| 31 | +Enables the external headers options, starting in Visual Studio 2017 version 15.6. |
| 32 | + |
| 33 | +**`/external:anglebrackets`**\ |
| 34 | +Treats all headers included by `#include <header>`, where the *`header`* file is enclosed in angle brackets (**`< >`**), as external headers. |
| 35 | + |
| 36 | +**`/external:I`** *`path`*\ |
| 37 | +Defines a root directory that contains external headers. All recursive subdirectories of *`path`* are considered external, but only the *`path`* value is added to the list of directories the compiler searches for include files. The space between **`/external:I`** and *`path`* is optional. Directories that include spaces must be enclosed in double quotes. A directory may be an absolute path or a relative path. |
| 38 | + |
| 39 | +**`/external:env:`**_`var`_\ |
| 40 | +Specifies the name of an environment variable *`var`* that holds a semicolon-separated list of external header directories. It's useful for build systems that rely on environment variables such as `INCLUDE`, which you use to specify the list of external include files. Or, `CAExcludePath`, for files that shouldn't be analyzed by `/analyze`. For example, you can specify `/external:env:INCLUDE` to make every directory in `INCLUDE` an external header directory at once. It's the same as using **`/external:I`** to specify the individual directories, but much less verbose. There should be no space between *`var`* and **`/external:env:`**. |
| 41 | + |
| 42 | +**`/external:Wn`**\ |
| 43 | +This option sets the default warning level to *`n`* (a value from 0 to 4) for external headers. For example, **`/external:W0`** effectively turns off warnings for external headers. The **`/external:Wn`** option has an effect similar to wrapping an included header in a `#pragma warning` directive: |
| 44 | + |
| 45 | +```cpp |
| 46 | +#pragma warning (push, 0) |
| 47 | +// the global warning level is now 0 here |
| 48 | +#include <external_header> |
| 49 | +#pragma warning (pop) |
| 50 | +``` |
| 51 | + |
| 52 | +**`/external:templates-`**\ |
| 53 | +Allows warnings from external headers when they occur in a template that's instantiated in your code. |
| 54 | + |
| 55 | +## Remarks |
| 56 | + |
| 57 | +By default, the **`/Wn`** warning level you specify for your build applies to all files. The options to specify external headers only define a set of files to which you can apply a different default warning level. So, if you specify external headers, also use **`/external:Wn`** to specify an external warning level to change compiler behavior. |
| 58 | + |
| 59 | +All the existing mechanisms to enable, disable, and suppress warnings still work in both external and non-external files. For example, a [`warning` pragma](../../preprocessor/warning.md) can still override the default warning level you set for external headers. |
| 60 | + |
| 61 | +### Example: Set external warning level |
| 62 | + |
| 63 | +This sample program has two source files, *`program.cpp`* and *`header_file.h`*. The *`header_file.h`* file is in an *`include_dir`* subdirectory of the directory containing the *`program.cpp`* file: |
| 64 | + |
| 65 | +```cpp |
| 66 | +// External header: include_dir/header_file.h |
| 67 | + |
| 68 | +template <typename T> |
| 69 | +struct sample_struct |
| 70 | +{ |
| 71 | + static const T value = -7; // W4: warning C4245: 'initializing': |
| 72 | + // conversion from 'int' to 'unsigned int', signed/unsigned mismatch |
| 73 | +}; |
| 74 | +``` |
| 75 | + |
| 76 | +```cpp |
| 77 | +// User code: program.cpp |
| 78 | +#include <header_file.h> |
| 79 | + |
| 80 | +int main() |
| 81 | +{ |
| 82 | + return sample_struct<unsigned int>().value; |
| 83 | +} |
| 84 | +``` |
| 85 | + |
| 86 | +You can build the sample by using this command line: |
| 87 | + |
| 88 | +```cmd |
| 89 | +cl /EHsc /I include_dir /W4 program.cpp |
| 90 | +``` |
| 91 | + |
| 92 | +As expected, this sample generates a warning: |
| 93 | + |
| 94 | +```console |
| 95 | +program.cpp |
| 96 | +include_dir\header_file.h(6): warning C4245: 'initializing': conversion from 'int' to 'const T', signed/unsigned mismatch |
| 97 | + with |
| 98 | + [ |
| 99 | + T=unsigned int |
| 100 | + ] |
| 101 | +program.cpp(6): note: see reference to class template instantiation 'sample_struct<unsigned int>' being compiled |
| 102 | +``` |
| 103 | + |
| 104 | +To treat the header file as an external file and suppress the warning, you can use this command line instead: |
| 105 | + |
| 106 | +```cmd |
| 107 | +cl /EHsc /experimental:external /I include_dir /external:anglebrackets /external:W0 /W4 program.cpp |
| 108 | +``` |
| 109 | + |
| 110 | +This command line suppresses the warning inside *`header_file.h`* while preserving warnings inside *`program.cpp`*. |
| 111 | + |
| 112 | +### Warnings across the internal and external boundary |
| 113 | + |
| 114 | +Setting a low warning level for external headers can hide some actionable warnings. In particular, it can turn off warnings emitted on template instantiations in user code. These warnings might indicate a problem in your code that only happens in instantiations for particular types. (For example, if you forgot to apply a type trait removing `const` or `&`.) To avoid silencing warnings inside templates defined in external headers, you can use the **`/external:templates-`** option. The compiler considers both the effective warning level in the file that defines the template, and the warning level where template instantiation occurs. Warnings emitted inside an external template appear if the template is instantiated within non-external code. For example, this command line re-enables warnings from template sources in the sample code: |
| 115 | + |
| 116 | +```cmd |
| 117 | +cl /EHsc /experimental:external /I include_dir /external:anglebrackets /external:W0 /external:templates- /W4 program.cpp |
| 118 | +``` |
| 119 | + |
| 120 | +The C4245 warning appears again in the output, even though the template code is inside an external header. |
| 121 | + |
| 122 | +### Enable, disable, or suppress warnings |
| 123 | + |
| 124 | +All the existing mechanisms to enable, disable, and suppress warnings still work in external headers. When a warning appears because you use the **`/external:templates-`** option, you can still suppress the warning at the point of instantiation. For example, to explicitly suppress the warning in the sample that reappears because of **`/external:templates-`**, use a `warning` pragma directive: |
| 125 | + |
| 126 | +```cpp |
| 127 | +int main() |
| 128 | +{ |
| 129 | + #pragma warning( suppress : 4245) |
| 130 | + return sample_struct<unsigned int>().value; |
| 131 | +} |
| 132 | +``` |
| 133 | + |
| 134 | +Library writers can use the same mechanisms to enforce certain warnings, or all the warnings at certain level, if they feel those warnings should never be silenced by **`/external:Wn`**. For example, this version of the header file forces warning C4245 to report an error: |
| 135 | + |
| 136 | +```cpp |
| 137 | +// External header: include_dir/header_file.h |
| 138 | + |
| 139 | +#pragma warning( push, 4 ) |
| 140 | +#pragma warning( error : 4245 ) |
| 141 | + |
| 142 | +template <typename T> |
| 143 | +struct sample_struct |
| 144 | +{ |
| 145 | + static const T value = -7; // W4: warning C4245: 'initializing': conversion from 'int' |
| 146 | + // to 'unsigned int', signed/unsigned mismatch |
| 147 | +}; |
| 148 | + |
| 149 | +#pragma warning( pop ) |
| 150 | +``` |
| 151 | + |
| 152 | +With this change to the library header, the author of the library ensures that the global warning level in this header is 4, no matter what gets specified in **`/external:Wn`**. Now all level 4 and above warnings are reported. The library author can also force certain warnings to be errors, disabled, suppressed, or emitted only once in the header. The **`/external`** options don't override that deliberate choice. |
| 153 | + |
| 154 | +`#pragma system_header` is an intrusive header marker that allows library writers to mark certain headers as external. These headers have the warning level specified by **`/external:Wn`**, if any. |
| 155 | + |
| 156 | +### Limitations |
| 157 | + |
| 158 | +Some warnings emitted by the compiler's back-end code generation aren't affected by the **`/external`** options. These warnings usually start with C47XX, though not all C47XX warnings are back-end warnings. You can still disable these warnings by using `/wd47XX`. Code analysis warnings are also unaffected, since they don't have warning levels. |
| 159 | + |
| 160 | +### To set this compiler option in the Visual Studio development environment |
| 161 | + |
| 162 | +1. Open the project's **Property Pages** dialog box. For details, see [Set C++ compiler and build properties in Visual Studio](../working-with-project-properties.md). |
| 163 | + |
| 164 | +1. Select the **Configuration Properties** > **C/C++** > **Command Line** property page. |
| 165 | + |
| 166 | +1. Enter the compiler options in the **Additional Options** box. |
| 167 | + |
| 168 | +### To set this compiler option programmatically |
| 169 | + |
| 170 | +- See <xref:Microsoft.VisualStudio.VCProjectEngine.VCCLCompilerTool.AdditionalOptions%2A>. |
| 171 | + |
| 172 | +## See also |
| 173 | + |
| 174 | +[MSVC compiler options](compiler-options.md)\ |
| 175 | +[MSVC compiler command-line syntax](compiler-command-line-syntax.md) |
0 commit comments