Document #: |
ISO/IEC/JTC1/SC22/WG21/P3335R3 |
Date: |
2024-11-21 |
Audience: |
SG15 |
Authors: |
René Ferdinand Rivera Morell |
Reply-to: | |
Copyright: |
Copyright 2024 René Ferdinand Rivera Morell, Creative Commons Attribution 4.0 International License (CC BY 4.0) |
I: Proposal
1. Abstract
Specify a minimal set of core structured options [1] for C++ compiler front ends.
2. Revision History
2.1. Revision 3 (November 2024)
Removed std.
prefixes from keys. Changed null
define value equate to 1
.
Made define value optional with a value of 1
.
3. Motivation
Tools in the C++ ecosystem have dealt with using a myriad of different options to invoke C++ compiler front ends for decades. Although we have found ways to manage the variety it is advantageous to agree on a common language to reduce the growing complexities that the variety creates.
Having a standard common set of structured options allows for:
-
Reuse of implementation by tools that interface with compiler front ends.
-
Wider adoption of tools that use, as consumers or producers, the common options.
-
Lowers the barriers for unexperienced users as they have less to learn.
-
Can be a basis for other standards to form a common configuration vocabulary.
4. Scope
This proposal aims to specify a set of C++ compiler frontend structured options [1] sufficient to build common C++ use cases. This includes specifying both the names and semantics of the structured options.
This does not aim to standardize compiler frontend command line arguments. Although vendors are free to adopt the names and semantics specified if they wish. And we encourage such adoption.
5. Design
The approach for the names and semantics of the options follows these goals:
-
Prefer widely used terms in current tools, not just C++ compiler front ends.
-
Use widely understood semantics.
-
Improve the structure of the data.
5.1. File References
In various places the options need to refer to file names and paths. And in
some of those instances it’s also possible to want to specify one or more
attributes to the file. For example when indicating the language for a source
file. We looked at various ways to achieve an arrangement to make that
specification both optional and future proof. After discussions a simple JSON
object with one required name
key and string value for the path was chosen:
{
"name": "file.ext"
}
Other fields are possible depending in the context of the file reference. For
example to specify the language
of a source file:
{
"name": "main.cpp",
"language": "c++"
}
ℹ
|
Previously we had proposed using a multi-stage scheme to simplify the human editing of file references that allowed: a single string, an object with string, or an object with objects. Discussions pointed out difficulties in such dynamic parsing of values by some JSON parsers. |
5.2. Lists
All lists are strictly JSON array
values.
ℹ
|
Previously we had proposed using a multi-stage scheme to simplify the human editing of lists that allowed lists with a single value to be abbreviated by the single value. Discussions pointed out difficulties in such dynamic parsing of values by some JSON parsers. |
5.3. Examples
Below are some examples that show a traditional command line invocation and the corresponding structured options specification. The examples are meant to be informational only to illustrate how the structured options could work. As such they may include options that are not proposed in this document. The example command line invocations may also contain some options that are not present in the structured options. I.e. they are not meant to be a one-to-one correspondence. Generally the examples where generated by running a real build system and collecting the command lines it invokes.
5.3.1. Hello World
This is the classic simplest C++ program with the twist that we want to allow full debugging when running it.
"g++" -O0 -fno-inline -Wall -g -static "hello.cpp" -o "hello"
"cl" "hello.cpp" /Fehello -TP /EHs /GR /Z7 /Od /Ob0 /W3 /Op /MLd /DEBUG
/subsystem:console
Those invocations can be represented as a somewhat more meaningful structured
options. This specification is formulated to be a single cross-vendor object
by using a vendor
specific section to represent options that only msvc
understands. And that other tools could ignore.
{
"source": [{ "name": "hello.cpp" }],
"output": [
{
"name": "hello",
"kind": "exec"
}
],
"optimization": {
"compile": "off",
"inline": false
},
"warnings": {
"enable": "all"
},
"runtime": {
"multithread": false,
"debug": true,
"static": true
},
"vendor": {
"msvc": {
"subsystem": "console"
}
}
}
5.3.2. Compile And Link
A single invocation that does everything is not particularly common, except as basic textbook examples. Here we see the more common case of compiling to produce an object file for the TU. Then linking to get the final executable.
"g++" --fPIC -O0 -fno-inline -Wall -g -c -o "hello.o" "hello.cpp"
"g++" -g "hello.o" -o "hello"
The compile only equivalent structured options:
{
"source": [{ "name": "hello.cpp" }],
"output": [{ "name": "hello.o", "kind": "object" }],
"optimization": {
"compile": "off",
"inline": false
},
"warnings": {
"enable": "all"
},
"runtime": {
"multithread": false,
"debug": true,
"static": true
}
}
Followed by the structured options to accomplish the link:
{
"source": [{ "name": "hello.o" }],
"output": [
{
"name": "hello",
"kind": "exec"
}
]
}
5.3.3. Many Sources
This is a single command B2 uses to bootstrap its engine on Linux with GCC, and Windows with MSVC. This is a variation on a simple basic invocation that builds many files with some extra options.
g++ -x c++ -std=c++11 -pthread -O2 -s -DNDEBUG bindjam.cpp builtins.cpp
class.cpp command.cpp compile.cpp constants.cpp cwd.cpp debug.cpp
debugger.cpp events.cpp execcmd.cpp execnt.cpp execunix.cpp filent.cpp
filesys.cpp fileunix.cpp frames.cpp function.cpp glob.cpp hash.cpp
hcache.cpp hdrmacro.cpp headers.cpp jam_strings.cpp jam.cpp jamgram.cpp
lists.cpp make.cpp make1.cpp md5.cpp mem.cpp modules.cpp native.cpp
option.cpp output.cpp parse.cpp pathnt.cpp pathsys.cpp pathunix.cpp
regexp.cpp rules.cpp scan.cpp search.cpp startup.cpp tasks.cpp
timestamp.cpp value.cpp variable.cpp w32_getreg.cpp mod_command_db.cpp
mod_db.cpp mod_jam_builtin.cpp mod_jam_class.cpp mod_jam_errors.cpp
mod_jam_modules.cpp mod_order.cpp mod_path.cpp mod_property_set.cpp
mod_regex.cpp mod_sequence.cpp mod_set.cpp mod_string.cpp mod_summary.cpp
mod_sysinfo.cpp mod_version.cpp -o b2
Other than many more files this example doesn’t differ much from the Hello World example.
{
"source": [
{ "name": "bindjam.cpp" },
{ "name": "builtins.cpp" },
{ "name": "class.cpp" },
{ "name": "command.cpp" },
{ "name": "compile.cpp" },
{ "name": "constants.cpp" },
{ "name": "cwd.cpp" },
{ "name": "debug.cpp" },
{ "name": "debugger.cpp" },
{ "name": "events.cpp" },
{ "name": "execcmd.cpp" },
{ "name": "execnt.cpp" },
{ "name": "execunix.cpp" },
{ "name": "filent.cpp" },
{ "name": "filesys.cpp" },
{ "name": "fileunix.cpp" },
{ "name": "frames.cpp" },
{ "name": "function.cpp" },
{ "name": "glob.cpp" },
{ "name": "hash.cpp" },
{ "name": "hcache.cpp" },
{ "name": "hdrmacro.cpp" },
{ "name": "headers.cpp" },
{ "name": "jam_strings.cpp" },
{ "name": "jam.cpp" },
{ "name": "jamgram.cpp" },
{ "name": "lists.cpp" },
{ "name": "make.cpp" },
{ "name": "make1.cpp" },
{ "name": "md5.cpp" },
{ "name": "mem.cpp" },
{ "name": "modules.cpp" },
{ "name": "native.cpp" },
{ "name": "option.cpp" },
{ "name": "output.cpp" },
{ "name": "parse.cpp" },
{ "name": "pathnt.cpp" },
{ "name": "pathsys.cpp" },
{ "name": "pathunix.cpp" },
{ "name": "regexp.cpp" },
{ "name": "rules.cpp" },
{ "name": "scan.cpp" },
{ "name": "search.cpp" },
{ "name": "startup.cpp" },
{ "name": "tasks.cpp" },
{ "name": "timestamp.cpp" },
{ "name": "value.cpp" },
{ "name": "variable.cpp" },
{ "name": "w32_getreg.cpp" },
{ "name": "mod_command_db.cpp" },
{ "name": "mod_db.cpp" },
{ "name": "mod_jam_builtin.cpp" },
{ "name": "mod_jam_class.cpp" },
{ "name": "mod_jam_errors.cpp" },
{ "name": "mod_jam_modules.cpp" },
{ "name": "mod_order.cpp" },
{ "name": "mod_path.cpp" },
{ "name": "mod_property_set.cpp" },
{ "name": "mod_regex.cpp" },
{ "name": "mod_sequence.cpp" },
{ "name": "mod_set.cpp" },
{ "name": "mod_string.cpp" },
{ "name": "mod_summary.cpp" },
{ "name": "mod_sysinfo.cpp" },
{ "name": "mod_version.cpp" }
],
"output": [{ "name": "b2", "kind": "exec" }],
"define": [{ "name": "NDEBUG" }],
"language": {
"name": "c++",
"standard": "11"
},
"optimization": {
"compile": "minimal",
"link": true,
"msvc.global_data": true
},
"runtime": {
"multithread": true,
"debug": false,
"static": true
}
}
"cl" /nologo /MP /MT /TP /Feb2 /wd4996 /wd4675 /O2 /GL /EHsc /Zc:wchar_t /Gw
-DNDEBUG bindjam.cpp builtins.cpp class.cpp command.cpp compile.cpp
constants.cpp cwd.cpp debug.cpp debugger.cpp events.cpp execcmd.cpp
execnt.cpp execunix.cpp filent.cpp filesys.cpp fileunix.cpp frames.cpp
function.cpp glob.cpp hash.cpp hcache.cpp hdrmacro.cpp headers.cpp jam.cpp
jamgram.cpp lists.cpp make.cpp make1.cpp md5.cpp mem.cpp modules.cpp
native.cpp option.cpp output.cpp parse.cpp pathnt.cpp pathsys.cpp
pathunix.cpp regexp.cpp rules.cpp scan.cpp search.cpp jam_strings.cpp
startup.cpp tasks.cpp timestamp.cpp value.cpp variable.cpp w32_getreg.cpp
mod_command_db.cpp mod_db.cpp mod_jam_builtin.cpp mod_jam_class.cpp
mod_jam_errors.cpp mod_jam_modules.cpp mod_order.cpp mod_path.cpp
mod_property_set.cpp mod_regex.cpp mod_sequence.cpp mod_set.cpp
mod_string.cpp mod_summary.cpp mod_sysinfo.cpp mod_version.cpp
/link kernel32.lib advapi32.lib user32.lib
/MANIFEST:EMBED /MANIFESTINPUT:b2.exe.manifest
The msvc
equivalent has the addition of listing some system libraries and
the special Windows embedded manifest for the executable.
{
"source": [
{ "name": "bindjam.cpp" },
{ "name": "builtins.cpp" },
{ "name": "class.cpp" },
{ "name": "command.cpp" },
{ "name": "compile.cpp" },
{ "name": "constants.cpp" },
{ "name": "cwd.cpp" },
{ "name": "debug.cpp" },
{ "name": "debugger.cpp" },
{ "name": "events.cpp" },
{ "name": "execcmd.cpp" },
{ "name": "execnt.cpp" },
{ "name": "execunix.cpp" },
{ "name": "filent.cpp" },
{ "name": "filesys.cpp" },
{ "name": "fileunix.cpp" },
{ "name": "frames.cpp" },
{ "name": "function.cpp" },
{ "name": "glob.cpp" },
{ "name": "hash.cpp" },
{ "name": "hcache.cpp" },
{ "name": "hdrmacro.cpp" },
{ "name": "headers.cpp" },
{ "name": "jam_strings.cpp" },
{ "name": "jam.cpp" },
{ "name": "jamgram.cpp" },
{ "name": "lists.cpp" },
{ "name": "make.cpp" },
{ "name": "make1.cpp" },
{ "name": "md5.cpp" },
{ "name": "mem.cpp" },
{ "name": "modules.cpp" },
{ "name": "native.cpp" },
{ "name": "option.cpp" },
{ "name": "output.cpp" },
{ "name": "parse.cpp" },
{ "name": "pathnt.cpp" },
{ "name": "pathsys.cpp" },
{ "name": "pathunix.cpp" },
{ "name": "regexp.cpp" },
{ "name": "rules.cpp" },
{ "name": "scan.cpp" },
{ "name": "search.cpp" },
{ "name": "startup.cpp" },
{ "name": "tasks.cpp" },
{ "name": "timestamp.cpp" },
{ "name": "value.cpp" },
{ "name": "variable.cpp" },
{ "name": "w32_getreg.cpp" },
{ "name": "mod_command_db.cpp" },
{ "name": "mod_db.cpp" },
{ "name": "mod_jam_builtin.cpp" },
{ "name": "mod_jam_class.cpp" },
{ "name": "mod_jam_errors.cpp" },
{ "name": "mod_jam_modules.cpp" },
{ "name": "mod_order.cpp" },
{ "name": "mod_path.cpp" },
{ "name": "mod_property_set.cpp" },
{ "name": "mod_regex.cpp" },
{ "name": "mod_sequence.cpp" },
{ "name": "mod_set.cpp" },
{ "name": "mod_string.cpp" },
{ "name": "mod_summary.cpp" },
{ "name": "mod_sysinfo.cpp" },
{ "name": "mod_version.cpp" },
{ "name": "kernel32.lib" },
{ "name": "advapi32.lib" },
{ "name": "user32.lib" }
],
"output": [{ "name": "b2", "kind": "exec" }],
"define": [{ "name": "NDEBUG", "value": null }],
"language": { "name": "c++", "standard": "11" },
"optimization": {
"compile": "minimal",
"link": true,
"msvc.global_data": true
},
"runtime": {
"multithread": true,
"debug": false,
"static": true
},
"vendor": {
"msvc": {
"manifest": {
"source": "b2.exe.manifest",
"embed": true
}
}
}
}
5.4. Options
ℹ
|
In the tables below compiler drivers or front ends we list the un-prefixed option name. And for build systems we list any abstraction for the option. But importantly, we don’t list if the build system only allows for specifying the raw option. As it doesn’t add any more information than what is given for the compiler driver information. |
The options specified below show first how the concept is specified in two kinds of tools, compiler driver/front-ends and build systems. This is a small, but hopefully representative, sampling of syntax and semantics. The tools considered are: MSVC, [2] GCC, [3] CMake, [4] B2 [5]
And subsequently show the chosen key, value, and semantics of the option. The schema for the value is explained in the value if it’s brief. But otherwise defined in the semantics of each. As mentioned previously there can be multiple value types for an option. Each of those is outlined to the extent that the specific option allows (currently). The explanations of the options are not exhaustively precise. That is left for future wording.
5.4.1. Source
Tool | Name | Semantics |
---|---|---|
MSVC |
|
A file specified as a regular argument is added as a source to process. |
GCC |
|
A file specified as a regular argument is added as a source to process. |
CMake |
|
A file specified as an argument to a target is added as a source to process. |
B2 |
|
A file specified as an argument to a target is added as a source to process. |
- Key
-
Use
source
. - Value
-
An
array
of Source Object values. - Semantics
-
Adds the sources given to the set of files to process.
- Merge Semantics
-
The sources in this specification are appended to any existing sources.
5.4.1.1. Source Object
A source is specified as an object
it consist of at minimum a name
field
specifying the file name of the source. Other fields are optional. And, if
possible, the tool can inspect the source (or name) to determine values for
unspecified fields.
Examples
{
"source": [{ "name": "main.cpp", "language": { "name": "c++" } }]
}
{
"source": [
{ "name": "main.cpp" },
{ "name": "utils.cpp" },
{ "name": "algo.cpp" },
{ "name": "api.i", "language": { "name": "c" } }
]
}
5.4.2. Output
Tool | Name | Semantics |
---|---|---|
MSVC |
|
Set the name of the generated output. The option specifies the kind of
output generated as: |
GCC |
|
Sets the file to output with ( |
CMake |
|
Defines a target for an executable or library. |
B2 |
|
Defines a target of the given type: |
- Key
-
Use
output
. - Value
-
An
array
of Output Object values. - Semantics
-
Specifies the output file, or files, to generate when processing the sources.
- Merge Semantics
-
The outputs in this specification are appended to any existing outputs.
5.4.2.1. Output Object
A single output specifies an object
consisting at minimum of the name
and
kind
fields. Other fields are optional. And, if possible, the tool can infer
the other fields as needed.
name
-
The required file name of the output.
kind
-
The kind of output. The kind of output also indicates the type of operation the tool will do. Possible kinds of outputs:
exec
-
Links the compiled sources into an executable file.
object
-
Compiles the sources into a linkable object file.
dynamic_lib
-
Links the compiled sources into a dynamically loadable library.
archive_lib
-
Collects the compiled sources into an archive library of object files.
Examples
{
"output": [{ "name": "a.out", "kind": "exec" }]
}
5.4.3. Include Directories
Tool | Name | Semantics |
---|---|---|
MSVC |
|
Adds the directory to the include search list. |
GCC |
|
Adds the directory to the include search list. |
CMake |
|
Adds the directories to the include search list. |
B2 |
|
Adds the directory, order unspecified, to the include search list. |
- Key
-
Use
include_dirs
. - Value
-
An
array
ofstring
-s. Eachstring
is a pathname of which interpretation is up to the application. - Semantics
-
Adds the listed pathnames to the end of the include directories of the application. It is up to the application to interpret how the composed list of directories is used. But it commonly interpreted as
#include
preprocessor directives to look for files in the order of the include directories list. - Merge Semantics
-
The directories in this specification are appended to any existing directories.
Examples
{
"include_dirs": ["/opt/boost_config/include", "/opt/openssl/include"]
}
5.4.4. Library Directories
Tool | Name | Semantics |
---|---|---|
MSVC |
|
Adds to the list of directories to search for link libs. The |
GCC |
|
|
CMake |
|
Adds to the list of directories which will be used by the linker to search
for libraries. Specifying |
B2 |
|
Adds to the list of directories which will be used by the linker to search for libraries. |
- Key
-
Use
library_dirs
. - Value
-
An
array
ofstring
-s. Eachstring
is a pathname of which interpretation is up to the application. - Semantics
-
Adds the listed pathnames to the end of the library search directories of the application. It is up to the application to interpret how the composed list of directories is used.
- Merge Semantics
-
The directories in this specification are appended to any existing directories.
Examples
{
"library_dirs": ["/opt/boost_config/lib", "/opt/openssl/lib"]
}
5.4.5. Define Preprocessor Symbols
Tool | Name | Semantics |
---|---|---|
MSVC |
|
Defines a preprocessor symbol to a value overriding any previous definition.
If no value is given |
GCC |
|
Defines a preprocessor symbol to a value overriding any previous definition.
If no value is given |
CMake |
|
Defines a preprocessor symbol to a value overriding any previous definition. If no value is given no value is used and the value is up to the compiler. |
B2 |
|
Defines a preprocessor symbol to a value overriding any previous definition. If no value is given no value is used and the value is up to the compiler. |
- Key
-
Use
define
. - Value
-
An
array
of Preprocessor Symbol values. - Semantics
-
For each symbol a language preprocessor will define the symbol to the value.
- Merge Semantics
-
The definitions in this specification either: add to existing set of definitions when the symbol doesn’t exist, or replace the definitions when the symbol already exists.
5.4.5.1. Preprocessor Symbol
A preprocessor symbol specifies a name
and an optional value
. The value
defined by the preprocessor is converted as follows based on the type of JSON
value given:
-
JSON
number
is converted to a string and pasted. -
JSON
string
is used directly. -
JSON
boolean
is converted astrue
⇒1
andfalse
⇒0
. -
JSON
null
is converted to1
. -
No value is converted to
1
.
Examples
{
"define": [
{ "name": "BOOST_ALL_NO_LIB", "value": 1 },
{ "name": "_WIN32_WINNT", "value": "0x0600" },
{ "name": "_GNU_SOURCE", "value": true },
{ "name": "U_USING_ICU_NAMESPACE", "value": false },
{ "name": "NOMINMAX", "value": null },
{ "name": "NDEBUG" }
]
}
5.4.6. Undefine Preprocessor Symbols
Tool | Name | Semantics |
---|---|---|
MSVC |
|
Undefines the given preprocessor symbol. |
GCC |
|
Undefines the given preprocessor symbol. |
CMake |
N/A |
|
B2 |
|
Undefines the given preprocessor symbol. |
- Key
-
Use
undef
. - Value
-
The option would be either a single
string
or anarray
ofstring
-s. Eachstring
is a symbol to undefine. - Semantics
-
For each
string
in the value "undefines" the preprocessor symbol. The option is evaluated after thedefine
option. - Merge Semantics
-
The undefs in this specification either: add to existing set of undefs when the symbol doesn’t exist, or replace the undefs when the symbol already exists.
{
"undef": ["NDEBUG"]
}
5.4.7. Language
Tool | Name | Semantics |
---|---|---|
MSVC |
|
Specified a source file is a C ( |
GCC |
|
Specified source files are the given language. Otherwise the file extension is used. |
CMake |
|
Specified source files are the given language. Otherwise the file extension is used. |
B2 |
|
Specified source files are the given language. Otherwise the file extension is used. |
- Key
-
Use
language
. - Value
-
The option value is a single
string
indicating the name of a language. The set of values is open. But at minimumc++
andc
must be recognized. Other values could be:assembly
,objective-c
,objective-c++
,fortran
,go
,d
,ada
. - Semantics
-
The given language sets the one to use for sources that do not otherwise specify one. The tool should indicate an error for languages it doesn’t recognize.
{
"language": { "name": "c++" }
}
- Merge Semantics
-
The language in this specification replaces an existing language specification.
5.4.8. Optimization
Tool | Name | Semantics |
---|---|---|
MSVC |
|
Disables ( |
GCC |
|
Disables ( |
CMake |
|
Generates build description that may enable optimizations. |
B2 |
|
Disables ( |
- Key
-
Use
optimization
. - Value
- Semantics
-
The level of optimization is applied to all the sources being processed.
- Merge Semantics
-
The fields in the
object
value replace existing optimization fields. For a singlestring
value the equivalentobject
for that value is merged.
Examples
{
"optimization": { "compile": "minimal" }
}
5.4.8.1. Optimization Object
An optimization object can have the following fields:
If the value is an object
it can have the following fields, and semantics:
compile
-
The set of values for
compile
is fixed, but tools are free to ignore or use equivalent for the various values. Which optimizations the tool performs for each value is up to the tool. The only required semantic is foroff
that must disable all optimizations. Possible values:-
off
- Disable optimizations. -
minimal
- Optimizations that may improve speed and space. -
speed
- Prefer speed over space optimizations. -
space
- Prefer smaller binaries over speed optimizations. -
debug
- Optimize such that debugging capabilities are preserved.
-
link
-
A
boolean
value that whentrue
enables link time (whole program) optimizations. Whenfalse
, or not present, disables link time optimizations.
5.4.9. Vendor
We recognize that std
options will never be sufficient, or practical, to
delineate all possible functionality. To accommodate the flexibility needed
over time to support all build capabilities we need to allow for tools to
define their own options outside of the standard. While it is possible for tools
to use scoped keys to specify their own options, that method may be harder to
manage for some environments. To allow for easier destructuring we introduce
a vendor
option.
- Key
-
Use
vendor
. - Value
-
The option contains a single
object
with tool defined keys and values. The names of the keys, or the type of the values, or the semantics are not specified here. And it is up to the tool creators to coordinate on unique keys. - Semantics
-
The value in the vendor specific fields is interpreted per the tool requirements. Any number of vendor keys+values is allowed. Tools are not restricted in what they support. Either of their own keys+values. Or the Keys+values of other vendor tools. This allows from some level of interchange for tools that need to support some understanding of what other tools specify. For example static analyzers that often need to digest sources across different vendors.
- Merge Semantics
-
The semantics are up to the vendor to specify for the individual options they define. Above that, if a vendor key in this specification is not present in the existing specification it is added. Otherwise, for a key in the vendor
object
in this specification is not present in the existing specification it is added.
Examples
{
"optimization": {
"compile": "debug",
"link": true,
"vendor": {
"msvc": {
"global_data": true
}
}
},
"vendor": {
"msvc": {
"manifest": {
"source": "b2.exe.manifest",
"embed": true
},
"subsystem": "console"
}
}
}
6. Polls
6.1. SG15: P3335R2 (2024-11-21)
Modify P3335R2 such that a defines value of null is 1 instead of impl defined, a define lacking a value is 1, and remove the std. prefix and then forward to EWG for inclusion in the initial Ecosystem IS. Also modify P3342 (the Ecosystem IS draft) to include the wording in P3335R2 as modified above.
SF | F | N | A | SA |
---|---|---|---|---|
7 |
0 |
1 |
0 |
0 |
II: Wording
Wording is relative to P3342R0 Working Draft, Standard for C++ Ecosystem. [6]
An important goal in the wording below is to minimize how much application behavior is mandated. As specifying more than absolutely needed can impede current and future behavior of applications.
7. Edit 1
Replace 7 Structured Parameters Core Options [strctparamopt] with [strctopt.core] below.
7.1. Structured Core Options [strctopt.core]
7.1.1. Preamble [strctopt.core.pre]
This clause describes the schema and semantics of core structured options ([strctopt.schema.struct]) for C++ compiler front-end applications.
This clause specifies the std.strctopt.core
capability
([intspct.cap]) version 1.0.0
.
An application can implement this capability.
An application that implements the std.strctopt.core
capability shall include
the std.strctopt.core
field and version value in the introspection JSON
text output ([intspct.schema.cap]).
7.1.2. Source [strctopt.core.src]
Name: source
Type: array
Value: The value shall be a JSON array
. The items in the array
shall be of JSON object
items specifying source objects
([strctopt.core.srcobj]).
Description:
Defines a list of source files for an application to process.
The application shall add the given sources to the set of files to process.
The sources given shall be appended to existing sources in the order given.
7.1.2.1. Source Object [strctopt.core.srcobj]
A source object shall have a name
field.
Name: name
Type: string
Value: A pathname to a file.
Description: The pathname of the source file.
A source object can have a language field ([strctopt.core.lang]).
Specifying a language field for a source shall replace any other determination of the source language by the application.
Specifying a language field for a source shall replace a language field specified in the structured parameters options field ([strctparam.schema.opts]).
A source object can have a kind field ([strctopt.core.kind]).
Specifying a kind field for a source shall replace any other determination of the source kind by the application.
Specifying a kind field for a source shall replace a kind field specified in the structured parameters options field ([strctparam.schema.opts]).
A source object can have a vendor field ([strctopt.core.vendor]).
7.1.3. Output [strctopt.core.out]
Name: output
Type: array
Value: The value shall be a JSON array
. The items in the array
shall be JSON object
items specifying output objects
([strctopt.core.outobj]).
Description:
Specifies the output files to generated when processing sources
([strctopt.core.src]).
7.1.3.1. Output Object [strctopt.core.outobj]
An output object shall have a name
field.
Name: name
Type: string
Value: A pathname to a file.
Description: The name of the output file.
An output object can have a kind field ([strctopt.core.kind]).
Specifying a kind field for output shall replace any other determination of the output kind by the application.
An output object can have a vendor field ([strctopt.core.vendor]).
7.1.4. Include Directories [strctopt.core.incd]
Name: include_dirs
Type: array
Value: The value shall be a JSON array
. The items in the array
shall be JSON string
items of pathnames to directories.
Description:
One or more entries to directories that are searched by the header inclusion
of a C++ preprocessor.
The application shall add the given directories to the set of directories searched by the header inclusion of a C++ preprocessor.
The directories given shall be appended to the existing include search directories in the order given.
7.1.5. Library Directories [strctopt.core.libd]
Name: library_dirs
Type: array
Value: The value shall be a JSON array
. The items in the array
shall be JSON string
items of pathnames to directories.
Description:
One or more entries to directories that are searched for libraries.
The application shall add the given directories to the set of directories searched for libraries.
The directories given shall be appended to the existing library search directories in the order given.
7.1.6. Define Preprocessor Symbols [strctopt.core.def]
Name: define
Type: array
Value: The value shall be a JSON array
. The items in the array
shall be JSON object
items specifying preprocessor symbol definition
objects ([strctopt.core.def.sym]).
Description:
Specifies preprocessor symbols to define during processing of sources.
7.1.6.1. Preprocessor Symbol Definition Object [strctopt.core.def.sym]
Name: name
Type: string
Value: A valid preprocessor symbol.
Description:
The field specifies the preprocessor symbol to define.
The symbol shall be valid for the consuming application.
The application shall indicate an error for invalid symbols.
Name: value
Type: number
, string
, boolean
, or null
Value: A valid preprocessor define value.
Description:
The field specifies the value to assign to the preprocessor symbol.
The value shall be valid for the consuming application.
The value can be omitted. When the value is omitted it shall be converted to a
string value of 1
.
A number
value shall be converted to a string value.
A string
value shall be used as given.
A true
value shall be converted to a string value of 1
.
A false
value shall be converted to a string value of 0
.
A null
value shall be converted to a string value of 1
.
7.1.7. Undefine Preprocessor Symbols [strctopt.core.undef]
Name: undef
Type: array
Value: The value shall be a JSON array
. The items in the array
shall be of JSON string
defining preprocessor symbol names.
Description: Specifies preprocessor symbols to "undefine".
The symbols shall be valid for the consuming application.
The application shall indicate an error for invalid symbols.
The application shall evaluate this option after any define
([strctopt.core.def]) options.
7.1.8. Optimization [strctopt.core.opt]
Name: optimization
Type: string
Value: An optimization object item ([strctopt.core.optobj])
Description: The optimization to apply when generating the output.
The application shall replace each existing field in the optimization object ([strctopt.core.optobj]).
7.1.8.1. Optimization Object [strctopt.core.optobj]
An optimization object can have any of compile
and link
fields.
Name: compile
Type: string
Value: off
, minimal
, speed
, space
, or debug
Description:
The amount or type of optimization to apply to the generated output.
An application shall not perform optimization when given the off
value.
For minimal
, speed
, space
, and debug
values the application behavior is
unspecified.
Name: link
Type: boolean
Value: true
or false
Description:
Specify if optimizations that happen for linked output generation happen.
An application shall not perform optimizations for linked output generation
when the value is false
.
For a true
value the application behavior is unspecified.
An optimization object can have a vendor field ([strctopt.core.vendor]).
7.1.9. Vendor [strctopt.core.vendor]
Name: vendor
Type: object
Value: A vendor object ([strctopt.core.vendorobj])
Description:
Specifies vendor defined options to apply in the context they appear.
An application shall apply the vendor option semantics in the context they appear.
7.1.9.1. Vendor Object [strctopt.core.vendorobj]
A vendor object can have any number of fields.
The name of a field is unspecified.
The value of a field is unspecified.
ℹ
|
It is up to application vendors to agree on the name fields. |
ℹ
|
It is up to application vendors to document the schema of the field values. |
7.1.10. Language [strctopt.core.lang]
Name: language
Type: object
Value: A language object [strctop.core.langobj]
Description: The language to interpret the source as.
7.1.10.1. Language Object [strctopt.core.langobj]
A language object shall have a name
field.
Name: name
Type: string
Value: One of: c++
or an application defined value.
Description: Specifies the source text language.
Only a value of c++
specifies that source text ([strctopt.core.src]) is
C++ ISO language.
7.1.11. Kind [strctopt.core.kind]
Name: kind
Type: string
Value: A kind item ([strctopt.core.kind])
Description:
The kind, or format, of the source file corresponding to the output
file ([strctopt.core.out]).
7.1.11.1. Kind Object [strctopt.core.kindobj]
Name: name
Type: string
Value: One of: text
, exec
, object
, dynamic_lib
,
archive_lib
Description: The kind, or format, of source and output files.
A text
value specifies that the source or output is textual.
A exec
value specifies that the source or output is an executable program.
A object
value specifies that the source or output is a linkable object.
A dynamic_lib
value specifies that the source or output is dynamically
linkable.
A archive_lib
value specifies that the source or output is an archive, or
collection, of linkable objects.
8. Edit 2
Replace B.2 JSON Schema Specification [strctparamjschm.spec] with [strctparam.json.schema.spec] below.
8.1. JSON Schema Specification [strctparamjschm.spec]
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "std_param-1.0.0.json",
"title": "Structured Parameters Version 1.0.0 JSON Schema",
"type": "object",
"properties": {
"$schema": {
"description": "JSON Schema URI for the version of the structured parameters format.",
"type": "string",
"format": "uri"
},
"version": {
"description": "The Structured Parameters format version.",
"type": "string",
"$ref": "#/$defs/Version"
}
},
"patternProperties": {
"arguments": {
"description": "Application direct arguments.",
"type": "array",
"items": { "type": "string" }
},
"options": {
"type": "object",
"patternProperties": {
"param": { "$ref": "#/$defs/Std.Param" },
"source": {
"$ref": "std_opt_core-1.0.0.json#/$defs/Std.Source"
},
"output": {
"$ref": "std_opt_core-1.0.0.json#/$defs/Std.Output"
},
"include_dirs": {
"$ref": "std_opt_core-1.0.0.json#/$defs/Std.IncludeDirs"
},
"library_dirs": {
"$ref": "std_opt_core-1.0.0.json#/$defs/Std.LibraryDirs"
},
"define": {
"$ref": "std_opt_core-1.0.0.json#/$defs/Std.Define"
},
"undef": {
"$ref": "std_opt_core-1.0.0.json#/$defs/Std.Undef"
},
"language": {
"$ref": "std_opt_core-1.0.0.json#/$defs/Std.Language"
},
"optimization": {
"$ref": "std_opt_core-1.0.0.json#/$defs/Std.Optimization"
},
"vendor": {
"$ref": "std_opt_core-1.0.0.json#/$defs/Std.Vendor"
}
}
}
},
"additionalProperties": false,
"oneOf": [{ "required": ["arguments"] }, { "required": ["options"] }],
"$defs": {
"Version": {
"type": "string",
"pattern": "^[0-9]+([.][0-9]+){0,2}$"
},
"Name": {
"type": "string",
"pattern": "^([a-z0-9_-]+[.])*([a-z0-9_-]+)$"
},
"StringOrArray": {
"type": ["string", "array"],
"items": { "type": "string" }
},
"Std.Param": {
"description": "Recursive reference to one or more structured parameters files.",
"type": "object",
"properties": {
"pre": { "$ref": "#/$defs/StringOrArray" },
"post": { "$ref": "#/$defs/StringOrArray" }
},
"additionalProperties": false
}
}
}
9. Edit 3
Insert [strctopt.core.jschm.annex] (below) after Annex B.
9.1. Annex C
9.1.1. Structured Core Options JSON Schema [strctoptcorejschm]
9.1.1.1. General [strctoptcorejschm.general]
This Annex defines the structured parameter core options schema ([strctopt.core]) in terms os a JSON Schema.
9.1.1.2. JSON Schema Specification [strctoptcorejschm.spec]
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "std_opt_core-1.0.0",
"title": "Structured Core Options Version 1.0.0 JSON Schema",
"patternProperties": {
"source": { "$ref": "#/$defs/Std.Source" },
"output": { "$ref": "#/$defs/Std.Output" },
"include_dirs": { "$ref": "#/$defs/Std.IncludeDirs" },
"library_dirs": { "$ref": "#/$defs/Std.LibraryDirs" },
"define": { "$ref": "#/$defs/Std.Define" },
"undef": { "$ref": "#/$defs/Std.Undef" },
"optimization": { "$ref": "#/$defs/Std.Optimization" },
"vendor": { "$ref": "#/$defs/Std.Vendor" },
"language": { "$ref": "#/$defs/Std.Language" },
"kind": { "$ref": "#/$defs/Std.Kind" }
},
"$defs": {
"Std.Source": {
"description": "The source files to process.",
"type": "array",
"items": {
"description": "A file to process.",
"type": "object",
"patternProperties": {
"name": { "type": "string" },
"language": { "$ref": "#/$defs/Std.Language" },
"kind": { "$ref": "#/$defs/Std.Kind" },
"vendor": { "$ref": "#/$defs/Std.Vendor" }
},
"required": ["name"],
"additionalProperties": false
}
},
"Std.Output": {
"description": "The output files to generate.",
"type": "array",
"items": {
"description": "An output file.",
"type": "object",
"patternProperties": {
"name": { "type": "string" },
"kind": { "$ref": "#/$defs/Std.Kind" },
"vendor": { "$ref": "#/$defs/Std.Vendor" }
},
"required": ["name"],
"additionalProperties": false
}
},
"Std.IncludeDirs": {
"description": "Include directories.",
"type": "array",
"items": { "type": "string" }
},
"Std.LibraryDirs": {
"description": "Library directories.",
"type": "array",
"items": { "type": "string" }
},
"Std.Define": {
"description": "Define preprocessor symbols.",
"type": "array",
"items": {
"type": "object",
"patternProperties": {
"name": { "type": "string" },
"value": {
"type": ["number", "integer", "string", "boolean", "null"]
}
},
"required": ["name"],
"additionalProperties": false
}
},
"Std.Undef": {
"description": "Undefine preprocessor symbols.",
"type": "array",
"items": { "type": "string" }
},
"Std.Language": {
"description": "The language to interpret sources for.",
"type": "object",
"patternProperties": {
"name": {
"type": "string"
}
},
"required": ["name"]
},
"Std.Optimization": {
"description": "The optimizations to apply to different stages of the processing.",
"type": "object",
"patternProperties": {
"compile": {
"type": "string",
"enum": ["off", "minimal", "speed", "space", "debug"]
},
"link": {
"type": "boolean"
},
"vendor": { "$ref": "#/$defs/Std.Vendor" }
}
},
"Std.Vendor": {
"description": "Vendor defined specifications.",
"type": "object",
"patterProperties": {
"^[a-z]+$": {
"type": "object"
}
}
},
"Std.Kind": {
"description": "The kind of data a source of output is.",
"type": "string",
"enum": ["text", "exec", "object", "dynamic_lib", "archive_lib"]
}
}
}
III: Colophon
10. License
This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.