The Meson Build System http://mesonbuild.com/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

261 lines
6.9 KiB

# How do I do X in Meson?
This page lists code snippets for common tasks. These are written
mostly using the C compiler, but the same approach should work on
almost all other compilers.
## Set compiler
When first running Meson, set it in an environment variable.
```console
$ CC=mycc meson <options>
```
Note that environment variables like `CC` _always_ refer to the native
compiler. That is, the compiler used to compile programs that run on
the current machine. The compiler used in cross compilation is set
with the cross file.
This behaviour is different from e.g. Autotools, where cross
compilation is done by setting `CC` to point to the cross compiler
(such as `/usr/bin/arm-linux-gnueabihf-gcc`). The reason for this is
that Meson supports natively the case where you compile helper tools
(such as code generators) and use the results during the
build. Because of this Meson needs to know both the native and the
cross compiler. The former is set via the environment variables or
native-files and the latter via the cross file only.
## Set dynamic linker
*New in 0.53.0*
Like the compiler, the linker is selected via the `<compiler variable>_LD`
environment variable, or through the `<compiler entry>_ld` entry in a native
or cross file. You must be aware of whether you're using a compiler that
invokes the linker itself (most compilers including GCC and Clang) or a
linker that is invoked directly (when using MSVC or compilers that act like
it, including Clang-Cl). With the former `c_ld` or `CC_LD` should be the value
to pass to the compiler's special argument (such as `-fuse-ld` with clang and
gcc), with the latter it should be an executable, such as `lld-link.exe`.
*NOTE* In meson 0.53.0 the `ld` entry in the cross/native file and the `LD`
environment variable were used, this resulted in a large number of regressions
and was changed in 0.53.1 to `<lang>_ld` and `<comp variable>_LD`.
```console
$ CC=clang CC_LD=lld meson <options>
```
or
```console
$ CC=clang-cl CC_LD=link meson <options>
```
or in a cross or native file:
```ini
[binaries]
c = 'clang'
c_ld = 'lld'
```
## Set default C/C++ language version
```meson
project('myproj', 'c', 'cpp',
default_options : ['c_std=c11', 'cpp_std=c++11'])
```
The language version can also be set on a per-target basis.
```meson
executable(..., override_options : ['c_std=c11'])
```
## Enable threads
Lots of people seem to do this manually with `find_library('pthread')`
or something similar. Do not do that. It is not portable. Instead do
this.
```meson
thread_dep = dependency('threads')
executable(..., dependencies : thread_dep)
```
## Set extra compiler and linker flags from the outside (when e.g. building distro packages)
The behavior is the same as with other build systems, with environment
variables during first invocation. Do not use these when you need to rebuild
the source
```console
$ CFLAGS=-fsomething LDFLAGS=-Wl,--linker-flag meson <options>
```
## Use an argument only with a specific compiler
First check which arguments to use.
```meson
if meson.get_compiler('c').get_id() == 'clang'
extra_args = ['-fclang-flag']
else
extra_args = []
endif
```
Then use it in a target.
```meson
executable(..., c_args : extra_args)
```
If you want to use the arguments on all targets, then do this.
```meson
if meson.get_compiler('c').get_id() == 'clang'
add_global_arguments('-fclang-flag', language : 'c')
endif
```
## Set a command's output to configuration
```meson
txt = run_command('script', 'argument').stdout().strip()
cdata = configuration_data()
cdata.set('SOMETHING', txt)
configure_file(...)
```
## Generate a runnable script with `configure_file`
`configure_file` preserves metadata so if your template file has
execute permissions, the generated file will have them too.
## Producing a coverage report
First initialize the build directory with this command.
```console
$ meson <other flags> -Db_coverage=true
```
Then issue the following commands.
```console
$ ninja
$ ninja test
$ ninja coverage-html (or coverage-xml)
```
The coverage report can be found in the meson-logs subdirectory.
Note: Currently, Meson does not support generating coverage reports
with Clang.
## Add some optimization to debug builds
By default the debug build does not use any optimizations. This is the
desired approach most of the time. However some projects benefit from
having some minor optimizations enabled. GCC even has a specific
compiler flag `-Og` for this. To enable its use, just issue the
following command.
```console
$ meson configure -Dc_args=-Og
```
This causes all subsequent builds to use this command line argument.
## Use address sanitizer
Clang comes with a selection of analysis tools such as the [address
sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html). Meson
has native support for these with the `b_sanitize` option.
```console
$ meson <other options> -Db_sanitize=address
```
After this you just compile your code and run the test suite. Address
sanitizer will abort executables which have bugs so they show up as
test failures.
## Use Clang static analyzer
Install scan-build and configure your project. Then do this:
```console
$ ninja scan-build
```
You can use the `SCANBUILD` environment variable to choose the
scan-build executable.
```console
$ SCANBUILD=<your exe> ninja scan-build
```
## Use profile guided optimization
Using profile guided optimization with GCC is a two phase
operation. First we set up the project with profile measurements
enabled and compile it.
```console
$ meson <Meson options, such as --buildtype=debugoptimized> -Db_pgo=generate
$ ninja -C builddir
```
Then we need to run the program with some representative input. This
step depends on your project.
Once that is done we change the compiler flags to use the generated
information and rebuild.
```console
$ meson configure -Db_pgo=use
$ ninja
```
After these steps the resulting binary is fully optimized.
## Add math library (`-lm`) portably
Some platforms (e.g. Linux) have a standalone math library. Other
platforms (pretty much everyone else) do not. How to specify that `m`
is used only when needed?
```meson
cc = meson.get_compiler('c')
m_dep = cc.find_library('m', required : false)
executable(..., dependencies : m_dep)
```
## Install an executable to `libexecdir`
```meson
executable(..., install : true, install_dir : get_option('libexecdir'))
```
## Use existing `Find<name>.cmake` files
Meson can use the CMake `find_package()` ecosystem if CMake is installed.
To find a dependency with custom `Find<name>.cmake`, set the `cmake_module_path`
property to the path in your project where the CMake scripts are stored.
Example for a `FindCmakeOnlyDep.cmake` in a `cmake` subdirectory:
```meson
cm_dep = dependency('CmakeOnlyDep', cmake_module_path : 'cmake')
```
The `cmake_module_path` property is only needed for custom CMake scripts. System
wide CMake scripts are found automatically.
More information can be found [here](Dependencies.md#cmake)