diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/markdown/Porting-from-autotools.md | 2 | ||||
-rw-r--r-- | docs/markdown/Reference-manual.md | 88 | ||||
-rw-r--r-- | docs/markdown/Wrap-best-practices-and-tips.md | 38 |
3 files changed, 104 insertions, 24 deletions
diff --git a/docs/markdown/Porting-from-autotools.md b/docs/markdown/Porting-from-autotools.md index 91ed5d2..5786e0e 100644 --- a/docs/markdown/Porting-from-autotools.md +++ b/docs/markdown/Porting-from-autotools.md @@ -578,7 +578,7 @@ introspection_sources = [ 'as-tag.c', 'as-tag.h', 'as-utils.c', - 'as-utils.h'] + 'as-utils.h', 'as-version.h'] gnome.generate_gir(asglib, diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 901535b..c98bd79 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -68,10 +68,10 @@ Like `add_project_arguments` but the arguments are passed to the linker. Add a custom test setup that can be used to run the tests with a custom setup, for example under Valgrind. The keyword arguments are the following: +- `env` an [environment object](#environment-object) to use a custom environment - `exe_wrapper` a list containing the wrapper command or script followed by the arguments to it - `gdb` if `true`, the tests are also run under `gdb` - `timeout_multiplier` a number to multiply the test timeout with -- `env` an [environment object](#environment-object) to use a custom environment To use the test setup, run `mesontest --setup=*name*` inside the build dir. @@ -123,12 +123,21 @@ When a list of strings is passed to the `command:` keyword argument, it takes an These are all the supported keyword arguments: -- `input` the input file name. If it's not specified in configuration mode, all the variables in the `configuration:` object (see above) are written to the `output:` file. -- `output` the output file name (since v0.41.0, may contain `@PLAINNAME@` or `@BASENAME@` substitutions). In configuration mode, the permissions of the input file (if it is specified) are copied to the output file. -- `configuration` as explained above, this is where you pass the configuration data object as returned by `configuration_data()` -- `command` as explained above, if specified, Meson does not create the file itself but rather runs the specified command, which allows you to do fully custom file generation -- `capture` when this argument is set to true, Meson captures `stdout` of the `command` and writes it to the target file specified as `output`. Available since v0.41.0. -- `install_dir` the subdirectory to install the generated file to (e.g. `share/myproject`), if omitted the file is not installed. +- `capture` when this argument is set to true, Meson captures `stdout` + of the `command` and writes it to the target file specified as + `output`. Available since v0.41.0. +- `command` as explained above, if specified, Meson does not create + the file itself but rather runs the specified command, which allows + you to do fully custom file generation +- `input` the input file name. If it's not specified in configuration + mode, all the variables in the `configuration:` object (see above) + are written to the `output:` file. +- `install_dir` the subdirectory to install the generated file to + (e.g. `share/myproject`), if omitted the file is not installed. +- `output` the output file name (since v0.41.0, may contain + `@PLAINNAME@` or `@BASENAME@` substitutions). In configuration mode, + the permissions of the input file (if it is specified) are copied to + the output file. ### custom_target() @@ -136,30 +145,63 @@ These are all the supported keyword arguments: customtarget custom_target(*name*, ...) ``` -Create a custom top level build target. The only positional argument is the name of this target and the keyword arguments are the following. - +Create a custom top level build target. The only positional argument +is the name of this target and the keyword arguments are the +following. + +- `build_by_default` *(added 0.38.0)* causes, when set to true, to + have this target be built by default, that is, when invoking plain + `ninja`; the default value is false +- `build_always` if `true` this target is always considered out of + date and is rebuilt every time, useful for things such as build + timestamps or revision control tags +- `capture`, there are some compilers that can't be told to write + their output to a file but instead write it to standard output. When + this argument is set to true, Meson captures `stdout` and writes it + to the target file. Note that your command argument list may not + contain `@OUTPUT@` when capture mode is active. +- `command` command to run to create outputs from inputs. The command + may be strings or the return of `find_program()` or `executable()` + (note: always specify commands in array form `['commandname', + '-arg1', '-arg2']` rather than as a string `'commandname -arg1 + -arg2'` as the latter will *not* work) +- `depend_files` files ([`string`](#string-object), + [`files()`](#files), or [`configure_file()`](#configure_file)) that + this target depends on but are not listed in the `command` keyword + argument. Useful for adding regen dependencies. +- `depends` specifies that this target depends on the specified + target(s), even though it does not take any of them as a command + line argument. This is meant for cases where you have a tool that + e.g. does globbing internally. Usually you should just put the + generated sources as inputs and Meson will set up all dependencies + automatically. +- `depfile` is a dependency file that the command can write listing + all the additional files this target depends on, for example a C + compiler would list all the header files it included, and a change + in any one of these files triggers a recompilation - `input` list of source files. As of 0.41.0 the list will be flattened. -- `output` list of output files -- `command` command to run to create outputs from inputs. The command may be strings or the return of `find_program()` or `executable()` (note: always specify commands in array form `['commandname', '-arg1', '-arg2']` rather than as a string `'commandname -arg1 -arg2'` as the latter will *not* work) - `install` when true, this target is installed during the install step - `install_dir` directory to install to -- `build_always` if `true` this target is always considered out of date and is rebuilt every time, useful for things such as build timestamps or revision control tags -- `capture`, there are some compilers that can't be told to write their output to a file but instead write it to standard output. When this argument is set to true, Meson captures `stdout` and writes it to the target file. Note that your command argument list may not contain `@OUTPUT@` when capture mode is active. -- `depends` specifies that this target depends on the specified target(s), even though it does not take any of them as a command line argument. This is meant for cases where you have a tool that e.g. does globbing internally. Usually you should just put the generated sources as inputs and Meson will set up all dependencies automatically. -- `depend_files` files ([`string`](#string-object), [`files()`](#files), or [`configure_file()`](#configure_file)) that this target depends on but are not listed in the `command` keyword argument. Useful for adding regen dependencies. -- `depfile` is a dependency file that the command can write listing all the additional files this target depends on, for example a C compiler would list all the header files it included, and a change in any one of these files triggers a recompilation -- `build_by_default` *(added 0.38.0)* causes, when set to true, to have this target be built by default, that is, when invoking plain `ninja`; the default value is false - -The list of strings passed to the `command` keyword argument accept the following special string substitutions: +- `output` list of output files -- `@INPUT@` the full path to the input passed to `input`. If more than one input is specified, all of them will be substituted as separate arguments only if the command uses `'@INPUT@'` as a standalone-argument. For instance, this would not work: `command : ['cp', './@INPUT@']`, but this would: `command : ['cp', '@INPUT@']`. -- `@OUTPUT@` the full path to the output passed to `output`. If more than one outputs are specified, the behavior is the same as `@INPUT@`. +The list of strings passed to the `command` keyword argument accept +the following special string substitutions: + +- `@INPUT@` the full path to the input passed to `input`. If more than + one input is specified, all of them will be substituted as separate + arguments only if the command uses `'@INPUT@'` as a + standalone-argument. For instance, this would not work: `command : + ['cp', './@INPUT@']`, but this would: `command : ['cp', '@INPUT@']`. +- `@OUTPUT@` the full path to the output passed to `output`. If more + than one outputs are specified, the behavior is the same as + `@INPUT@`. - `@INPUT0@` `@INPUT1@` `...` the full path to the input with the specified array index in `input` - `@OUTPUT0@` `@OUTPUT1@` `...` the full path to the output with the specified array index in `output` - `@OUTDIR@` the full path to the directory where the output(s) must be written - `@DEPFILE@` the full path to the dependency file passed to `depfile` -The returned object also has methods that are documented in the [object methods section](#custom-target-object) below. +The returned object also has methods that are documented in the +[object methods section](#custom-target-object) below. ### declare_dependency() @@ -543,7 +585,7 @@ This function prints its argument to stdout. void project(project_name, list_of_languages, ...) ``` -The first argument to this function must be a string defining the name of this project. It must be followed by one or more programming languages that the project uses. Supported values for languages are `c`, `cpp` (for `C++`), `objc`, `objcpp`, `fortran`, `java`, `cs` (for `C#`) and `vala`. +The first argument to this function must be a string defining the name of this project. It is followed by programming languages that the project uses. Supported values for languages are `c`, `cpp` (for `C++`), `objc`, `objcpp`, `fortran`, `java`, `cs` (for `C#`) and `vala`. In versions before `0.40.0` you must have at least one language listed. The project name can be any string you want, it's not used for anything except descriptive purposes. However since it is written to e.g. the dependency manifest is usually makes sense to have it be the same as the project tarball or pkg-config name. So for example you would probably want to use the name _libfoobar_ instead of _The Foobar Library_. diff --git a/docs/markdown/Wrap-best-practices-and-tips.md b/docs/markdown/Wrap-best-practices-and-tips.md index cebc779..b164ec5 100644 --- a/docs/markdown/Wrap-best-practices-and-tips.md +++ b/docs/markdown/Wrap-best-practices-and-tips.md @@ -61,3 +61,41 @@ executable('dep_using_exe', 'main.c', ``` Meson will ensure that the header file has been built before compiling `main.c`. + +## Avoid exposing compilable source files in declare_dependency + +The main use for the `sources` argument in `declare_dependency` is to construct the correct dependency graph for the backends, as demonstrated in the previous section. It is extremely important to note that it should *not* be used to directly expose compilable sources (`.c`, `.cpp`, etc.) of dependencies, and should rather only be used for header/config files. The following example will illustrate what can go wrong if you accidentally expose compilable source files. + +So you've read about unity builds and how Meson natively supports them. You decide to expose the sources of dependencies in order to have unity builds that include their dependencies. For your support library you do + +```meson +my_support_sources = files(...) + +mysupportlib = shared_library( + ... + sources : my_support_sources, + ...) +mysupportlib_dep = declare_dependency( + ... + link_with : mylibrary, + sources : my_support_sources, + ...) +``` + +And for your main project you do: + +```meson +mylibrary = shared_library( + ... + dependencies : mysupportlib_dep, + ...) +myexe = executable( + ... + link_with : mylibrary, + dependencies : mysupportlib_dep, + ...) +``` + +This is extremely dangerous. When building, `mylibrary` will build and link the support sources `my_support_sources` into the resulting shared library. Then, for `myexe`, these same support sources will be compiled again, will be linked into the resulting executable, in addition to them being already present in `mylibrary`. This can quickly run afoul of the [One Definition Rule (ODR)](https://en.wikipedia.org/wiki/One_Definition_Rule) in C++, as you have more than one definition of a symbol, yielding undefined behavior. While C does not have a strict ODR rule, there is no language in the standard which guarantees such behavior to work. Violations of the ODR can lead to weird idiosyncratic failures such as segfaults. In the overwhelming number of cases, exposing library sources via the `sources` argument in `declare_dependency` is thus incorrect. If you wish to get full cross-library performance, consider building `mysupportlib` as a static library instead and employing LTO. + +There are exceptions to this rule. If there are some natural constraints on how your library is to be used, you can expose sources. For instance, the WrapDB module for GoogleTest directly exposes the sources of GTest and GMock. This is valid, as GTest and GMock will only ever be used in *terminal* link targets. A terminal target is the final target in a dependency link chain, for instance `myexe` in the last example, whereas `mylibrary` is an intermediate link target. For most libraries this rule is not applicable though, as you cannot in general control how others consume your library, and as such should not expose sources. |