diff options
Diffstat (limited to 'meson/docs/markdown/howtox.md')
-rw-r--r-- | meson/docs/markdown/howtox.md | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/meson/docs/markdown/howtox.md b/meson/docs/markdown/howtox.md new file mode 100644 index 000000000..1521f7244 --- /dev/null +++ b/meson/docs/markdown/howtox.md @@ -0,0 +1,325 @@ +# 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` only works in native builds. +The `CC` refers to the compiler for the host platform, that is the +compiler used to compile programs that run on the machine we will +eventually install the project on. The compiler used to build things +that run on the machine we do the building can be specified with +`CC_FOR_BUILD`. You can use it in cross builds. + +Note that environment variables are never the idiomatic way to do +anything with Meson, however. It is better to use the native and cross +files. And the tools for the host platform in cross builds can only be +specified with a cross file. + +There is a table of all environment variables supported +[Here](Reference-tables.md#compiler-and-linker-selection-variables) + + +## Set 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' +``` + +There is a table of all environment variables supported +[Here](Reference-tables.md#compiler-and-linker-selection-variables) + + +## 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 configuration data from files + +`The [fs module](#Fs-modules) offers the `read` function` which enables adding +the contents of arbitrary files to configuration data (among other uses): + +```meson +fs = import('fs') +cdata = configuration_data() +copyright = fs.read('LICENSE') +cdata.set('COPYRIGHT', copyright) +if build_machine.system() == 'linux' + os_release = fs.read('/etc/os-release') + cdata.set('LINUX_BUILDER', os_release) +endif +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 +$ meson compile +$ meson test +$ meson compile coverage-html (or coverage-xml) +``` + +The coverage report can be found in the meson-logs subdirectory. + +*New in 0.55.0* llvm-cov support for use 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 program, then do this: + +```console +$ meson setup builddir +$ ninja -C builddir scan-build +``` + +You can use the `SCANBUILD` environment variable to choose the +scan-build executable. + +```console +$ SCANBUILD=<your exe> ninja -C builddir scan-build +``` + +You can use it for passing arguments to scan-build program by +creating a script, for example: + +```sh +#!/bin/sh +scan-build -v --status-bugs "$@" +``` + +And then pass it through the variable (remember to use absolute path): + +```console +$ SCANBUILD=$(pwd)/my-scan-build.sh ninja -C builddir 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 setup <Meson options, such as --buildtype=debugoptimized> -Db_pgo=generate +$ meson compile -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 +$ meson compile +``` + +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) + +## Get a default not-found dependency? + +```meson +null_dep = dependency('', required : false) +``` + +This can be used in cases where you want a default value, but might override it +later. + +```meson +# Not needed on Windows! +my_dep = dependency('', required : false) +if host_machine.system() in ['freebsd', 'netbsd', 'openbsd', 'dragonfly'] + my_dep = dependency('some dep', required : false) +elif host_machine.system() == 'linux' + my_dep = dependency('some other dep', required : false) +endif + +executable( + 'myexe', + my_sources, + deps : [my_dep] +) +``` |