diff options
Diffstat (limited to 'meson/docs/markdown/FAQ.md')
-rw-r--r-- | meson/docs/markdown/FAQ.md | 631 |
1 files changed, 631 insertions, 0 deletions
diff --git a/meson/docs/markdown/FAQ.md b/meson/docs/markdown/FAQ.md new file mode 100644 index 000000000..0ed731e51 --- /dev/null +++ b/meson/docs/markdown/FAQ.md @@ -0,0 +1,631 @@ +--- +title: FAQ +... +# Meson Frequently Asked Questions + +See also [How do I do X in Meson](howtox.md). + +## Why is it called Meson? + +When the name was originally chosen, there were two main limitations: +there must not exist either a Debian package or a Sourceforge project +of the given name. This ruled out tens of potential project names. At +some point the name Gluon was considered. Gluons are elementary +particles that hold protons and neutrons together, much like a build +system's job is to take pieces of source code and a compiler and bind +them to a complete whole. + +Unfortunately this name was taken, too. Then the rest of subatomic +particles were examined and Meson was found to be available. + +## What is the correct way to use threads (such as pthreads)? + +```meson +thread_dep = dependency('threads') +``` + +This will set up everything on your behalf. People coming from +Autotools or CMake want to do this by looking for `libpthread.so` +manually. Don't do that, it has tricky corner cases especially when +cross compiling. + +## How to use Meson on a host where it is not available in system packages? + +Starting from version 0.29.0, Meson is available from the [Python +Package Index](https://pypi.python.org/pypi/meson/), so installing it +simply a matter of running this command: + +```console +$ pip3 install <your options here> meson +``` + +If you don't have access to PyPI, that is not a problem either. Meson +has been designed to be easily runnable from an extracted source +tarball or even a git checkout. First you need to download Meson. Then +use this command to set up you build instead of plain `meson`. + +```console +$ /path/to/meson.py <options> +``` + +After this you don't have to care about invoking Meson any more. It +remembers where it was originally invoked from and calls itself +appropriately. As a user the only thing you need to do is to `cd` into +your build directory and invoke `meson compile`. + +## Why can't I specify target files with a wildcard? + +Instead of specifying files explicitly, people seem to want to do this: + +```meson +executable('myprog', sources : '*.cpp') # This does NOT work! +``` + +Meson does not support this syntax and the reason for this is simple. +This can not be made both reliable and fast. By reliable we mean that +if the user adds a new source file to the subdirectory, Meson should +detect that and make it part of the build automatically. + +One of the main requirements of Meson is that it must be fast. This +means that a no-op build in a tree of 10 000 source files must take no +more than a fraction of a second. This is only possible because Meson +knows the exact list of files to check. If any target is specified as +a wildcard glob, this is no longer possible. Meson would need to +re-evaluate the glob every time and compare the list of files produced +against the previous list. This means inspecting the entire source +tree (because the glob pattern could be `src/\*/\*/\*/\*.cpp` or +something like that). This is impossible to do efficiently. + +The main backend of Meson is Ninja, which does not support wildcard +matches either, and for the same reasons. + +Because of this, all source files must be specified explicitly. + +## But I really want to use wildcards! + +If the tradeoff between reliability and convenience is acceptable to +you, then Meson gives you all the tools necessary to do wildcard +globbing. You are allowed to run arbitrary commands during +configuration. First you need to write a script that locates the files +to compile. Here's a simple shell script that writes all `.c` files in +the current directory, one per line. + + +```bash +#!/bin/sh + +for i in *.c; do + echo $i +done +``` + +Then you need to run this script in your Meson file, convert the +output into a string array and use the result in a target. + +```meson +c = run_command('grabber.sh') +sources = c.stdout().strip().split('\n') +e = executable('prog', sources) +``` + +The script can be any executable, so it can be written in shell, +Python, Lua, Perl or whatever you wish. + +As mentioned above, the tradeoff is that just adding new files to the +source directory does *not* add them to the build automatically. To +add them you need to tell Meson to reinitialize itself. The simplest +way is to touch the `meson.build` file in your source root. Then Meson +will reconfigure itself next time the build command is run. Advanced +users can even write a small background script that utilizes a +filesystem event queue, such as +[inotify](https://en.wikipedia.org/wiki/Inotify), to do this +automatically. + +## Should I use `subdir` or `subproject`? + +The answer is almost always `subdir`. Subproject exists for a very +specific use case: embedding external dependencies into your build +process. As an example, suppose we are writing a game and wish to use +SDL. Let us further suppose that SDL comes with a Meson build +definition. Let us suppose even further that we don't want to use +prebuilt binaries but want to compile SDL for ourselves. + +In this case you would use `subproject`. The way to do it would be to +grab the source code of SDL and put it inside your own source +tree. Then you would do `sdl = subproject('sdl')`, which would cause +Meson to build SDL as part of your build and would then allow you to +link against it or do whatever else you may prefer. + +For every other use you would use `subdir`. As an example, if you +wanted to build a shared library in one dir and link tests against it +in another dir, you would do something like this: + +```meson +project('simple', 'c') +subdir('src') # library is built here +subdir('tests') # test binaries would link against the library here +``` + +## Why is there not a Make backend? + +Because Make is slow. This is not an implementation issue, Make simply +can not be made fast. For further info we recommend you read [this +post](http://neugierig.org/software/chromium/notes/2011/02/ninja.html) +by Evan Martin, the author of Ninja. Makefiles also have a syntax that +is very unpleasant to write which makes them a big maintenance burden. + +The only reason why one would use Make instead of Ninja is working on +a platform that does not have a Ninja port. Even in this case it is an +order of magnitude less work to port Ninja than it is to write a Make +backend for Meson. + +Just use Ninja, you'll be happier that way. I guarantee it. + +## Why is Meson not just a Python module so I could code my build setup in Python? + +A related question to this is *Why is Meson's configuration language +not Turing-complete?* + +There are many good reasons for this, most of which are summarized on +this web page: [Against The Use Of Programming Languages in +Configuration Files](https://taint.org/2011/02/18/001527a.html). + +In addition to those reasons, not exposing Python or any other "real" +programming language makes it possible to port Meson's implementation +to a different language. This might become necessary if, for example, +Python turns out to be a performance bottleneck. This is an actual +problem that has caused complications for GNU Autotools and SCons. + +## How do I do the equivalent of Libtools export-symbol and export-regex? + +Either by using [GCC symbol +visibility](https://gcc.gnu.org/wiki/Visibility) or by writing a +[linker +script](https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html). This +has the added benefit that your symbol definitions are in a standalone +file instead of being buried inside your build definitions. An example +can be found +[here](https://github.com/jpakkane/meson/tree/master/test%20cases/linuxlike/3%20linker%20script). + +## My project works fine on Linux and MinGW but fails to link with MSVC due to a missing .lib file (fatal error LNK1181). Why? + +With GCC, all symbols on shared libraries are exported automatically +unless you specify otherwise. With MSVC no symbols are exported by +default. If your shared library exports no symbols, MSVC will silently +not produce an import library file leading to failures. The solution +is to add symbol visibility definitions [as specified in GCC +wiki](https://gcc.gnu.org/wiki/Visibility). + +## I added some compiler flags and now the build fails with weird errors. What is happening? + +You probably did the equivalent to this: + +```meson +executable('foobar', ... + c_args : '-some_arg -other_arg') +``` + +Meson is *explicit*. In this particular case it will **not** +automatically split your strings at whitespaces, instead it will take +it as is and work extra hard to pass it to the compiler unchanged, +including quoting it properly over shell invocations. This is +mandatory to make e.g. files with spaces in them work flawlessly. To +pass multiple command line arguments, you need to explicitly put them +in an array like this: + +```meson +executable('foobar', ... + c_args : ['-some_arg', '-other_arg']) +``` + +## Why are changes to default project options ignored? + +You probably had a project that looked something like this: + +```meson +project('foobar', 'cpp') +``` + +This defaults to `c++11` on GCC compilers. Suppose you want to use +`c++14` instead, so you change the definition to this: + +```meson +project('foobar', 'cpp', default_options : ['cpp_std=c++14']) +``` + +But when you recompile, it still uses `c++11`. The reason for this is +that default options are only looked at when you are setting up a +build directory for the very first time. After that the setting is +considered to have a value and thus the default value is ignored. To +change an existing build dir to `c++14`, either reconfigure your build +dir with `meson configure` or delete the build dir and recreate it +from scratch. + +The reason we don't automatically change the option value when the +default is changed is that it is impossible to know to do that +reliably. The actual question that we need to solve is "if the +option's value is foo and the default value is bar, should we change +the option value to bar also". There are many choices: + + - if the user has changed the value themselves from the default, then + we must not change it back + + - if the user has not changed the value, but changes the default + value, then this section's premise would seem to indicate that the + value should be changed + + - suppose the user changes the value from the default to foo, then + back to bar and then changes the default value to bar, the correct + step to take is ambiguous by itself + +In order to solve the latter question we would need to remember not +only the current and old value, but also all the times the user has +changed the value and from which value to which other value. Since +people don't remember their own actions that far back, toggling +between states based on long history would be confusing. + +Because of this we do the simple and understandable thing: default +values are only defaults and will never affect the value of an option +once set. + +## Does wrap download sources behind my back? + +It does not. In order for Meson to download anything from the net +while building, two conditions must be met. + +First of all there needs to be a `.wrap` file with a download URL in +the `subprojects` directory. If one does not exist, Meson will not +download anything. + +The second requirement is that there needs to be an explicit +subproject invocation in your `meson.build` files. Either +`subproject('foobar')` or `dependency('foobar', fallback : ['foobar', +'foo_dep'])`. If these declarations either are not in any build file +or they are not called (due to e.g. `if/else`) then nothing is +downloaded. + +If this is not sufficient for you, starting from release 0.40.0 Meson +has a option called `wrap-mode` which can be used to disable wrap +downloads altogether with `--wrap-mode=nodownload`. You can also +disable dependency fallbacks altogether with `--wrap-mode=nofallback`, +which also implies the `nodownload` option. + +If on the other hand, you want Meson to always use the fallback +for dependencies, even when an external dependency exists and could +satisfy the version requirements, for example in order to make +sure your project builds when fallbacks are used, you can use +`--wrap-mode=forcefallback` since 0.46.0. + +## Why is Meson implemented in Python rather than [programming language X]? + +Because build systems are special in ways normal applications aren't. + +Perhaps the biggest limitation is that because Meson is used to build +software at the very lowest levels of the OS, it is part of the core +bootstrap for new systems. Whenever support for a new CPU architecture +is added, Meson must run on the system before software using it can be +compiled natively. This requirement adds two hard limitations. + +The first one is that Meson must have the minimal amount of +dependencies, because they must all be built during the bootstrap to +get Meson to work. + +The second is that Meson must support all CPU architectures, both +existing and future ones. As an example many new programming languages +have only an LLVM based compiler available. LLVM has limited CPU +support compared to, say, GCC, and thus bootstrapping Meson on such +platforms would first require adding new processor support to +LLVM. This is in most cases unfeasible. + +A further limitation is that we want developers on as many platforms +as possible to submit to Meson development using the default tools +provided by their operating system. In practice what this means is +that Windows developers should be able to contribute using nothing but +Visual Studio. + +At the time of writing (April 2018) there are only three languages +that could fulfill these requirements: + + - C + - C++ + - Python + +Out of these we have chosen Python because it is the best fit for our +needs. + +## I have proprietary compiler toolchain X that does not work with Meson, how can I make it work? + +Meson needs to know several details about each compiler in order to +compile code with it. These include things such as which compiler +flags to use for each option and how to detect the compiler from its +output. This information can not be input via a configuration file, +instead it requires changes to Meson's source code that need to be +submitted to Meson master repository. In theory you can run your own +forked version with custom patches, but that's not good use of your +time. Please submit the code upstream so everyone can use the +toolchain. + +The steps for adding a new compiler for an existing language are +roughly the following. For simplicity we're going to assume a C +compiler. + +- Create a new class with a proper name in + `mesonbuild/compilers/c.py`. Look at the methods that other + compilers for the same language have and duplicate what they do. + +- If the compiler can only be used for cross compilation, make sure to + flag it as such (see existing compiler classes for examples). + +- Add detection logic to `mesonbuild/environment.py`, look for a + method called `detect_c_compiler`. + +- Run the test suite and fix issues until the tests pass. + +- Submit a pull request, add the result of the test suite to your MR + (linking an existing page is fine). + +- If the compiler is freely available, consider adding it to the CI + system. + +## Why does building my project with MSVC output static libraries called `libfoo.a`? + +The naming convention for static libraries on Windows is usually +`foo.lib`. Unfortunately, import libraries are also called `foo.lib`. + +This causes filename collisions with the default library type where we +build both shared and static libraries, and also causes collisions +during installation since all libraries are installed to the same +directory by default. + +To resolve this, we decided to default to creating static libraries of +the form `libfoo.a` when building with MSVC. This has the following +advantages: + +1. Filename collisions are completely avoided. +1. The format for MSVC static libraries is `ar`, which is the same as the GNU + static library format, so using this extension is semantically correct. +1. The static library filename format is now the same on all platforms and with + all toolchains. +1. Both Clang and GNU compilers can search for `libfoo.a` when specifying + a library as `-lfoo`. This does not work for alternative naming schemes for + static libraries such as `libfoo.lib`. +1. Since `-lfoo` works out of the box, pkgconfig files will work correctly for + projects built with both MSVC, GCC, and Clang on Windows. +1. MSVC does not have arguments to search for library filenames, and [it does + not care what the extension is](https://docs.microsoft.com/en-us/cpp/build/reference/link-input-files?view=vs-2019), + so specifying `libfoo.a` instead of `foo.lib` does not change the workflow, + and is an improvement since it's less ambiguous. + +If, for some reason, you really need your project to output static +libraries of the form `foo.lib` when building with MSVC, you can set +the +[`name_prefix:`](https://mesonbuild.com/Reference-manual.html#library) +kwarg to `''` and the +[`name_suffix:`](https://mesonbuild.com/Reference-manual.html#library) +kwarg to `'lib'`. To get the default behaviour for each, you can +either not specify the kwarg, or pass `[]` (an empty array) to it. + +## Do I need to add my headers to the sources list like in Autotools? + +Autotools requires you to add private and public headers to the sources list so +that it knows what files to include in the tarball generated by `make dist`. +Meson's `dist` command simply gathers everything committed to your git/hg +repository and adds it to the tarball, so adding headers to the sources list is +pointless. + +Meson uses Ninja which uses compiler dependency information to automatically +figure out dependencies between C sources and headers, so it will rebuild +things correctly when a header changes. + +The only exception to this are generated headers, for which you must [declare +dependencies correctly](#how-do-i-tell-meson-that-my-sources-use-generated-headers). + +If, for whatever reason, you do add non-generated headers to the sources list +of a target, Meson will simply ignore them. + +## How do I tell Meson that my sources use generated headers? + +Let's say you use a [`custom_target()`](https://mesonbuild.com/Reference-manual.html#custom_target) +to generate the headers, and then `#include` them in your C code. Here's how +you ensure that Meson generates the headers before trying to compile any +sources in the build target: + +```meson +libfoo_gen_headers = custom_target('gen-headers', ..., output: 'foo-gen.h') +libfoo_sources = files('foo-utils.c', 'foo-lib.c') +# Add generated headers to the list of sources for the build target +libfoo = library('foo', sources: [libfoo_sources + libfoo_gen_headers]) +``` + +Now let's say you have a new target that links to `libfoo`: + +```meson +libbar_sources = files('bar-lib.c') +libbar = library('bar', sources: libbar_sources, link_with: libfoo) +``` + +This adds a **link-time** dependency between the two targets, but note that the +sources of the targets have **no compile-time** dependencies and can be built +in any order; which improves parallelism and speeds up builds. + +If the sources in `libbar` *also* use `foo-gen.h`, that's a *compile-time* +dependency, and you'll have to add `libfoo_gen_headers` to `sources:` for +`libbar` too: + +```meson +libbar_sources = files('bar-lib.c') +libbar = library('bar', sources: libbar_sources + libfoo_gen_headers, link_with: libfoo) +``` + +Alternatively, if you have multiple libraries with sources that link to +a library and also use its generated headers, this code is equivalent to above: + +```meson +# Add generated headers to the list of sources for the build target +libfoo = library('foo', sources: libfoo_sources + libfoo_gen_headers) + +# Declare a dependency that will add the generated headers to sources +libfoo_dep = declare_dependency(link_with: libfoo, sources: libfoo_gen_headers) + +... + +libbar = library('bar', sources: libbar_sources, dependencies: libfoo_dep) +``` + +**Note:** You should only add *headers* to `sources:` while declaring +a dependency. If your custom target outputs both sources and headers, you can +use the subscript notation to get only the header(s): + +```meson +libfoo_gen_sources = custom_target('gen-headers', ..., output: ['foo-gen.h', 'foo-gen.c']) +libfoo_gen_headers = libfoo_gen_sources[0] + +# Add static and generated sources to the target +libfoo = library('foo', sources: libfoo_sources + libfoo_gen_sources) + +# Declare a dependency that will add the generated *headers* to sources +libfoo_dep = declare_dependency(link_with: libfoo, sources: libfoo_gen_headers) +... +libbar = library('bar', sources: libbar_sources, dependencies: libfoo_dep) +``` + +A good example of a generator that outputs both sources and headers is +[`gnome.mkenums()`](https://mesonbuild.com/Gnome-module.html#gnomemkenums). + +## How do I disable exceptions and RTTI in my C++ project? + +With the `cpp_eh` and `cpp_rtti` options. A typical invocation would +look like this: + +``` +meson -Dcpp_eh=none -Dcpp_rtti=false <other options> +``` + +The RTTI option is only available since Meson version 0.53.0. + +## Should I check for `buildtype` or individual options like `debug` in my build files? + +This depends highly on what you actually need to happen. The +´buildtype` option is meant do describe the current build's +_intent_. That is, what it will be used for. Individual options are +for determining what the exact state is. This becomes clearer with a +few examples. + +Suppose you have a source file that is known to miscompile when using +`-O3` and requires a workaround. Then you'd write something like this: + +```meson +if get_option('optimization') == '3' + add_project_arguments('-DOPTIMIZATION_WORKAROUND', ...) +endif +``` + +On the other hand if your project has extra logging and sanity checks +that you would like to be enabled during the day to day development +work (which uses the `debug` buildtype), you'd do this instead: + +```meson +if get_option('buildtype') == 'debug' + add_project_arguments('-DENABLE_EXTRA_CHECKS', ...) +endif +``` + +In this way the extra options are automatically used during +development but are not compiled in release builds. Note that (since +Meson 0.57.0) you can set optimization to, say, 2 in your debug builds +if you want to. If you tried to set this flag based on optimization +level, it would fail in this case. + +## How do I use a library before declaring it? + +This is valid (and good) code: +``` +libA = library('libA', 'fileA.cpp', link_with : []) +libB = library('libB', 'fileB.cpp', link_with : [libA]) +``` +But there is currently no way to get something like this to work: +``` +libB = library('libB', 'fileB.cpp', link_with : [libA]) +libA = library('libA', 'fileA.cpp', link_with : []) +``` +This means that you HAVE to write your `library(...)` calls in the order that the +dependencies flow. While ideas to make arbitrary orders possible exist, they were +rejected because reordering the `library(...)` calls was considered the "proper" +way. See [here](https://github.com/mesonbuild/meson/issues/8178) for the discussion. + +## Why doesn't meson have user defined functions/macros? + +The tl;dr answer to this is that meson's design is focused on solving specific +problems rather than providing a general purpose language to write complex +code solutions in build files. Build systems should be quick to write and +quick to understand, functions muddle this simplicity. + +The long answer is twofold: + +First, Meson aims to provide a rich set of tools that solve specific problems +simply out of the box. This is similar to the "batteries included" mentality of +Python. By providing tools that solve common problems in the simplest way +possible *in* Meson we are solving that problem for everyone instead of forcing +everyone to solve that problem for themselves over and over again, often +badly. One example of this are Meson's dependency wrappers around various +config-tool executables (sdl-config, llvm-config, etc). In other build +systems each user of that dependency writes a wrapper and deals with the +corner cases (or doesn't, as is often the case), in Meson we handle them +internally, everyone gets fixes and the corner cases are ironed out for +*everyone*. Providing user defined functions or macros goes directly against +this design goal. + +Second, functions and macros makes the build system more difficult to reason +about. When you encounter some function call, you can refer to the reference +manual to see that function and its signature. Instead of spending +frustrating hours trying to interpret some bit of m4 or follow long include +paths to figure out what `function1` (which calls `function2`, which calls +`function3`, ad infinitum), you know what the build system is doing. Unless +you're actively developing Meson itself, it's just a tool to orchestrate +building the thing you actually care about. We want you to spend as little +time worrying about build systems as possible so you can spend more time on +*your code*. + +Many times user defined functions are used due to a lack of loops or +because loops are tedious to use in the language. Meson has both arrays/lists +and hashes/dicts natively. Compare the following pseudo code: + +```meson +func(name, sources, extra_args) + executable( + name, + sources, + c_args : extra_args + ) +endfunc + +func(exe1, ['1.c', 'common.c'], []) +func(exe2, ['2.c', 'common.c'], []) +func(exe2_a, ['2.c', 'common.c'], ['-arg']) +``` + +```meson +foreach e : [['1', '1.c', []], + ['2', '2.c', []], + ['2', '2.c', ['-arg']]] + executable( + 'exe' + e[0], + e[1], + c_args : e[2], + ) +endforeach +``` + +The loop is both less code and is much easier to reason about than the function +version is, especially if the function were to live in a separate file, as is +common in other popular build systems. + +Build system DSLs also tend to be badly thought out as generic programming +languages, Meson tries to make it easy to use external scripts or programs +for handling complex problems. While one can't always convert build logic +into a scripting language (or compiled language), when it can be done this is +often a better solution. External languages tend to be well-thought-out and +tested, generally don't regress, and users are more likely to have domain +knowledge about them. They also tend to have better tooling (such as +autocompletion, linting, testing solutions), which make them a lower +maintenance burden over time. |