diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2019-03-06 14:41:00 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2019-05-22 12:09:09 +0200 |
commit | d894c48660a573f257f76fe075e512415fdd0f91 (patch) | |
tree | b077999723cc6724c4ab141334af0cb00577ba91 /docs | |
parent | e9bd7d49bdc8c630cca3bf4cc02c437841b6aaf6 (diff) | |
download | meson-d894c48660a573f257f76fe075e512415fdd0f91.zip meson-d894c48660a573f257f76fe075e512415fdd0f91.tar.gz meson-d894c48660a573f257f76fe075e512415fdd0f91.tar.bz2 |
new module "sourceset" to match source file lists against configuration data
In QEMU a single set of source files is built against many different
configurations in order to generate many executable. Each executable
includes a different but overlapping subset of the source files; some
of the files are compiled separately for each output, others are
compiled just once.
Using Makefiles, this is achieved with a complicated mechanism involving
a combination of non-recursive and recursive make; Meson can do better,
but because there are hundreds of such conditional rules, it's important
to keep meson.build files brief and easy to follow. Therefore, this
commit adds a new module to satisfy this use case while preserving
Meson's declarative nature.
Configurations are mapped to a configuration_data object, and a new
"source set" object is used to store all the rules, and then retrieve
the desired set of sources together with their dependencies.
The test case shows how extract_objects can be used to satisfy both
cases, i.e. when the object files are shared across targets and when
they have to be separate. In the real-world case, a project would use
two source set objects for the two cases and then do
"executable(..., sources: ... , objects: ...)". The next commit
adds such an example.
Diffstat (limited to 'docs')
-rw-r--r-- | docs/markdown/SourceSet-module.md | 196 | ||||
-rw-r--r-- | docs/markdown/snippets/sourceset.md | 8 | ||||
-rw-r--r-- | docs/sitemap.txt | 1 |
3 files changed, 205 insertions, 0 deletions
diff --git a/docs/markdown/SourceSet-module.md b/docs/markdown/SourceSet-module.md new file mode 100644 index 0000000..fee643a --- /dev/null +++ b/docs/markdown/SourceSet-module.md @@ -0,0 +1,196 @@ +--- +short-description: Source set module +authors: + - name: Paolo Bonzini + email: pbonzini@redhat.com + years: [2019] +... + +# Source set module + +This module provides support for building many targets against a single set +of files; the choice of which files to include in each target depends on the +contents of a dictionary or a `configuration_data` object. The module can +be loaded with: + +``` meson +ssmod = import('sourceset') +``` + +A simple example of using the module looks like this: + +``` meson +ss = ssmod.source_set() +# Include main.c unconditionally +ss.add(files('main.c')) +# Include a.c if configuration key FEATURE1 is true +ss.add(when: 'FEATURE1', if_true: files('a.c')) +# Include zlib.c if the zlib dependency was found, and link zlib +# in the executable +ss.add(when: zlib, if_true: files('zlib.c')) +# many more rules here... +ssconfig = ss.apply(config) +executable('exe', sources: ssconfig.sources(), + dependencies: ssconfig.dependencies()) +``` + +and it would be equivalent to + +``` meson +sources = files('main.c') +dependencies = [] +if config['FEATURE1'] then + sources += [files('a.c')] +endif +if zlib.found() then + sources += [files('zlib.c')] + dependencies += [zlib] +endif +# many more "if"s here... +executable('exe', sources: sources, dependencies: dependencies()) +``` + +Sourcesets can be used with a single invocation of the `apply` method, +similar to the example above, but the module is especially useful +when multiple executables are generated by applying the same rules to +many different configurations. + +*Added 0.51.0* + +## Functions + +### `source_set()` + +``` meson +ssmod.source_set() +``` + +Create and return a new source set object. + +**Returns**: a [source set][`source_set` object] + +## `source_set` object + +The `source_set` object provides methods to add files to a source set and +to query it. The source set becomes immutable after any method but `add` +is called. + +### Methods + +#### `add()` + +``` meson +source_set.add([when: varnames_and_deps], + [if_true: sources_and_deps], + [if_false: list_of_alt_sources]) +source_set.add(sources_and_deps) +``` + +Add a *rule* to a source set. A rule determines the conditions under which +some source files or dependency objects are included in a build configuration. +All source files must be present in the source tree or they can be created +in the build tree via `configure_file`, `custom_target` or `generator`. + +`varnames_and_deps` is a list of conditions for the rule, which can be +either strings or dependency objects (a dependency object is anything that +has a `found()` method). If *all* the strings evaluate to true and all +dependencies are found, the rule will evaluate to true; `apply()` +will then include the contents of the `if_true` keyword argument in its +result. Otherwise, that is if any of the strings in the positional + arguments evaluate to false or any dependency is not found, `apply()` +will instead use the contents of the `if_false` keyword argument. + +Dependencies can also appear in `sources_and_deps`. In this case, a +missing dependency will simply be ignored and will *not* disable the rule, +similar to how the `dependencies` keyword argument works in build targets. + +**Note**: It is generally better to avoid mixing source sets and disablers. +This is because disablers will cause the rule to be dropped altogether, +and the `list_of_alt_sources` would not be taken into account anymore. + +#### `add_all()` + +``` meson +source_set.add_all(when: varnames_and_deps, + if_true: [source_set1, source_set2, ...]) +source_set.add_all(source_set1, source_set2, ...) +``` + +Add one or more source sets to another. + +For each source set listed in the arguments, `apply()` will +consider their rules only if the conditions in `varnames_and_deps` are +evaluated positively. For example, the following: + +``` meson +sources_b = ssmod.source_set() +sources_b.add(when: 'HAVE_A', if_true: 'file.c') +sources = ssmod.source_set() +sources.add_all(when: 'HAVE_B', if_true: sources_b) +``` + +is equivalent to: + +``` meson +sources = ssmod.source_set() +sources.add(when: ['HAVE_A', 'HAVE_B'], if_true: 'file.c') +``` + +#### `all_sources()` + +``` meson +list source_set.all_sources(...) +``` + +Returns a list of all sources that were placed in the source set using +`add` (including nested source sets) and that do not have a not-found +dependency. If a rule has a not-found dependency, only the `if_false` +sources are included (if any). + +**Returns**: a list of file objects + +#### `apply()` + +``` meson +source_files source_set.apply(conf_data[, strict: false]) +``` + +Match the source set against a dictionary or a `configuration_data` object +and return a *source configuration* object. A source configuration object +allows you to retrieve the sources and dependencies for a specific configuration. + +By default, all the variables that were specified in the rules have to +be present in `conf_data`. However, in some cases the convention is +that `false` configuration symbols are absent in `conf_data`; this is +the case for example when the configuration was loaded from a Kconfig file. +In that case you can specify the `strict: false` keyword argument, which +will treat absent variables as false. + +**Returns**: a [source configuration][`source_configuration` object] + +## `source_configuration` object + +The `source_configuration` object provides methods to query the result of an +`apply` operation on a source set. + +### Methods + +#### `sources()` + +``` meson +source_config.sources() +``` + +Return the source files corresponding to the applied configuration. + +**Returns**: a list of file objects + +#### `dependencies()` + +``` meson +source_config.dependencies() +``` + +Return the dependencies corresponding to the applied configuration. + +**Returns**: a list of dependency objects diff --git a/docs/markdown/snippets/sourceset.md b/docs/markdown/snippets/sourceset.md new file mode 100644 index 0000000..7c09eb5 --- /dev/null +++ b/docs/markdown/snippets/sourceset.md @@ -0,0 +1,8 @@ +## New `sourceset` module + +A new module, `sourceset`, was added to help building many binaries +from the same source files. Source sets associate source files and +dependencies to keys in a `configuration_data` object or a dictionary; +they then take multiple `configuration_data` objects or dictionaries, +and compute the set of source files and dependencies for each of those +configurations. diff --git a/docs/sitemap.txt b/docs/sitemap.txt index 2e6eb68..449f08b 100644 --- a/docs/sitemap.txt +++ b/docs/sitemap.txt @@ -43,6 +43,7 @@ index.md Qt5-module.md RPM-module.md Simd-module.md + SourceSet-module.md Windows-module.md Cuda-module.md Kconfig-module.md |