From c08bf939d0d9ee475f5553135ad4dbe3e5684f3b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 14 Oct 2021 08:26:22 +0200 Subject: Rearrange internal scope documentation, add note in target import --- doc/manual.cli | 296 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 149 insertions(+), 147 deletions(-) (limited to 'doc/manual.cli') diff --git a/doc/manual.cli b/doc/manual.cli index bc7a68e..d63e887 100644 --- a/doc/manual.cli +++ b/doc/manual.cli @@ -2580,6 +2580,13 @@ also try to locate its \c{pkg-config(1)} file and, if present, extract additional compile/link flags from it. The link rule also automatically produces \c{pkg-config(1)} files for libraries that it installs.| +\N|A common problem with importing and using third-party C/C++ libraries is +compiler warnings. Specifically, we are likely to include their headers into +our project's source files which means we may see warnings in such headers +(which we cannot always fix) mixed with warnings in our code (which we should +normally be able to fix). See \l{#cc-internal-scope Compilation Internal +Scope} for a mechanism to deal with this problem.| + Let's now examine the exporting side of the importation mechanism. While a project doesn't need to do anything special to be found by \c{import}, it does need to handle locating the exported target (or targets; there could be @@ -6491,6 +6498,148 @@ $ b config.cxx=\"g++ -m32\" $ b config.cxx=\"clang++ -stdlib=libc++\" \ +\h#cc-internal-scope|Compilation Internal Scope| + +\N|While this section uses the \c{cxx} module and C++ compilation as an +example, the same functionality is available for C compilation \- simply +replace \c{cxx} with \c{c} in the module and variable names.| + +The \c{cxx} module has a notion of a project's internal scope. During +compilation of a project's C/C++ translation units a header search path +(\c{-I}) exported by a library that is outside of the internal scope is +considered external and, if supported by the compiler, the corresponding +\c{-I} option is translated to an appropriate \"external header search path\" +option (\c{-isystem} for GCC/Clang, \c{/external:I} for MSVC 16.10 and +later). In particular, this suppresses compiler warnings in such external +headers (\c{/external:W0} is automatically added unless a custom +\c{/external:Wn} is specified). + +\N|While the aim of this functionality is to control warnings in external +libraries, the underlying mechanisms currently provided by compilers have +limitations and undesirable side effects. In particular, \c{-isystem} paths +are searched after \c{-I} so translating \c{-I} to \c{-isystem} alters the +search order. This should normally be harmless when using a development build +of a library but may result in a change of semantics for installed +libraries. Also, marking the search path as system has additional (to warning +suppression) effects, see +\l{https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html System Headers} in +the GCC documentation for details. On the MSVC side, \c{/external:W0} +currently does not suppress some warnings (refer to the MSVC documentation for +details). + +Another issue is warnings in template instantiations. Each such warning could +be either due to a (potential) issue in the template itself or due to the +template arguments we are instantiating it with. By default, all such warnings +are suppressed and there is currently no way to change this with GCC/Clang +\c{-isystem}. While MSVC provides \c{/external:templates-}, it cannot be +applied on the library by library basis, only globally for the entire +compilation. See MSVC \c{/external:templates-} documentation for more +background on this issue.| + +\N|In the future this functionality will be extended to side-building BMIs for +external module interfaces and header units.| + +The internal scope can be specified by the project with the +\c{cxx.internal.scope} variable and overridden by the user with the +\c{config.cxx.internal.scope} variable. Note that \c{cxx.internal.scope} must +be specified before loading the \c{cxx} module (\c{cxx.config}, more +precisely) and after which it contains the effective value (see below). For +example: + +\ +# root.build + +cxx.std = latest +cxx.internal.scope = current + +using cxx +\ + +Valid values for \c{cxx.internal.scope} are: + +\ +current -- current root scope (where variable is assigned) +base -- target's base scope +root -- target's root scope +bundle -- target's bundle amalgamation +strong -- target's strong amalgamation +weak -- target's weak amalgamation +global -- global scope (everything is internal) +\ + +Valid values for \c{config.cxx.internal.scope} are the same except for +\c{current}. + +Note also that there are \c{[config.]cc.internal.scope} variables that can be +used to specify the internal scope for all the \c{cc}-based modules. + +The project's effective internal scope is chosen based on the following +priority list: + +\ol| + +\li|\c{config.cxx.internal.scope}| + +\li|\c{config.cc.internal.scope}| + +\li|effective scope from bundle amalgamation| + +\li|\c{cxx.internal.scope}| + +\li|\c{cc.internal.scope}|| + +In particular, item #3 allows an amalgamation that bundles a project to +override its internal scope. + +\N|If no \c{*.internal.scope} is specified by the project, user, or bundle, +then this functionality is disabled and all libraries are treated as internal +regardless of their location. + +While it may seem natural to have this enabled by default, the limitations and +side effects of the underlying mechanisms as well as cases where it would be +undesirable (such as in separate \c{*-tests} projects, see below) all suggest +that explicit opt-in is probably the correct choice.| + +The recommended value for a typical project is \c{current}, meaning that only +headers inside the project will be considered internal. The \c{tests} +subproject, if present, will inherit its value from the project (which acts as +a bundle amalgamation), unless it is being built out of source (for example, +to test an installed library). + +A project can also whitelist specific libraries using the +\c{cxx.internal.libs} variable. If a library target name (that is, the name +inside \c{lib{\}}) matches any of the wildcard patterns listed in this +variable, then the library is considered internal regardless of its +location. For example (notice that the pattern is quoted): + +\ +# root.build + +cxx.std = latest +cxx.internal.scope = current +cxx.internal.libs = foo 'bar-*' + +using cxx +\ + +Note that this variable should also be set before loading the \c{cxx} module +and there is the common \c{cc.internal.libs} equivalent. However, there are +no \c{config.*} versions nor the override by the bundle amalgamation +semantics. + +Typically you would want to whitelist libraries that are developed together +but reside in separate build system projects. In particular, a separate +\c{*-tests} project for a library should whitelist the library being tested if +the internal scope functionality is in use. Another reason to whitelist is to +catch warnings in instantiations of templates that belong to a library that is +otherwise warning-free (see the MSVC \c{/external:templates-} option for +background). + +Note also that if multiple libraries are installed into the same location (or +otherwise share the same header search paths, for example, as a family of +libraries), then the whitelist may not be effective. + + \h#cc-gcc|GCC Compiler Toolchain| The GCC compiler id is \c{gcc}. @@ -6719,16 +6868,6 @@ config.c.internal.scope c.internal.scope \ -\h#c-internal-scope|C Compilation Internal Scope| - -The \c{c} module has a notion of a project's internal scope. During -compilation of a project's C translation units a header search path (\c{-I}) -exported by a library that is outside of the internal scope is considered -external and, if supported by the compiler, the corresponding \c{-I} option is -translated to an appropriate \"external header search path\" option. See -\l{#cxx-internal-scope C++ Compilation Internal Scope} for details on this -functionality. - \h1#module-cxx|\c{cxx} Module| @@ -6796,143 +6935,6 @@ config.cxx.translate_include cxx.translate_include \ -\h#cxx-internal-scope|C++ Compilation Internal Scope| - -The \c{cxx} module has a notion of a project's internal scope. During -compilation of a project's C++ translation units a header search path (\c{-I}) -exported by a library that is outside of the internal scope is considered -external and, if supported by the compiler, the corresponding \c{-I} option is -translated to an appropriate \"external header search path\" option -(\c{-isystem} for GCC/Clang, \c{/external:I} for MSVC 16.10 and later). In -particular, this suppresses compiler warnings in such external headers -(\c{/external:W0} is automatically added unless a custom \c{/external:Wn} is -specified). - -\N|While the aim of this functionality is to control warnings in external -libraries, the underlying mechanisms currently provided by compilers have -limitations and undesirable side effects. In particular, \c{-isystem} paths -are searched after \c{-I} so translating \c{-I} to \c{-isystem} alters the -search order. This should normally be harmless when using a development build -of a library but may result in a change of semantics for installed -libraries. Also, marking the search path as system has additional (to warning -suppression) effects, see -\l{https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html System Headers} in -the GCC documentation for details. On the MSVC side, \c{/external:W0} -currently does not suppress some warnings (refer to the MSVC documentation for -details). - -Another issue is warnings in template instantiations. Each such warning could -be either due to a (potential) issue in the template itself or due to the -template arguments we are instantiating it with. By default, all such warnings -are suppressed and there is currently no way to change this with GCC/Clang -\c{-isystem}. While MSVC provides \c{/external:templates-}, it cannot be -applied on the library by library basis, only globally for the entire -compilation. See MSVC \c{/external:templates-} documentation for more -background on this issue.| - -\N|In the future this functionality will be extended to side-building BMIs for -external module interfaces and header units.| - -The internal scope can be specified by the project with the -\c{cxx.internal.scope} variable and overridden by the user with the -\c{config.cxx.internal.scope} variable. Note that \c{cxx.internal.scope} must -be specified before loading the \c{cxx} module (\c{cxx.config}, more -precisely) and after which it contains the effective value (see below). For -example: - -\ -# root.build - -cxx.std = latest -cxx.internal.scope = current - -using cxx -\ - -Valid values for \c{cxx.internal.scope} are: - -\ -current -- current root scope (where variable is assigned) -base -- target's base scope -root -- target's root scope -bundle -- target's bundle amalgamation -strong -- target's strong amalgamation -weak -- target's weak amalgamation -global -- global scope (everything is internal) -\ - -Valid values for \c{config.cxx.internal.scope} are the same except for -\c{current}. - -Note also that there are \c{[config.]cc.internal.scope} variables that can be -used to specify the internal scope for all the \c{cc}-based modules. - -The project's effective internal scope is chosen based on the following -priority list: - -\ol| - -\li|\c{config.cxx.internal.scope}| - -\li|\c{config.cc.internal.scope}| - -\li|effective scope from bundle amalgamation| - -\li|\c{cxx.internal.scope}| - -\li|\c{cc.internal.scope}|| - -In particular, item #3 allows an amalgamation that bundles a project to -override its internal scope. - -\N|If no \c{*.internal.scope} is specified by the project, user, or bundle, -then this functionality is disabled and all libraries are treated as internal -regardless of their location. - -While it may seem natural to have this enabled by default, the limitations and -side effects of the underlying mechanisms as well as cases where it would be -undesirable (such as in separate \c{*-tests} projects, see below) all suggest -that explicit opt-in is probably the correct choice.| - -The recommended value for a typical project is \c{current}, meaning that only -headers inside the project will be considered internal. The \c{tests} -subproject, if present, will inherit its value from the project (which acts as -a bundle amalgamation), unless it is being built out of source (for example, -to test an installed library). - -A project can also whitelist specific libraries using the -\c{cxx.internal.libs} variable. If a library target name (that is, the name -inside \c{lib{\}}) matches any of the wildcard patterns listed in this -variable, then the library is considered internal regardless of its -location. For example (notice that the pattern is quoted): - -\ -# root.build - -cxx.std = latest -cxx.internal.scope = current -cxx.internal.libs = foo 'bar-*' - -using cxx -\ - -Note that this variable should also be set before loading the \c{cxx} module -and there is the common \c{cc.internal.libs} equivalent. However, there are -no \c{config.*} versions nor the override by the bundle amalgamation -semantics. - -Typically you would want to whitelist libraries that are developed together -but reside in separate build system projects. In particular, a separate -\c{*-tests} project for a library should whitelist the library being tested if -the internal scope functionality is in use. Another reason to whitelist is to -catch warnings in instantiations of templates that belong to a library that is -otherwise warning-free (see the MSVC \c{/external:templates-} option for -background). - -Note also that if multiple libraries are installed into the same location (or -otherwise share the same header search paths, for example, as a family of -libraries), then the whitelist may not be effective. - \h#cxx-modules|C++ Modules Support| -- cgit v1.1