Code generation
Tint makes use of code generation tooling to emit source code and build files used to build Tint.
All code is generated with ./tools/run gen.
The generator uses heavy use of Go's text/template
package. This is augmented with the functions declared in tools/src/template/template.go, and the data types provided by the tooling.
Build file generation
The generator will scan all the Tint source directories to produce BUILD.gn
and BUILD.cmake files. These files contain the per-directory targets,
conditionals and inter-target dependency information which is labour-intensive
to maintain by hand.
The bulk of the build generator logic is in the file: tools/src/cmd/gen/build/build.go
Targets
There are 8 kinds of build target:
cmdtargets are executables.libtargets are libraries used in production code, and can also be used as a dependency by any other target kind .testtargets are libraries used by Tint unittests. Must not be used by production code.test_cmdare test executables.benchtargets are libraries used by Tint benchmarks. Must not be used by production code.bench_cmdare benchmark executables.fuzztargets are libraries used by Tint fuzzers. Must not be used by production code.fuzz_cmdare fuzzer executables.
The build generator uses a file naming convention based on the file name before the extension to classify each source file to a single target kind.
- Source files named
testor with a_testsuffix are classed astestlibrary targets.
Example:parser_test.cc. - Source files named
benchor with a_benchsuffix are classed asbenchlibrary targets.
Example:writer_bench.cc. - Source files named
fuzzor with a_fuzzsuffix are classed asfuzzlibrary targets.
Example:writer_fuzz.cc. - Source files with the name
mainare classed as executable targets. These typically exist undersrc/tint/cmd.
Example:cmd/tint/main.cc. - Source files with the name
main_testare classed as test executable targets. These typically exist undersrc/tint/cmd/test.
Example:cmd/test/main_test.cc. - Source files with the name
main_benchare classed as benchmark executable targets. These typically exist undersrc/tint/cmd/bench.
Example:cmd/benchmark/main_bench.cc. - Source files with the name
main_fuzzare classed as fuzzer executable targets. These typically exist undersrc/tint/cmd/fuzz.
Example:cmd/benchmark/main_bench.cc. - All other files are considered
libtargets.
Example:parser.cc.
Each source directory can have at most one lib, test, test_main, bench, bench_main or cmd
target.
The graph of target dependencies must be acyclic (DAG).
Target dependencies are automatically inferred from #includes made by the source files.
Additional target dependencies can be added with the use of a BUILD.cfg file.
External dependencies
All external dependencies must be declared in src/tint/externals.json.
The syntax of this file is:
{
"external-target-name": {
"IncludePatterns": [
/*
A list of #include path patterns that refer to this external target.
You may use the '*' wildcard for a single directory, or '**' as a multi-directory wildcard.
*/
"myexternal/**.h",
],
/* An optional build condition expression to wrap all uses of this external dependency */
"Condition": "expression",
},
/* Repeat the above for all external targets */
}
GEN_BUILD directives
Source and build files can be annotated with special directives in comments to control the build file generation.
| Directive | Description |
|---|---|
GEN_BUILD:IGNORE_FILE |
Add to a source file to have the file ignored by the generator Example: // GEN_BUILD:IGNORE_FILE |
GEN_BUILD:IGNORE_INCLUDE |
Apply to the end of a #include in a source file to ignore this include for dependency analysis Example: #include "foo/bar.h" // GEN_BUILD:IGNORE_INCLUDE |
GEN_BUILD:CONDITION(cond) |
Applies the build condition for this source file. Example: // GEN_BUILD:CONDITION(is_linux) |
GEN_BUILD:DO_NOT_GENERATE |
Prevents the BUILD.* file from being generated. Example: # GEN_BUILD:DO_NOT_GENERATE |
BUILD.cfg files
A source directory may have an optional BUILD.cfg JSON file. The syntax of this file is:
{
/* Build condition to apply to all targets of this directory. */
"Condition": "cond",
/* Options for the 'lib' target */
"lib": { /* see TargetConfig */ },
/* Options for the 'test' target */
"test": { /* see TargetConfig */ },
/* Options for the 'bench' target */
"bench": { /* see TargetConfig */ },
/* Options for the 'cmd' target */
"cmd": { /* see TargetConfig */ },
}
All fields are optional.
The syntax of TargetConfig is:
{
/* An override for the output file name for the target */
"OutputName": "name",
/* An additional condition for building this target */
"Condition": "cond",
"AdditionalDependencies": {
"Internal": [
/*
A list of target name patterns that should in added as dependencies to this target.
You may use the '*' wildcard for a single directory, or '**' as a multi-directory wildcard.
*/
],
"External": [
/*
A list of external targets that should in added as dependencies to this target.
Must match an external dependency declared in src/tint/externals.json
*/
]
},
}
All fields are optional.
Templates
The build generator will emit a BUILD.ext file in each source directory, for each BUILD.ext.tmpl file found in tools/src/cmd/gen/build.
The template will be passed the Directory as $.