README
Meson Documentation
Build dependencies
Meson uses itself and hotdoc for generating documentation.
Minimum required version of hotdoc is 0.8.9.
Instructions on how to install hotdoc are here.
Our custom hotdoc extensions require:
- chevron
- strictyaml
Building the documentation
From the Meson repository root dir:
$ cd docs/
$ meson setup built_docs/
$ ninja -C built_docs/Now you should be able to open the documentation locally
built_docs/Meson documentation-doc/html/index.htmlUpload
Meson uses the git-upload hotdoc plugin which basically
removes the html pages and replaces with the new content.
You can simply run:
$ ninja -C built_docs/ upload---
Markdown/Snippets/Fix Intro Target Dependencies
Target introspection reports all direct target dependencies
The depends entry in intro-targets.json now reports direct target
dependencies from target inputs, generated sources, extracted objects,
internal linking, and explicit depends arguments. Previously it only
reported the dependencies attribute used by alias and run targets, so most
build target and custom target dependencies were omitted.
---
Markdown/Snippets/Rosetta Can Run Host Binaries
meson.can_run_host_binaries() now accounts for Rosetta 2 on Apple Silicon
Previously, when cross-compiling for x86_64 on an aarch64 Mac,
[[meson.can_run_host_binaries]] (and the underlying needs_exe_wrapper
logic) always returned false, even though Rosetta 2 lets these Macs
execute x86_64 binaries directly. Meson now detects whether Rosetta 2
is installed and, if so, reports that x86_64 host binaries can run
natively without requiring an exe_wrapper.
---
Markdown/Snippets/Subproject Lang Args
Per-subproject language arguments are now applied
Compiler and linker arguments set for a specific subproject, for example-Dsub:c_args=-DFOO on the command line or c_args in thedefault_options of a subproject() call, are now added to the compile
and link commands of that subproject's targets. Previously such values
were accepted and stored but silently ignored.
Similarly, <lang>_args and <lang>_link_args entries in a target'soverride_options now take effect.
In all cases the per-subproject or per-target value replaces the global
value (including flags coming from environment variables such asCFLAGS), it is not appended to it. This matches whatget_option('c_args') already returned inside a subproject.
---
Markdown/Snippets/Wild Linker
Wild linker is now supported on Linux
When CC_LD environment variables is set to wild, Meson will configure GCC 16+ or Clang
to use Wild as the linker on Linux. You should expect to see line like this in the output:C linker for the host machine: cc ld.wild 0.10.0 confirming that Wild was picked up.
---
Markdown/ Include Qt Base
compile_resources
New in 0.59.0
Compiles Qt's resources collection files (.qrc) into c++ files for compilation.
It takes no positional arguments, and the following keyword arguments:
- name (string | empty): if provided a single .cpp file will be generated,
and the output of all qrc files will be combined in this file, otherwise
each qrc file be written to its own cpp file.
- sources (File | string | custom_target | custom_target index | generator_output)[]:
A list of sources to be transpiled. Required, must have at least one source
New in 0.60.0: support for custom_target, custom_target_index, and generator_output.
- extra_args string[]: Extra arguments to pass directly to qt-rcc
- method string: The method to use to detect Qt, see dependency() for more
information.
compile_ui
New in 0.59.0
Compiles Qt's ui files (.ui) into header files.
It takes no positional arguments, and the following keyword arguments:
- sources (File | string | custom_target | custom_target index | generator_output)[]:
A list of sources to be transpiled. Required, must have at least one source
New in 0.60.0: support for custom_target, custom_target_index, and generator_output.
- extra_args string[]: Extra arguments to pass directly to qt-uic
- method string: The method to use to detect Qt, see dependency() for more
information.
- preserve_paths bool: Since 1.4.0. If true, specifies that the output
files need to maintain their directory structure inside the target temporary
directory. For instance, when a file called subdir/one.input is processed
it generates a file {target private directory}/subdir/one.out when true,
and {target private directory}/one.out when false (default).
compile_moc
New in 0.59.0
Compiles Qt's moc files (.moc) into header and/or source files. At least one of
the keyword arguments headers and sources must be provided.
It takes no positional arguments, and the following keyword arguments:
- sources (File | string | custom_target | custom_target index | generator_output)[]:
A list of sources to be transpiled into .moc files for manual inclusion.
New in 0.60.0: support for custom_target, custom_target_index, and generator_output.
- headers (File | string | custom_target | custom_target index | generator_output)[]:
A list of headers to be transpiled into .cpp files
New in 0.60.0: support for custom_target, custom_target_index, and generator_output.
- extra_args string[]: Extra arguments to pass directly to qt-moc
- method string: The method to use to detect Qt, see dependency() for more
information.
- dependencies: dependency objects whose include directories are used by moc.
- include_directories (string | IncludeDirectory)[]: A list of include_directory()
objects used when transpiling the .moc files
- preserve_paths bool: New in 1.4.0. If true, specifies that the output
files need to maintain their directory structure inside the target temporary
directory. For instance, when a file called subdir/one.input is processed
it generates a file {target private directory}/subdir/one.out when true,
and {target private directory}/one.out when false (default).
preprocess
Consider using compile_resources, compile_ui, and compile_moc instead.
Takes sources for moc, uic, and rcc, and converts them into c++ files for
compilation.
Has the following signature: qt.preprocess(name: str | None, *sources: str)
If the name parameter is passed then all of the rcc files will be written to a single output file
The variadic sources arguments have been deprecated since Meson 0.59.0, as has the sources keyword argument. These passed files unmodified through the preprocessor, don't do this, just add the output of the generator to another sources list:
sources = files('a.cpp', 'main.cpp', 'bar.c')
sources += qt.preprocess(qresources : ['resources'])This method takes the following keyword arguments:
- qresources (string | File)[]: Passed to the RCC compiler
- ui_files: (string | File | CustomTarget)[]: Passed the uic compiler
- moc_sources: (string | File | CustomTarget)[]: Passed the moc compiler. These are converted into .moc files meant to be #includeed
- moc_headers: (string | File | CustomTarget)[]: Passed the moc compiler. These will be converted into .cpp files
- include_directories (IncludeDirectories | string)[], the directories to add to header search path for moc
- moc_extra_arguments string[]: any additional arguments to moc. Since v0.44.0.
- uic_extra_arguments string[]: any additional arguments to uic. Since v0.49.0.
- rcc_extra_arguments string[]: any additional arguments to rcc. Since v0.49.0.
- dependencies Dependency[]: dependency objects needed by moc. Available since v0.48.0.
- sources: a list of extra sources, which are added to the output unchanged. Deprecated in 0.59.0.
- preserve_paths bool: New in 1.4.0. If true, specifies that the output
files need to maintain their directory structure inside the target temporary
directory. For instance, when a file called subdir/one.input is processed
it generates a file {target private directory}/subdir/one.out when true,
and {target private directory}/one.out when false (default).
It returns an array of targets and sources to pass to a compilation target.
compile_translations
since 0.44.0
This method generates the necessary targets to build translation files with
lrelease, it takes no positional arguments, and the following keyword arguments:
- ts_files (File | string | custom_target | custom_target index | generator_output)[]:
the list of input translation files produced by Qt's lupdate tool.
New in 0.60.0: support for custom_target, custom_target_index, and generator_output.
- install bool: when true, this target is installed during the install step (optional).
- install_dir string: directory to install to (optional).
- build_by_default bool: when set to true, to have this target be built by
default, that is, when invoking meson compile; the default value is false
(optional).
- qresource string: rcc source file to extract ts_files from; cannot be used
with ts_files kwarg. Available since v0.56.0.
- rcc_extra_arguments string[]: any additional arguments to rcc (optional),
when used with qresource. Available since v0.56.0.
Returns either: a list of custom targets for the compiled
translations, or, if using a qresource file, a single custom target
containing the processed source file, which should be passed to a main
build target.
has_tools
since 0.54.0
This method returns true if all tools used by this module are found,false otherwise.
It should be used to compile optional Qt code:
qt5 = import('qt5')
if qt5.has_tools(required: get_option('qt_feature'))
moc_files = qt5.preprocess(...)
...
endifThis method takes the following keyword arguments:
- required bool | FeatureOption: by default, required is set to false. If required is set totrue
or an enabled feature and some tools aremethod
missing Meson will abort.
- string: method used to find the Qt dependency (auto by default).version
- str | array[str]: Since 1.11.0. Specifies the required version,
a string containing a comparison operator followed by the version string.
Dependencies
See Qt dependencies
The 'modules' argument is used to include Qt modules in the project.
See the Qt documentation for the list of
modules.
The 'private_headers' argument allows usage of Qt's modules private
headers. (since v0.47.0)
Example
A simple example would look like this:
qt5 = import('qt5')
qt5_dep = dependency('qt5', modules: ['Core', 'Gui'])
inc = include_directories('includes')
moc_files = qt5.compile_moc(headers : 'myclass.h',
extra_args: ['-DMAKES_MY_MOC_HEADER_COMPILE'],
include_directories: inc,
dependencies: qt5_dep)
translations = qt5.compile_translations(ts_files : 'myTranslation_fr.ts', build_by_default : true)
executable('myprog', 'main.cpp', 'myclass.cpp', moc_files,
include_directories: inc,
dependencies : qt5_dep)Sometimes, translations are embedded inside the binary using qresource
files. In this case the ts files do not need to be explicitly listed,
but will be inferred from the built qm files listed in the qresource
file. For example:
qt5 = import('qt5')
qt5_dep = dependency('qt5', modules: ['Core', 'Gui'])
lang_cpp = qt5.compile_translations(qresource: 'lang.qrc')
executable('myprog', 'main.cpp', lang_cpp,
dependencies: qt5_dep)---
Markdown/ Sidebar
Quick References
* Functions
* Options
* Configuration
* Dependencies
* Tests
* Syntax
Modules
* codegen
* gnome
* i18n
* pkgconfig
* rust
* wayland
---
Markdown/Adding Arguments
---
short-description: Adding compiler arguments
...
Adding arguments
Often you need to specify extra compiler arguments. Meson provides two
different ways to achieve this: global arguments and per-target
arguments.
Global arguments
--
Global compiler arguments are set with the following command. As an
example you could do this.
add_global_arguments('-DFOO=bar', language : 'c')This makes Meson add the define to all C compilations. Usually you
would use this setting for flags for global settings. Note that for
setting the C/C++ language standard (the -std=c99 argument in GCC),
you would probably want to use a default option of the [[project]]
function. For details see the reference manual.
Global arguments have certain limitations. They all have to be defined
before any build targets are specified. This ensures that the global
flags are the same for every single source file built in the entire
project with one exception. Compilation tests that are run as part of
your project configuration do not use these flags. The reason for that
is that you may need to run a test compile with and without a given
flag to determine your build setup. For this reason tests do not use
these global arguments.
You should set only the most essential flags with this setting, you
should not set debug or optimization flags. Instead they should be
specified by selecting an appropriate build type.
Project arguments
--
Project arguments work similar to global arguments except that they
are valid only within the current subproject. The usage is simple:
add_project_arguments('-DMYPROJ=projname', language : 'c')This would add the compiler flags to all C sources in the current
project.
Per target arguments
--
Per target arguments are just as simple to define.
executable('prog', 'prog.cc', cpp_args : '-DCPPTHING')Here we create a C++ executable with an extra argument that is used
during compilation but not for linking.
You can find the parameter name for other languages in the reference
tables.
Specifying extra linker arguments is done in the same way:
executable('prog', 'prog.cc', link_args : '-Wl,--linker-option')---
Markdown/Adding New Projects To Wrapdb
Adding new projects to WrapDB
How it works
New wraps must be submitted as a working subproject to the wrapdb
repository.
There are two types of wraps on WrapDB - regular wraps and wraps with
Meson build definition patches.
Wraps with Meson build definition patches work in much the same way as
Debian: we take the unaltered upstream source package and add a new
build system to it as a patch. These build systems are stored as a
subdirectory of subprojects/packagefiles/. They only contain build
definition files. You may also think of them as an overlay to upstream
source.
Wraps without Meson build definition patches only contain the wrap
metadata describing how to fetch the project
Whenever a new release is pushed into the wrapdb, a new tag is
generated with an incremented version number, and a new release is
added to the wrapdb API listing. All the old releases remain
unaltered. New commits are always done via GitHub merge requests and
must be reviewed by someone other than the submitter.
Note that your Git repo with wrap must not contain the subdirectory of
the source release. That gets added automatically by the service. You
also must not commit any source code from the original tarball into
the wrap repository.
Choosing the wrap name
Wrapped subprojects are used much like external dependencies. Thus
they should have the same name as the upstream projects.
NOTE: Wrap names must fully match this regexp: [a-z0-9._]+.
If the project provides a pkg-config file, then the wrap name
should be the same as the pkg-config name. Usually this is the name of
the project, such as libpng. Sometimes it is slightly different,ogg
however. As an example the libogg project's chosen pkg-config name is instead of libogg, which is the reason why the wrap isogg
named plain .
If there is no pkg-config file, the name the project uses/promotes
should be used, lowercase only (Catch2 -> catch2).
If the project name is too generic or ambiguous (e.g. benchmark),organization-project
consider using naming format (e.g.google-benchmark).
Overriding dependencies in the submitted project
Ideally the project you submit should make a call to meson.override_dependency
for each dependency you would like to expose, with the first argument
matching the pkg-config file name. This abstracts away the
need to know and keep track of the variable names downstream.
For instance, the Apache Arrow project exposes multiple dependencies like
its base arrow library, along with an arrow-compute library. Thearrow.pc
project generates and arrow-compute.pc files for pkg-config
respectively, so internally the project also calls:
arrow_dep = declare_dependency(...)
meson.override_dependency('arrow', arrow_dep)arrow_compute_dep = declare_dependency(...)
meson.override_dependency('arrow-compute', arrow_compute_dep)
How to contribute a new wrap
If the project already uses Meson build system, then only a wrap file
project.wrap should be provided. In other case a Meson buildmeson.build
definition patch - a set of files - should also be
provided.
Creating the wrap contents
New release branches require a project.wrap file, so create one if
needed.
${EDITOR} upstream.wrapThe file format is simple, see any existing wrapdb subproject for the
content. The checksum is SHA-256 and can be calculated with the
following command on most unix-like operating systems:
sha256sum path/to/libfoo-1.0.0.tar.gzUnder macOS the command is the following:
shasum -a 256 path/to/libfoo-1.0.0.tar.gzNext you need to add the entries that define what dependencies the
current project provides. This is important, as it is what makes
Meson's automatic dependency resolver work.
Assuming the project that you are creating
a wrap file for has called meson.override_dependency, then youprovide
can declare those overridden dependencies in the section
of the wrap file:
[provide]
dependency_names = arrow, arrow_computeIn the case that you do not control the upstream Meson configuration
and it does not already make a call to meson.override_dependency,
then you can still expose dependency variables in the wrap file, using
a syntax like:
[provide]
arrow = arrow_dep
arrow_compute = arrow_compute_depThe arrow and arrow_compute parts on the left refer to the dependencyarrow_dep
names, which should be the same as their Pkg-Config name. andarrow_compute_dep on the right refer to the variables in the builddeclare_dependency
definition that provide the dependencies. Most commonly, they hold the
result of a call. If a variable of that name is
not defined, Meson will exit with a hard error. For further details see
the main Wrap manual.
However, it is strongly advised in such cases to request that the upstream
repository use meson.override_dependency for its next release, so that
the variable names chosen in the upstream configuration file can be
decoupled from the wrap file contents.
Now you can create the build files, if the upstream project does not
contain any, and work on them until the project builds correctly.
Remember that all files go in the directory
subprojects/packagefiles/<project-name>.
${EDITOR} meson.build meson_options.txtIn order to apply the locally added build files to the upstream
release tarball, the wrap-file section must contain apatch_directory property naming the subdirectory in
subprojects/packagefiles/ with the build files inside, as this is
central to the way the wrapdb works. It will be used by the wrapdb
meson.build, and when a release is created, the files from this
directory will be converted into an archive and a patch_url will be
added to the wrap file.
When you are satisfied with the results, add the build files to Git, update
releases.json as described in
README.md, and push the result
to GitHub.
<verify that your project builds and runs>
git add releases.json subprojects/project.wrap subprojects/packagefiles/project/
git commit -a -m 'Add wrap files for libfoo-1.0.0'
git push -u origin libfooNow you should create a pull request on GitHub.
If packaging review requires you to do changes, use the --amendcommit
argument to so that your branch will have only one commit.
${EDITOR} meson.build
git commit -u --amend
git push --forceChanges to original source
The point of a wrap is to provide the upstream project with as few
changes as possible. Most projects should not contain anything more
than a few Meson definition files. Sometimes it may be necessary to
add a template header file or something similar. These should be held
at a minimum.
It should especially be noted that there must not be any patches
to functionality. All such changes must be submitted to upstream. You
may also host your own Git repo with the changes if you wish. The Wrap
system has native support for Git subprojects.
Passing automatic validation
Every submitted wrap goes through an automated correctness review and
passing it is a requirement for merging. Therefore it is highly
recommended that you run the validation checks yourself so you can fix
any issues faster.
You can test the wrap itself with the following commands:
meson subprojects purge --confirm
tools/sanity_checks.py
The first command is to ensure the wrap is correctly fetched from the
latest packagefiles. The second command builds the project and runs tests.
If you want to manually build the project without running the full test
suite, you can:
meson setup builddir/ -Dwraps=<project-name>
The GitHub project contains automatic CI on pushing to run the project
and check the metadata for obvious mistakes. This can be checked from
your fork before submitting a PR.
---
Markdown/Additional
---
short-description: Misc documentation
...
Additional documentation
This section references documents miscellaneous design, benchmarks, or
basically anything concerning Meson.
---
Markdown/ARM Performance Test
Arm performance test
Performance differences in build systems become more apparent on
slower platforms. To examine this difference we compared the
performance of Meson with GNU Autotools. We took the GLib software
project and rewrote its build setup with Meson. GLib was chosen
because it is a relatively large C code base which requires lots of
low level configuration.
The Meson version of the build system is not fully equivalent to the
original Autotools one. It does not do all the same configuration
steps and does not build all the same targets. The biggest missing
piece being internationalisation support with Gettext. However it does
configure the system enough to build all C source and run all unit
tests.
All measurements were done on a Nexus 4 smart phone running the latest
Ubuntu touch image (updated on September 9th 2013).
Measurements
------
The first thing we measured was the time it took to run the configure step.
Meson takes roughly 20 seconds whereas Autotools takes 220. This is a
difference of one order of magnitude. Autotools' time contains both
autogen and configure. Again it should be remembered that Meson does
not do all the configure steps that Autotools does. It does do about
90% of them and it takes just 10% of the time to do it.
Then we measured the build times. Two parallel compilation processes
were used for both systems.
On desktop machines Ninja based build systems are 10-20% faster than
Make based ones. On this platform the difference grows to 50%. The
difference is probably caused by Make's inefficient disk access
patterns. Ninja is better at keeping both cores running all the time
which yields impressive performance improvements.
Next we measured the "empty build" case. That is, how long does it
take for the build system to detect that no changes need to be
made. This is one of the most important metrics of build systems
because it places a hard limit on how fast you can iterate on your
code. Autotools takes 14 seconds to determine that no work needs to be
done. Meson (or, rather, Ninja) takes just one quarter of a second.
One step which takes quite a lot of time is linking. A common case is
that you are working on a library and there are tens of small test
executables that link to it. Even if the compilation step would be
fast, relinking all of the test executables takes time. It is common
for people to manually compile only one test application with a
command such as make sometest rather than rebuild everything.
Meson has an optimization for this case. Whenever a library is
rebuilt, Meson inspects the ABI it exports. If it has not changed,
Meson will skip all relinking steps as unnecessary. The difference
this makes can be clearly seen in the chart above. In that test the
source was fully built, then the file glib/gbytes.c was touched to
force the rebuild of the base glib shared library. As can be seen,
Autotools then relinks all test executables that link with glib. Since
Meson can detect that the ABI is the same it can skip those steps. The
end result being that Meson is almost one hundred times faster on this
very common use case.
Conclusions
-----
One of the main drawbacks of C and C++ compared to languages such as
Java are long compilation times. However at least some of the blame
can be found in the build tools used rather than the languages
themselves or their compilers. Choosing proper tools can bring C and
C++ compilation very close to instantaneous rebuilds. This has a
direct impact on programmer productivity.
---
Markdown/Build Options
---
short-description: Build options to configure project properties
...
Build options
Most non-trivial builds require user-settable options. As an example a
program may have two different data backends that are selectable at
build time. Meson provides for this by having an option definition
file. Its name is meson.options and it is placed at the root ofmeson_options.txt
your source tree. For versions of meson before 1.1, this file was called.
Here is a simple option file.
option('someoption', type : 'string', value : 'optval', description : 'An option')
option('other_one', type : 'boolean', value : false)
option('combo_opt', type : 'combo', choices : ['one', 'two', 'three'], value : 'three')
option('integer_opt', type : 'integer', min : 0, max : 5, value : 3) # Since 0.45.0
option('free_array_opt', type : 'array', value : ['one', 'two']) # Since 0.44.0
option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two'])
option('some_feature', type : 'feature', value : 'enabled') # Since 0.47.0
option('long_desc', type : 'string', value : 'optval',
description : 'An option with a very long description' +
'that does something in a specific context') # Since 0.55.0For built-in options, see [Built-in options][builtin_opts].
Build option types
All types allow a description value to be set describing the option,
if no description is set then the name of the option will be used instead.
Strings
The string type is a free form string. If the default value is not set
then an empty string will be used as the default.
Booleans
Booleans may have values of either true or false. If no defaulttrue
value is supplied then will be used as the default.
Combos
A combo allows any one of the values in the choices parameter to be
selected. If no default value is set then the first value will be the
default.
Integers
An integer option contains a single integer with optional upper and
lower values that are specified with the min and max keyword
arguments.
This type is available since Meson version 0.45.0.
Arrays
Arrays represent an array of strings. By default the array can contain
arbitrary strings. To limit the possible values that can be used set the
choices parameter. Meson will then only allow the value array tovalue
contain strings that are in the given list. The array may be
empty. The parameter specifies the default value of the optionchoices
and if it is unset then the values of will be used as the
default.
As of 0.47.0 -Dopt= and -Dopt=[] both pass an empty list, before this
-Dopt= would pass a list with an empty string.
This type is available since version 0.44.0
Features
A feature option has three states: enabled, disabled or auto.required
It is intended to be passed as a value for the keyword
argument of most functions. Currently supported in
[[add_languages]],
[[compiler.find_library]],
[[compiler.has_header]],
[[dependency]],
[[find_program]],
[[import]] and
[[subproject]]
functions.
- enabled is the same as passing required : true.auto
- is the same as passing required : false.disabled
- do not look for the dependency and always return 'not-found'.
When getting the value of this type of option using [[get_option]], a
special [[@feature]] object is returned instead
of the string representation of the option's value. This object can be
passed to required:
d = dependency('foo', required : get_option('myfeature'))
if d.found()
app = executable('myapp', 'main.c', dependencies : [d])
endifTo check the value of the feature, the object has three methods
returning a boolean and taking no argument:
- .enabled().disabled()
- .auto()
-
This is useful for custom code depending on the feature:
if get_option('myfeature').enabled()
# ...
endifIf the value of a feature option is set to auto, that value isauto_features
overridden by the global option (which defaults toauto). This is intended to be used by packagers who want to haveauto_features=enabled
full control on which dependencies are required and which are
disabled, and not rely on build-deps being installed (at the right
version) to get a feature enabled. They could set to enable all features and disable explicitly
only the few they don't want, if any.
This type is available since version 0.47.0
Deprecated options
Since 0.60.0
Project options can be marked as deprecated and Meson will warn when user sets a
value to it. It is also possible to deprecate only some of the choices, and map
deprecated values to a new value.
Option fully deprecated, it warns when any value is set.
option('o1', type: 'boolean', deprecated: true)One of the choices is deprecated, it warns only when 'a' is in the list of values.
option('o2', type: 'array', choices: ['a', 'b'], deprecated: ['a'])One of the choices is deprecated, it warns only when 'a' is in the list of values
and replace it by 'c'.
option('o3', type: 'array', choices: ['a', 'b', 'c'], deprecated: {'a': 'c'})A boolean option has been replaced by a feature, old true/false values are remapped.
option('o4', type: 'feature', deprecated: {'true': 'enabled', 'false': 'disabled'})A feature option has been replaced by a boolean, enabled/disabled/auto values are remapped.
option('o5', type: 'boolean', deprecated: {'enabled': 'true', 'disabled': 'false', 'auto': 'false'})Since 0.63.0 the deprecated keyword argument can take the name of a new option
that replaces this option. In that case, setting a value on the deprecated option
will set the value on both the old and new names, assuming they accept the same
values.
A boolean option has been replaced by a feature with another name, old true/false values
are accepted by the new option for backward compatibility.
option('o6', type: 'boolean', value: 'true', deprecated: 'o7')
option('o7', type: 'feature', value: 'enabled', deprecated: {'true': 'enabled', 'false': 'disabled'})A project option is replaced by a module option
option('o8', type: 'string', value: '', deprecated: 'python.platlibdir')Using build options
optval = get_option('opt_name')This function also allows you to query the value of Meson's built-in
project options. For example, to get the installation prefix you would
issue the following command:
prefix = get_option('prefix')It should be noted that you cannot set option values in your Meson
scripts. They have to be set externally with the meson configuremeson configure
command line tool. Running without arguments in a
build dir shows you all options you can set.
To change their values use the -D
option:
$ meson configure -Doption=newvalueSetting the value of arrays is a bit special. If you only pass a
single string, then it is considered to have all values separated by
commas. Thus invoking the following command:
$ meson configure -Darray_opt=foo,barwould set the value to an array of two elements, foo and bar.
If you need to have commas in your string values, then you need to
pass the value with proper shell quoting like this:
$ meson configure "-Doption=['a,b', 'c,d']"The inner values must always be single quotes and the outer ones
double quotes.
To change values in subprojects prepend the name of the subproject and
a colon:
$ meson configure -Dsubproject:option=newvalueNOTE: If you cannot call meson configure you likely have an oldmesonconf
version of Meson. In that case you can call instead, but
that is deprecated in newer versions
Yielding to superproject option
Suppose you have a master project and a subproject. In some cases it
might be useful to have an option that has the same value in both of
them. This can be achieved with the yield keyword. Suppose you have
an option definition like this:
option('some_option', type : 'string', value : 'value', yield : true)If you build this project on its own, this option behaves like
usual. However if you build this project as a subproject of another
project which also has an option called some_option, then callingget_option returns the value of the superproject. If the value ofyield is false, get_option returns the value of the subproject's
option.
Since 1.8.0 -Dsub:some_option=anothervalue, when used with a
yielding option, sets the value separately from the option
it yields to.
Built-in build options
There are a number of [built-in options][builtin_opts]. To get the
current list execute meson configure in the build directory.
[builtin_opts]: https://mesonbuild.com/Builtin-options.html
Visual Studio
#### Startup project
The backend_startup_project option can be set to define the default
project that will be executed with the "Start debugging F5" action in
visual studio. It should be the same name as an executable target
name.
project('my_project', 'c', default_options: ['backend_startup_project=my_exe'])
executable('my_exe', ...)Ninja
#### Max links
The backend_max_links can be set to limit the number of processes
that ninja will use to link.
---
Markdown/Build System Converters
---
short-description: Converting other build systems to Meson
...
Build system converters
Moving from one build system into another includes a fair bit of
work. To make things easier, Meson provides scripts to convert other
build systems into Meson. At the time of writing, scripts for CMake
and autotools exist. It can be found in the tools subdirectory in
Meson's source tree.
The scripts do not try to do a perfect conversion. This would be
extremely difficult because the data models of other build systems are
very different. The goal of the converter script is to convert as much
of the low level drudgery as possible. Using the scripts is
straightforward. We'll use the CMake one as an example but the
Autotools one works exactly the same way.
cmake2meson.py path/to/CMake/project/root
This command generates a skeleton Meson project definition that tries
to mirror CMake's setup as close as possible. Once this is done, you
need to go through these files manually and finalize the
conversion. To make this task as simple as possible, the converter
script will transfer all comments from the CMake definition into Meson
definition.
---
Markdown/Build Targets
---
short-description: Definition of build targets
...
Build targets
Meson provides four kinds of build targets: executables, libraries
(which can be set to be built as static or shared or both of them at
the build configuration time), static libraries, and shared libraries.
They are created with the commands executable, library,static_library and shared_library, respectively. All objects created
in this way are immutable. That is, you cannot change any aspect of
them after they have been constructed. This ensures that all information
pertaining to a given build target is specified in one well defined
place.
Libraries and executables
--
As an example, here is how you would build a library.
project('shared lib', 'c')
library('mylib', 'source.c')It is generally preferred to use the library command instead ofshared_library and static_library and then configure whichdefault_library
libraries (static or shared or both of them) will be built at the
build configuration time using the
built-in option.
In Unix-like operating systems, shared libraries can be
versioned. Meson supports this with keyword arguments, which will be
ignored if the library is configured as static at the compile time.
project('shared lib', 'c')
library('mylib', 'source.c', version : '1.2.3', soversion : '1')It is common to build a library and then an executable that links
against it. This is supported as well.
project('shared lib', 'c')
lib = library('mylib', 'source.c')
executable('program', 'prog.c', link_with : lib)Meson sets things up so that the resulting executable can be run
directly from the build directory. There is no need to write shell
scripts or set environment variables.
One target can have multiple language source files.
project('multilang', 'c', 'cpp')
executable('multiexe', 'file.c', 'file2.cc')Object files
--
Sometimes you can't build files from sources but need to utilize an
existing object file. A typical case is using an object file provided
by a third party. Object files can be specified just like sources.
exe = executable('myexe', 'source.cpp', objects : 'third_party_object.o')A different case is when you want to use object files built in one
target directly in another. A typical case is when you build a shared
library and it has an internal class that is not exported in the
ABI. This means you can't access it even if you link against the
library. Typical workarounds for this include building both a shared
and static version of the library or putting the source file in the
test executable's source list. Both of these approaches cause the
source to be built twice, which is slow.
In Meson you can extract object files from targets and use them as-is
on other targets. This is the syntax for it.
lib = shared_library('somelib', 'internalclass.cc', 'file.cc', ...)
eo = lib.extract_objects('internalclass.cc')
executable('classtest', 'classtest.cpp', objects : eo)Here we take the internal class object and use it directly in the
test. The source file is only compiled once.
Note that careless use of this feature may cause strange bugs. As an
example trying to use objects of an executable or static library in a
shared library will not work because shared library objects require
special compiler flags. Getting this right is the user's
responsibility. For this reason it is strongly recommended that you
only use this feature for generating unit test executables in the
manner described above.
---
Markdown/Builtin Options
---
short-description: Built-in options to configure project properties
...
Built-in options
Meson provides two kinds of options: build options provided by the
build files and built-in options that are either
universal options, base options, compiler options.
Universal options
All these can be set by passing -Doption=value to meson (aka meson
setup), or by setting them inside default_options of [[project]] in yourmeson.build. Some options can also be set by --option=value, or --option
value -- a list is shown by running meson setup --help.
For legacy reasons --warnlevel is the cli argument for thewarning_level option.
They can also be edited after setup using meson configure
-Doption=value.
Installation options are usually relative to the prefix but it should
not be relied on, since they can be absolute paths in the following cases:
* When the prefix is /usr: sysconfdir defaults to /etc,localstatedir
defaults to /var, and sharedstatedir defaults to/var/lib
/usr/local
* When the prefix is : localstatedir defaults/var/local
to , and sharedstatedir defaults to /var/local/lib
* When an absolute path outside of prefix is provided by the user/distributor.
Directories
| Option | Default value | Description |
| ------ | ------------- | ----------- |
| prefix | see below | Installation prefix |
| bindir | bin | Executable directory |
| datadir | share | Data file directory |
| includedir | include | Header file directory |
| infodir | share/info | Info page directory |
| libdir | see below | Library directory |
| licensedir | see below | Licenses directory (since 1.1.0)|
| libexecdir | libexec | Library executable directory |
| localedir | share/locale | Locale data directory |
| localstatedir | var | Localstate data directory |
| mandir | share/man | Manual page directory |
| sbindir | sbin | System executable directory |
| sharedstatedir | com | Architecture-independent data directory |
| sysconfdir | etc | Sysconf data directory |
prefix defaults to C:/ on Windows, and /usr/local otherwise. You
should always override this value.
libdir is automatically detected based on your platform, it should
be correct when doing "native" (build machine == host machine)
compilation. For cross compiles Meson will try to guess the correct
libdir, but it may not be accurate, especially on Linux where
different distributions have different defaults. Using a cross
file, particularly the
paths section may be necessary.
licensedir is empty by default. If set, it defines the default location
to install a dependency manifest and project licenses. For more details,
see [[meson.install_dependency_manifest]].
Core options
Options that are labeled "per machine" in the table are set per
machine. See the specifying options per
machine section for details.
| Option | Default value | Description | Is per machine | Per subproject (since) |
| -------------------------------------- | ------------- | ----------- | -------------- | ---------------------- |
| auto_features {enabled, disabled, auto} | auto | Override value of all 'auto' features | no | no |
| backend {ninja, vs,<br>vs2010, vs2012, vs2013, vs2015, vs2017, vs2019, vs2022, xcode, none} | ninja | Backend to use | no | no |
| genvslite {vs2022} | vs2022 | Setup multi-buildtype ninja build directories and Visual Studio solution | no | no |
| buildtype {plain, debug,<br>debugoptimized, release, minsize, custom} | debug | Build type to use | no | 1.8.0 |
| debug | true | Enable debug symbols and other information | no | 1.8.0 |
| default_both_libraries {shared, static, auto} | shared | Default library type for both_libraries | no | 1.8.0 |
| default_library {shared, static, both} | shared | Default library type | no | 0.54.0 |
| errorlogs | true | Whether to print the logs from failing tests. | no | no |
| install_umask {preserve, 0000-0777} | 022 | Default umask to apply on permissions of installed files | no | no |
| layout {mirror,flat} | mirror | Build directory layout | no | no |
| namingscheme {platform, classic} | classic | Library naming scheme to use | no | 1.10.0 |
| optimization {plain, 0, g, 1, 2, 3, s} | 0 | Optimization level | no | 1.8.0 |
| pkg_config_path {OS separated path} | '' | Additional paths for pkg-config to search before builtin paths | yes | no |
| prefer_static | false | Whether to try static linking before shared linking | no | no |
| cmake_prefix_path | [] | Additional prefixes for cmake to search before builtin paths | yes | no |
| stdsplit | true | Split stdout and stderr in test logs | no | no |
| strip | false | Strip targets on install | no | 1.8.0 |
| unity {on, off, subprojects} | off | Unity build | no | 1.8.0 |
| unity_size {>=2} | 4 | Unity file block size | no | 1.8.0 |
| warning_level {0, 1, 2, 3, everything} | 1 | Set the warning level. From 0 = compiler default to everything = highest | no | 0.56.0 |
| werror | false | Treat warnings as errors | no | 0.54.0 |
| wrap_mode {default, nofallback,<br>nodownload, forcefallback, nopromote} | default | Wrap mode to use | no | no |
| force_fallback_for | [] | Force fallback for those dependencies | no | no |
| vsenv | false | Activate Visual Studio environment | no | no |
| os2_emxomf | false | Use OMF format on OS/2 | no | no |
(For the Rust language only, warning_level=0 disables all warnings).
#### Details for backend
Several build file formats are supported as command runners to build the
configured project. Meson prefers ninja by default, but platform-specific
backends are also available for better IDE integration with native tooling:
Visual Studio for Windows, and xcode for macOS. It is also possible to
configure with no backend at all, which is an error if you have targets to
build, but for projects that need configuration + testing + installation allows
for a lighter automated build pipeline.
#### Details for genvslite
Setup multiple buildtype-suffixed, ninja-backend build directories (e.g.
[builddir]_[debug/release/etc.]) and generate [builddir]_vs containing a Visual
Studio solution with multiple configurations that invoke a meson compile of the
setup build directories, as appropriate for the current configuration (buildtype).
This has the effect of a simple setup macro of multiple 'meson setup ...'
invocations with a set of different buildtype values. E.g.
meson setup ... --genvslite vs2022 somebuilddir does the following -meson setup ... --backend ninja --buildtype debug somebuilddir_debug
meson setup ... --backend ninja --buildtype debugoptimized somebuilddir_debugoptimized
meson setup ... --backend ninja --buildtype release somebuilddir_release
and additionally creates another 'somebuilddir_vs' directory that contains
a generated multi-configuration visual studio solution and project(s) that are
set to build/compile with the somebuilddir_[...] that's appropriate for the
solution's selected buildtype configuration.
#### Details for buildtype
<a name="build-type-options"></a> For setting optimization levels and
toggling debug, you can either set the buildtype option, or you canoptimization
set the and debug options which give finer control-Dbuildtype=debugoptimized
over the same. Whichever you decide to use, the other will be deduced
from it. For example, is the same as-Ddebug=true -Doptimization=2 and vice-versa. This table documents
the two-way mapping:
| buildtype | debug | optimization |
| --------- | ----- | ------------ |
| plain | false | plain |
| debug | true | 0 |
| debugoptimized | true | 2 |
| release | false | 3 |
| minsize | true | s |
All other combinations of debug and optimization set buildtype to 'custom'.
Note that -Ddebug=false does not cause the compiler preprocessor macroNDEBUG to be defined.b_ndebug
The macro can be defined using the base option , described below.
#### Details for warning_level
Exact flags per warning level is compiler specific, but there is an approximate
table for most common compilers.
| Warning level | GCC/Clang | MSVC |
| ------------- | --- | ---- |
| 0 | | |
| 1 | -Wall | /W2 |
| 2 | -Wall -Wextra | /W3 |
| 3 | -Wall -Wextra -Wpedantic | /W4 |
| everything | -Weverything | /Wall |
Clang's -Weverything is emulated on GCC by passing all known warning flags.
#### Details for vsenv
The --vsenv argument is supported since 0.60.0, -Dvsenv=true syntax is supported1.1.0
since .
Since 0.59.0, meson automatically activates a Visual Studio environment on Windowsgcc
for all its subcommands, but only if no other compilers (e.g. or clang)
are found, and silently continues if Visual Studio activation fails.
Setting the vsenv option to true forces Visual Studio activation even when other
compilers are found. It also make Meson abort with an error message when activation
fails.
vsenv is true by default when using the vs backend.
#### Details for default_both_libraries
Since 1.6.0, you can specify the default type of library selected when using aboth_libraries object with default_both_libraries. Note that, unlikedefault_library, this option does not affect how the library artifacts are
built, but how they are internally linked to the dependent targets within the
same project.
The possible values of this option are 'shared' (default value, compatible with
previous meson versions), 'static', and 'auto'. With auto, the value from the
default_library option is used, unless it is 'both', in which case 'shared' is
used instead.
When default_both_libraries is 'auto', passing a [[@both_libs]] dependency
in [[both_libraries]] will link the static dependency with the static lib,
and the shared dependency with the shared lib.
#### Details for os2_emxomf
The --os2-emxomf argument is supported since 1.10.0, -Dos2_emxomf=true1.10.0
syntax is supported since .
Setting the os2_emxomf option to true forces to use emxomf toolchains in
order to generate OMF files instead of aout toolchains.
os2_emxomf is false by default.
Base options
These are set in the same way as universal options, either by
-Doption=value, or by setting them inside default_options ofmeson.build
[[project]] in your . However, they cannot be shown inmeson setup --help
the output of because they depend on both the currentmeson configure
platform and the compiler that will be selected. The only way to see
them is to setup a builddir and then run on it with
no options.
The following options are available. Note that they may not be
available on all platforms or with all compilers:
| Option | Default value | Possible values | Description |
|---------------------|----------------------|---------------------------------------------------------------|--------------------------------------------------------------------------------|
| b_asneeded | true | true, false | Use -Wl,--as-needed when linking |
| b_bitcode | false | true, false | Embed Apple bitcode, see below |
| b_colorout | always | auto, always, never | Use colored output |
| b_coverage | false | true, false | Enable coverage tracking |
| b_lundef | true | true, false | Don't allow undefined symbols when linking |
| b_lto | false | true, false | Use link time optimization |
| b_lto_threads | 0 | Any integer | Use multiple threads for lto. (Added in 0.57.0)* |
| b_lto_mode | default | default, thin | Select between lto modes, thin and default. (Added in 0.57.0) |
| b_thinlto_cache | false | true, false | Enable LLVM's ThinLTO cache for faster incremental builds. (Added in 0.64.0) |
| b_thinlto_cache_dir | (Internal build dir) | true, false | Specify where to store ThinLTO cache objects. (Added in 0.64.0) |
| b_ndebug | false | true, false, if-release | Disable asserts |
| b_pch | true | true, false | Use precompiled headers |
| b_pgo | off | off, generate, use | Use profile guided optimization |
| b_sanitize | none | see below | Code sanitizer to use |
| b_staticpic | true | true, false | Build static libraries as position independent |
| b_pie | false | true, false | Build position-independent executables (since 0.49.0) |
| b_vscrt | from_buildtype | none, md, mdd, mt, mtd, from_buildtype, static_from_buildtype | VS runtime library to use (since 0.48.0) (static_from_buildtype since 0.56.0) |
The default and possible values of sanitizers changed in 1.8. Before 1.8 they
were string values, and restricted to a specific subset of values: none,address, thread, undefined, memory, leak, or address,undefined. Inget_option('b_sanitize')
1.8 it was changed to a free form array of sanitizers, which are checked by a
compiler and linker check. For backwards compatibility reasons continues to return a string with the array values
separated by a comma. Furthermore:
- If the b_sanitize option is empty, the 'none' string is returned.
- If it contains only the values 'address' and 'undefined', they are'address,undefined'
always returned as the string, in this order.
- Otherwise, the array elements are returned in undefined order.
Be aware that b_lundef is true by default, which is incompatible with theb_lundef
address sanitizer when building shared libraries with clang, as documented
by clang
( makes meson use -Wl,--no-undefined, which is an alias for -Wl,-z,defs).
\* < 0 means disable, == 0 means automatic selection, > 0 sets a specific number to use
LLVM supports thin lto, for more discussion see LLVM's documentation
<a name="b_vscrt-from_buildtype"></a>
The default value of b_vscrt is from_buildtype. The following table isfrom_buildtype
used internally to pick the CRT compiler arguments for orstatic_from_buildtype (since 0.56) based on the value of the buildtype
option:
| buildtype | from_buildtype | static_from_buildtype |
| -------- | -------------- | --------------------- |
| debug | /MDd | /MTd |/MD
| debugoptimized | | /MT |/MD
| release | | /MT |/MD
| minsize | | /MT |
| custom | error! | error! |
Notes about Apple Bitcode support
b_bitcode will pass -fembed-bitcode while compiling and will pass-Wl,-bitcode_bundle while linking. These options are incompatibleb_asneeded
with , so that option will be silently disabled.
[[shared_module]]s will not have
bitcode embedded because -Wl,-bitcode_bundle is incompatible with-Wl,-undefined,dynamic_lookup which is necessary for shared modules to work.
Compiler options
Same caveats as base options above.
The following options are available. They can be set by passing
-Doption=value to meson. Note that both the options themselves and
the possible values they can take will depend on the target platform
or compiler being used:
| Option | Default value | Possible values | Description |
| ------ | ------------- | --------------- | ----------- |
| c_args | | free-form comma-separated list | C compile arguments to use |
| c_link_args | | free-form comma-separated list | C link arguments to use |
| c_std | none | none, c89, c99, c11, c17, c18, c2x, c23, c2y, gnu89, gnu99, gnu11, gnu17, gnu18, gnu2x, gnu23, gnu2y | C language standard to use |
| c_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against |
| c_thread_count | 4 | integer value ≥ 0 | Number of threads to use with emcc when using threads |
| cpp_args | | free-form comma-separated list | C++ compile arguments to use |
| cpp_link_args | | free-form comma-separated list | C++ link arguments to use |
| cpp_std | none | none, c++98, c++03, c++11, c++14, c++17, c++20 <br/>c++2a, c++1z, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z, <br/> gnu++2a, gnu++20, vc++14, vc++17, vc++20, vc++latest | C++ language standard to use |
| cpp_debugstl | false | true, false | C++ STL debug mode |
| cpp_eh | default | none, default, a, s, sc | C++ exception handling type |
| cpp_rtti | true | true, false | Whether to enable RTTI (runtime type identification) |
| cpp_thread_count | 4 | integer value ≥ 0 | Number of threads to use with emcc when using threads |
| cpp_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against |
| cpp_importstd | false | true or false | Whether to use import std |
| fortran_std | none | [none, legacy, f95, f2003, f2008, f2018] | Fortran language standard to use |
| rust_dynamic_std | false | true, false | Whether to link dynamically to the Rust standard library (Added in 1.9.0) |
| rust_nightly | auto | enabled, disabled, auto | Nightly Rust compiler (enabled=required, disabled=don't use nightly feature, auto=use nightly feature if available) (Added in 1.10.0) |
| cuda_ccbindir | | filesystem path | CUDA non-default toolchain directory to use (-ccbin) (Added in 0.57.1) |
The default values of c_winlibs and cpp_winlibs are in
compiler-specific argument forms, but the libraries are: kernel32,
user32, gdi32, winspool, shell32, ole32, oleaut32, uuid, comdlg32,
advapi32.
All these <lang>_* options are specified per machine. See below in
the specifying options per machine
section on how to do this in cross builds.
When using MSVC, cpp_eh=[value] will result in /EH[value] being passed.none
The magic value translates to s-c- to disable exceptions. *Sincedefault
0.51.0* translates to sc. When using gcc-style compilers, nothingcpp_eh=none
is passed (allowing exceptions to work), while passes-fno-exceptions.
Since 0.54.0 The <lang>_thread_count option can be used to control-s PTHREAD_POOL_SIZE
the value passed to when using emcc. No other
c/c++ compiler supports this option.
Since 0.63.0 all compiler options can be set per subproject, see
here for details on how the default value
is inherited from the main project. This is useful, for example, when the main
project requires C++11, but a subproject requires C++14. The cpp_std valuedefault_options
from the subproject's is now respected.
Since 1.3.0 c_std and cpp_std options now accept a list of values.default_options: 'c_std=gnu11,c11'
Projects that prefer GNU C, but can fallback to ISO C, can now set, for
example, , and it will use gnu11 whenc++17
available, but fallback to c11 otherwise. It is an error only if none of the
values are supported by the current compiler.
Likewise, a project that can take benefit of but can still build withc++11 can set default_options: 'cpp_std=c++17,c++11'.gnuXX
This allows us to deprecate values from the MSVC compiler. That meansdefault_options: 'c_std=gnu11'
that will now print a warning with MSVCc11
but fallback to . No warning is printed if at least onedefault_options: 'c_std=gnu11,c11'
of the values is valid, i.e. .c_std=gnu11
In the future that deprecation warning will become an hard error because should mean GNU is required, for projects that cannot be
built with MSVC for example.
Specifying options per machine
Since 0.51.0, some options are specified per machine rather than
globally for all machine configurations. Prefixing the option with
build. only affects the build machine configuration, while leaving it
unprefixed only affects the host machine configuration.
For example:
- build.pkg_config_path controls the paths pkg-config will searchnative: true
for (build machine) dependencies.
- pkg_config_path controls the paths pkg-config will search fornative: false
(host machine) dependencies.
This is useful for cross builds. In native builds, the build and host
machines are the same, and the unprefixed option alone will suffice.
Prior to 0.51.0, these options only affected native builds when
specified on the command line as there was no build. prefix.[properties]
Similarly named fields in the section of the cross file
would affect cross compilers, but the code paths were fairly different,
allowing differences in behavior to crop out.
Specifying options per subproject
Several built-in options and all compiler options can be defined per subproject.
This is useful, for example, when building shared libraries in the main project
and statically linking a subproject, or when the main project must build
with no warnings but some subprojects cannot.
Most of the time, this would be used either in the parent project by
setting subproject's default_options (e.g. subproject('foo',
default_options: 'default_library=static')), or by the user through the-Dfoo:default_library=static
command line: .
The value is overridden in this order:
- opt=value from parent project's default_optionsopt=value
- from subproject's default_optionsopt=value
- from machine fileopt=value
- from command linesubp:opt=value
- from parent project's default optionsopt=value
- from subproject() default_optionssubp:opt=value
- from machine filesubp:opt=value
- from command line
Old behavior
Between 0.54.0 and 1.7.x only a few options could be defined per subproject:
default_library and werror since 0.54.0*;
warning_level since 0.56.0*;
compiler options since 0.63.0*
The value was overridden in this order:
- opt=value from parent project's default_optionsopt=value
- from machine fileopt=value
- from command lineopt=value
- from subproject's default_optionssubp:opt=value
- from parent project's default optionsopt=value
- from subproject() default_optionssubp:opt=value
- from machine filesubp:opt=value
- from command line
In other word, the subproject's default_options had a higher priorityopt=value
than from machine file or command line.
Module options
Some Meson modules have built-in options. They can be set by prefixing the
option with the module's name:
-D<module>.<option>=<value> (e.g. -Dpython.platlibdir=/foo).
Pkgconfig module
| Option | Default value | Possible values | Description |
|-------------|---------------|-----------------|------------------------------------------------------------|
| relocatable | false | true, false | Generate the pkgconfig files as relocatable (Since 0.63.0) |
Since 0.63.0 The pkgconfig.relocatable option is used by thepkg.generate()
pkgconfig module–namely –andprefix
affects how the (not to be confused with thetrue
install prefix) in the generated pkgconfig file is set.
When it is , the prefix will be relative to the install_dir-thisfalse
allows the pkgconfig file to be moved around and still work, as long
as the relative path is not broken. In general, this allows for the whole
installed package to be placed anywhere on the system and still work as a
dependency. When it is set to , the prefix will be the same as
the install prefix.
An error will be raised if pkgconfig.relocatable is true and theinstall_dir for a generated pkgconfig file points outside the/usr
install prefix. For example: if the install prefix is and theinstall_dir for a pkgconfig file is /var/lib/pkgconfig.
Python module
| Option | Default value | Possible values | Description |
| ------ | ------------- | ----------------- | ----------- |
| bytecompile | 0 | integer from -1 to 2 | What bytecode optimization level to use (Since 1.2.0) |
| install_env | prefix | {auto,prefix,system,venv} | Which python environment to install to (Since 0.62.0) |
| platlibdir | | Directory path | Directory for site-specific, platform-specific files (Since 0.60.0) |
| purelibdir | | Directory path | Directory for site-specific, non-platform-specific files (Since 0.60.0) |
| allow_limited_api | true | true, false | Disables project-wide use of the Python Limited API (Since 1.3.0) |
| build_config | | File path | Specifies the Python build configuration file (PEP 739) (Since 1.10.0) |
Since 0.60.0 The python.platlibdir and python.purelibdir options are usedpython.install_sources()
by the python module methods andpython.get_install_dir(); Meson tries to detect the correct installation pathsprefix
and make them relative to the installation by default which will oftenprefix
result in the interpreter not finding the installed python modules unless is /usr on Linux, or, for instance, C:\Python39 on Windows. Theseprefix
options can be absolute paths outside of .
Since 0.62.0 The python.install_env option is used to detect the correctsystem
installation path. Setting to will avoid making the paths relative toprefix and instead use the global site-packages of the selected pythonvenv
interpreter directly, even if it is a venv. Setting to will instead useauto
the paths for the virtualenv the python found installation comes from (or fail
if it is not a virtualenv). Setting to will check if the foundvenv
installation is a virtualenv, and use or system as appropriate (butprefix
never ). Note that Conda environments are treated as system.platlibdir
This option is mutually exclusive with the /purelibdir.
For backwards compatibility purposes, the default install_env is prefix.
Since 1.2.0 The python.bytecompile option can be used to enable compiling
python bytecode. Bytecode has 3 optimization levels:
- 0, bytecode without optimizations
- 1, bytecode with some optimizations
- 2, bytecode with some more optimizations
To this, Meson adds level -1, which is to not attempt to compile bytecode at
all.
Since 1.3.0 The python.allow_limited_api option affects whether thelimited_api keyword argument of the extension_module method is respected.false
If set to , the effect of the limited_api argument is disabled.
---
Markdown/CMake Module
CMake module
Note: the functionality of this module is governed by Meson's
rules on mixing build systems.
This module provides helper tools for generating cmake package files.
It also supports the usage of CMake based subprojects, similar to
the normal Meson subprojects.
Usage
To use this module, just do: cmake = import('cmake'). The
following functions will then be available as methods on the object
with the name cmake. You can, of course, replace the name cmake
with anything else.
It is generally recommended to use the latest Meson version and
CMake >=3.17 for best compatibility. CMake subprojects will
usually also work with older CMake versions. However, this can
lead to unexpected issues in rare cases.
CMake subprojects
Using CMake subprojects is similar to using the "normal" Meson
subprojects. They also have to be located in the subprojects
directory.
Example:
add_library(cm_lib SHARED ${SOURCES})cmake = import('cmake')Configure the CMake project
sub_proj = cmake.subproject('libsimple_cmake')Fetch the dependency object
cm_lib = sub_proj.dependency('cm_lib')executable('exe1', ['sources'], dependencies: [cm_lib])
The subproject method is almost identical to the normal Meson
[[subproject]] function. The only difference is that a CMake project
instead of a Meson project is configured.
The returned sub_proj supports the same options as a "normal"
subproject. Meson automatically detects CMake build targets, which can
be accessed with the methods listed below.
It is usually enough to just use the dependency object returned by the
dependency() method in the build targets. This is almost identical
to using the [[declare_dependency]] object from a normal Meson subproject.
It is also possible to use executables defined in the CMake project as code
generators with the target() method:
add_executable(cm_exe ${EXE_SRC})cmake = import('cmake')Subproject with the "code generator"
sub_pro = cmake.subproject('cmCodeGen')Fetch the code generator exe
sub_exe = sub_pro.target('cm_exe')Use the code generator
generated = custom_target(
'cmake-generated',
input: [],
output: ['test.cpp'],
command: [sub_exe, '@OUTPUT@']
)It should be noted that not all projects are guaranteed to work. The
safest approach would still be to create a meson.build for the
subprojects in question.
Configuration options
New in meson 0.55.0
Meson also supports passing configuration options to CMake and overriding
certain build details extracted from the CMake subproject.
cmake = import('cmake')-DSOME_OTHER_VAR=ON
opt_var = cmake.subproject_options()Call CMake with
opt_var.add_cmake_defines({'SOME_OTHER_VAR': true})Globally override the C++ standard to c++11
opt_var.set_override_option('cpp_std', 'c++11')Override the previous global C++ standard
with c++14 only for the CMake target someLib
opt_var.set_override_option('cpp_std', 'c++14', target: 'someLib')sub_pro = cmake.subproject('someLibProject', options: opt_var)
Further changes to opt_var have no effect
See the CMake options object for a complete
reference of all supported functions.
The CMake configuration options object is very similar to the
[[@cfg_data]] object] object returned
by [[configuration_data]]. It
is generated by the subproject_options method.
All configuration options have to be set before the subproject is
configured and must be passed to the subproject method via theoptions key. Altering the configuration object won't have any effectcmake.subproject
on previous calls.
In earlier Meson versions CMake command-line parameters could be set
with the cmake_options kwarg. However, this feature is deprecatedoptions
since 0.55.0 and only kept for compatibility. It will not work
together with the kwarg.
subproject object
This object is returned by the subproject method described above
and supports the following methods:
- dependency(target) returns a dependency object for any CMake target. Theinclude_type
kwarg (new in 0.56.0) controls the include type of theinclude_directories(target)
returned dependency object similar to the same kwarg in the
[[dependency]] function.
- returns an array of Meson [[@inc]]target(target)
objects for the specified target. Using this method is not necessary
if the dependency object is used.
- returns the raw build target.target_type(target)
- returns the type of the target as a stringtarget_list()
- returns a list of all target names.get_variable(name)
- fetches the specified variable from insidedependency()
the subproject. Usually or target() should befound
preferred to extract build targets.
- returns true if the subproject is available, otherwise false
new in Meson 0.53.2
cmake options object
This object is returned by the subproject_options() method andoptions
consumed by the kwarg of the subproject method. The
following methods are supported:
- add_cmake_defines({'opt1': val1, ...}) add additional CMake commandline definesset_override_option(opt, val)
- set specific build optionsopt=val
for targets. This will effectively add to the override_optionsset_install(bool)
array of the [[build_target]]
- override whether targets should be installed or notappend_compile_args(lang, arg1, ...)
- append compile flags for a specificappend_link_args(arg1, ...)
language to the targets
- append linker args to the targetsclear()
- reset all data in the cmake options object
The methods set_override_option, set_install,append_compile_args and append_link_args support the optionaltarget kwarg. If specified, the set options affect the specific
target. The effect of the option is global for the subproject
otherwise.
If, for instance, opt_var.set_install(false) is called, no targetfoo
will be installed regardless of what is set by CMake. However, it is
still possible to install specific targets (here ) by setting thetarget kwarg: opt_var.set_install(true, target: 'foo')
Options that are not set won't affect the generated subproject. So, if
for instance, set_install was not called then the values extracted
from CMake will be used.
Cross compilation
New in 0.56.0
Meson will try to automatically guess most of the required CMake
toolchain variables from existing entries in the cross and native
files. These variables will be stored in an automatically generated
CMake toolchain file in the build directory. The remaining variables
that can't be guessed can be added by the user in the [cmake]
cross/native file section (new in 0.56.0).
Adding a manual CMake toolchain file is also supported with the
cmake_toolchain_file setting in the [properties] section. Directly-DCMAKE_TOOLCHAIN_FILE=/path/to/some/Toolchain.cmake
setting a CMake toolchain file with in themeson.build is not supported since the automatically generated
toolchain file is also used by Meson to inject arbitrary code into
CMake to enable the CMake subproject support.
The closest configuration to only using a manual CMake toolchain file
would be to set these options in the machine file:
[properties]cmake_toolchain_file = '/path/to/some/Toolchain.cmake'
cmake_defaults = false
[cmake]
No entries in this section
This will result in a toolchain file with just the bare minimum to
enable the CMake subproject support and include() thecmake_toolchain_file as the last instruction.
For more information see the cross and native file
specification.
CMake configuration files
cmake.write_basic_package_version_file()
This method is the equivalent of the corresponding CMake
function,
it generates a name package version file.
* name: the name of the package.version
* : the version of the generated package file.compatibility
* : a string indicating the kind of compatibility, the accepted values areAnyNewerVersion, SameMajorVersion, SameMinorVersion or ExactVersion.AnyNewerVersion
It defaults to . Depending on your cmake installation some kind ofarch_independent
compatibility may not be available.
: new in 0.62.0*, if true the generated package fileinstall_dir
will skip architecture checks. Useful for header-only libraries.
* : optional installation directory, it defaults to $(libdir)/cmake/$(name)
Example:
cmake = import('cmake')cmake.write_basic_package_version_file(name: 'myProject', version: '1.0.0')
cmake.configure_package_config_file()
This method is the equivalent of the corresponding CMake
function,
it generates a name package configuration file from the input@PACKAGE_INIT@
template file. Just like the cmake function in this file the statement will be replaced by the appropriate piecePATH_VARS
of cmake code. The equivalent argument is given throughconfiguration
the parameter.
* name: the name of the package.input
* : the template file where that will be treated for variable substitutions contained in configuration.install_dir
* : optional installation directory, it defaults to $(libdir)/cmake/$(name).configuration
* : a configuration_data object that will be used for variable substitution in the template file.
Since 0.62.0 it can take a dictionary instead.
Example:
meson.build:
cmake = import('cmake')conf = configuration_data()
conf.set_quoted('VAR', 'variable value')
cmake.configure_package_config_file(
name: 'myProject',
input: 'myProject.cmake.in',
configuration: conf
)
myProject.cmake.in:
@PACKAGE_INIT@set(MYVAR VAR)
---
Markdown/Code Formatting
---
short-description: Code formatting
...
clang-format
Since 0.50.0
When clang-format is installed and a .clang-format file is found at the mainclang-format
project's root source directory, Meson automatically adds a target
that reformat all C and C++ files (currently only with Ninja backend).
ninja -C builddir clang-formatSince 0.58.0
It is possible to restrict files to be reformatted with optional
.clang-format-include and .clang-format-ignore files.
The file .clang-format-include contains a list of patterns matching the files
that will be reformatted. The pattern matches this directory and all#
subdirectories recursively. Empty lines and lines starting with are ignored..clang-format-include
If is not found, the pattern defaults to /* which
means all files recursively in the source directory but has the disadvantage to
walk the whole source tree which could be slow in the case it contains lots of
files.
Example of .clang-format-include file:All files in src/ and its subdirectories
src//*All files in include/ but not its subdirectories
include/*
The file .clang-format-ignore contains a list of patterns matching the files
that will be excluded. Files matching the include list (see above) that match
one of the ignore pattern will not be reformatted. Unlike include patterns, ignore
patterns does not support and a single * match any characters including#
path separators. Empty lines and lines starting with are ignored.
The build directory and file without a well known C or C++ suffix are always
ignored.
Example of .clang-format-ignore file:Skip C++ files in src/ directory
src/*.cpp
Note that .clang-format-ignore has the same format as used byrun-clang-format.py.
A new target clang-format-check has been added. It returns an error code if
any file needs to be reformatted. This is intended to be used by CI.
Since 0.60.0
If .clang-format-include file is missing and source files are in a git
repository, only files tracked by git will be included.
---
Markdown/Codegen Module
---
short-description: Common Code Generators Module
authors:
- name: Dylan Baker
email: [email protected]
years: [2024, 2025]
...
Codegen Module
(New in 1.10.0)
This module provides wrappers around common code generators, such as flex/lex and yacc/bison. This purpose of this is to make it easier and more pleasant to use common code generators in a mesonic way.
Functions
lex()
lex_gen = codegen.lex(implementations : ['flex', 'reflex'], flex_version : ['>= 2.6', '< 3'], reflex_version : '!= 1.4.2')This function provides fine grained control over what implementation(s) and version(s) of lex are acceptable for a given project (These are set per-subproject). It returns a new object, which can be used to generate code.
It accepts the following keyword arguments:
- implementations: a string array of acceptable implementations to use. May include: lex, flex, reflex, or win_flex.lex_version
- : a string array of version constraints to apply to the lex binaryflex_version
- : a string array of version constraints to apply to the flex binaryreflex_version
- : a string array of version constraints to apply to the relex binarywin_flex_version
- : a string array of version constraints to apply to the win_flex binaryrequired
- : A boolean or feature optiondisabler
- : Return a disabler if not foundnative
- : Is this generator for the host or build machine?
yacc()
yacc = codegen.yacc(implementations : ['bison', 'win_bison'])This function provides fine grained controls over which implementation(s) and version(s) of the parser generator to use.
Accepts the following keyword arguments:
- implementations: a string array of acceptable implementations to use. May include: yacc, byacc, bison, or win_bison.yacc_version
- : a string array of version constraints to apply to the yacc binarybyacc_version
- : a string array of version constraints to apply to the byacc binarybison_version
- : a string array of version constraints to apply to the bison binarywin_bison_version
- : a string array of version constraints to apply to the win_bison binaryrequired
- : A boolean or feature optiondisabler
- : Return a disabler if not foundnative
- : Is this generator for the host or build machine?
Returned Objects
LexGenerator
#### lex.implementation
lex = codegen.lex()
impl = lex.implementation()Returns the string name of the lex implementation chosen. May be one of:
- lex
- flex
- reflex
- win_flex
#### lex.generate
lex = codegen.lex()
lex.generate('lexer.l')This function wraps flex, lex, reflex (but not RE/flex), and win_flex (on Windows). When using win_flex it will automatically add the --wincompat argument.
This requires an input file, which may be a string, File, or generated source. It additionally takes the following options keyword arguments:
- args: An array of extra arguments to pass the lexerplainname
- : If set to true then @PLAINNAME@ will be used as the source base, otherwise @BASENAME@.source
- : the name of the source output. If this is unset Meson will use {base}.{ext} with an extension of cpp if the input has an extension of .ll, or c otherwise, with base being determined by the plainname argument.header
- : The optional output name for a header file. If this is unset no header is addedtable
- : The optional output name for a table file. If this is unset no table will be generated
The outputs will be in the form source [header] [table], which means those can be accessed by indexing the output of the lex call:
lex = codegen.lex()
l1 = lex.generate('lexer.l', header : '@[email protected]', table : '@[email protected]')
headers = [l1[1], l1[2]] # [header, table]l2 = lex.generate('lexer.l', table : '@[email protected]')
table = l2[1]
YaccGenerator
#### yacc.implementation
yacc = codegen.yacc()
impl = yacc.implementation()Returns the string name of the yacc implementation chosen. May be one of:
- yacc
- bison
- byacc
- win_bison
#### yacc.generate
yacc = codegen.yacc()
yacc.generate('parser.y')This function wraps bison, yacc, byacc, and win_bison (on Windows), and attempts to abstract away the differences between them
This requires an input file, which may be a string, File, or generated source. It additionally takes the following options keyword arguments:
- version: Version constraints on the lexerargs
- : An array of extra arguments to pass the lexerplainname
- : If set to true then @PLAINNAME@ will be used as the source base, otherwise @BASENAME@.source
- : the name of the source output. If this is unset Meson will use {base}.{ext} with an extension of cpp if the input has an extension of .yy or c otherwise, with base being determined by the plainname argument.header
- : the name of the header output. If this is unset Meson will use {base}.{ext} with an extension of hpp if the input has an extension of .yy or h otherwise, with base being determined by the plainname argument.locations
- : The name of the locations file, if one is generated. Due to the way yacc works this must be duplicated in the file and in the command.
The outputs will be in the form source header [locations], which means those can be accessed by indexing the output of the yacc call:
yacc = codegen.yacc()
p1 = yacc.generate('parser.y', header : '@[email protected]', locations : 'locations.h')
headers = [p1[1], p1[2]] # [header, locations]p2 = yacc.generate('parser.yy', locations : 'locations.hpp')
locations = p2[1]
---
Markdown/Commands
Command-line commands
There are two different ways of invoking Meson. First, you can run it
directly from the source tree with the command
/path/to/source/meson.py. Meson may also be installed in which casemeson
the command is simply . In this manual we only use the latter
format for simplicity.
Meson is invoked using the following syntax:
meson [COMMAND] [COMMAND_OPTIONS]
This section describes all available commands and some of their
Optional arguments. The most common workflow is to run
setup, followed by compile, and then
install.
For the full list of all available options for a specific command use
the following syntax: meson COMMAND --help
configure
{{ configure_usage.inc }}
Changes options of a configured meson project.
{{ configure_arguments.inc }}
Most arguments are the same as in setup.
Note: reconfiguring project will not reset options to their default
values (even if they were changed in meson.build).
#### Examples:
List all available options:
meson configure builddirChange value of a single option:
meson configure builddir -Doption=new_valuecompile
(since 0.54.0)
{{ compile_usage.inc }}
Builds a default or a specified target of a configured Meson project.
{{ compile_arguments.inc }}
--verbose argument is available since 0.55.0.
#### Targets
(since 0.55.0)
TARGET has the following syntax [PATH/]NAME.SUFFIX[:TYPE], where:NAME
- : name of the target from meson.build (e.g. foo from executable('foo', ...)).SUFFIX
- : name of the suffix of the target from meson.build (e.g. exe from executable('foo', suffix: 'exe', ...)).PATH
- : path to the target relative to the root meson.build file. Note: relative path for a target specified in the root meson.build is ./.TYPE
- : type of the target. Can be one of the following: 'executable', 'static_library', 'shared_library', 'shared_module', 'custom', 'alias', 'run', 'jar'.
PATH, SUFFIX, and TYPE can all be omitted if the resulting TARGET can bemeson.build
used to uniquely identify the target in .
Note that SUFFIX did not exist prior to 1.3.0.
#### Backend specific arguments
(since 0.55.0)
BACKEND-args use the following syntax:
If you only pass a single string, then it is considered to have all
values separated by commas. Thus invoking the following command:
$ meson compile --ninja-args=-n,-d,explainwould add -n, -d and explain arguments to ninja invocation.
If you need to have commas or spaces in your string values, then you
need to pass the value with proper shell quoting like this:
$ meson compile "--ninja-args=['a,b', 'c d']"#### Examples:
Build the project:
meson compile -C builddirExecute a dry run on ninja backend with additional debug info:
meson compile --ninja-args=-n,-d,explainBuild three targets: two targets that have the same foo name, butbar
different type, and a target:
meson compile foo:shared_library foo:static_library barProduce a coverage html report (if available):
ninja coverage-htmldist
(since 0.52.0)
{{ dist_usage.inc }}
Generates a release archive from the current source tree.
{{ dist_arguments.inc }}
See notes about creating releases for more info.
#### Examples:
Create a release archive:
meson dist -C builddirinit
(since 0.45.0)
{{ init_usage.inc }}
Creates a basic set of build files based on a template.
{{ init_arguments.inc }}
#### Examples:
Create a project in sourcedir:meson init -C sourcedir
env2mfile
This command is experimental and subject to change.
{Since 0.62.0}
{{ env2mfile_usage.inc }}
Create native and cross files from the current environment, typically
by sniffing environment variables like CC and CFLAGS.
{{ env2mfile_arguments.inc }}
#### Examples:
Autodetect the current cross build environment:
meson env2mfile --cross -o current_cross.txt --cpu=arm7a --cpu-family=arm --system=linuxGenerate a cross build using Debian system information:
meson env2mfile --cross --debarch=armhf -o deb_arm_cross.txtintrospect
{{ introspect_usage.inc }}
Displays information about a configured Meson project.
{{ introspect_arguments.inc }}
#### Examples:
Display basic information about a configured project in builddir:
meson introspect builddir --projectinfoinstall
(since 0.47.0)
{{ install_usage.inc }}
Installs the project to the prefix specified in setup.
{{ install_arguments.inc }}
See the installation documentation for more info.
#### Examples:
Install project to prefix:meson install -C builddir
Install project to $DESTDIR/prefix:DESTDIR=/path/to/staging/area meson install -C builddir
Since 0.60.0 DESTDIR and --destdir can be a path relative to build
directory. An absolute path will be set into environment when executing scripts.
reprotest
(since 1.6.0)
{{ reprotest_usage.inc }}
Simple reproducible build tester that compiles the project twice and
checks whether the end results are identical.
This command must be run in the source root of the project you want to
test.
{{ reprotest_arguments.inc }}
#### Examples
meson reprotest
Builds the current project with its default settings.
meson reprotest --intermediaries -- --buildtype=debugoptimized
Builds the target and also checks that all intermediate files like
object files are also identical. All command line arguments after the
-- are passed directly to the underlying meson invocation. Only
use option arguments, i.e. those that start with a dash, Meson sets
directory arguments automatically.
rewrite
(since 0.50.0)
{{ rewrite_usage.inc }}
Modifies the Meson project.
{{ rewrite_arguments.inc }}
See the Meson file rewriter documentation for more info.
setup
{{ setup_usage.inc }}
Configures a build directory for the Meson project.
Deprecated since 0.64.0: This is the default Meson command (invoked if there
was no COMMAND supplied). However, supplying the command is necessary to avoid
clashes with future added commands, so "setup" should be used explicitly.
Since 1.1.0 --reconfigure is allowed even if the build directory does not
already exist, that argument is ignored in that case.
Since 1.3.0 If the build directory already exists, options are updated with
their new value given on the command line (-Dopt=value). Unless --reconfiguremeson configure <builddir> -Dopt=value
is also specified, this won't reconfigure immediately. This has the same behaviour
as .
Since 1.3.0 It is possible to clear the cache and reconfigure in a single command
with meson setup --clearcache --reconfigure <builddir>.
{{ setup_arguments.inc }}
See Meson introduction
page for more info.
#### Examples:
Configures builddir with default values:meson setup builddir
subprojects
(since 0.49.0)
{{ subprojects_usage.inc }}
Manages subprojects of the Meson project. Since 0.59.0 commands are run on
multiple subprojects in parallel by default, use --num-processes=1 if it is
not desired.
Since 0.64.0 the update subcommand will not download new wrap filesmeson wrap update
from WrapDB any more. Use command for that instead.
{{ subprojects_arguments.inc }}
test
{{ test_usage.inc }}
Run tests for the configure Meson project.
{{ test_arguments.inc }}
See the unit test documentation for more info.
Since 1.2.0 you can use wildcards in args for test names.
For example, "bas*" will match all test with names beginning with "bas".
Since 1.2.0 it is an error to provide a test name or wildcard that
does not match any test.
#### Examples:
Run tests for the project:
meson test -C builddirRun only specific_test_1 and specific_test_2:meson test -C builddir specific_test_1 specific_test_2
wrap
{{ wrap_usage.inc }}
An utility to manage WrapDB dependencies.
{{ wrap_arguments.inc }}
See the WrapDB tool documentation for more info.
devenv
(since 0.58.0)
{{ devenv_usage.inc }}
Runs a command, or open interactive shell if no command is provided, with
environment setup to run project from the build directory, without installation.
We automatically handle bash and set $PS1 accordingly. If the automatic $PS1$MESON_DISABLE_PS1_OVERRIDE
override is not desired (maybe you have a fancy custom prompt), set the environment variable and use $MESON_PROJECT_NAME
when setting the custom prompt, for example with a snippet like the following:
...
if [[ -n "${MESON_PROJECT_NAME-}" ]];
then
PS1+="[ ${MESON_PROJECT_NAME} ]"
fi
...These variables are set in environment in addition to those set using [[meson.add_devenv]]:
- MESON_DEVENV is defined to '1'.MESON_PROJECT_NAME
- is defined to the main project's name.PKG_CONFIG_PATH
- includes the directory where Meson generates -uninstalled.pcPATH
files.
- includes every directory where there is an executable that would bebindir
installed into . On windows it also includes every directory where thereLD_LIBRARY_PATH
is a DLL needed to run those executables.
- includes every directory where there is a shared library thatlibdir
would be installed into . This allows to run system application usingDYLD_LIBRARY_PATH
custom build of some libraries. For example running system GEdit when building
GTK from git. On OSX the environment variable is andPATH
on Windows.GI_TYPELIB_PATH
- includes every directory where a GObject Introspectiongnome.generate_gir()
typelib is built. This is automatically set when using .GSETTINGS_SCHEMA_DIR
- Since 0.59.0 includes every directory where a GSettingsgnome.compile_schemas()
schemas is compiled. This is automatically set when using .gnome.compile_schemas()
Note that this requires GLib >= 2.64 when is used inQEMU_LD_PREFIX
more than one directory.
- Since 1.0.0 is set to the sys_root value from cross fileXDG_DATA_DIRS
when cross compiling and that property is defined.
- Since 1.11.0 if not set in user's environment, the default value/usr/local/share:/usr/share
is set before adding project paths.XDG_CONFIG_DIRS
- Since 1.11.0 if not set in user's environment, the default value/etc/xdg
is set before adding project paths.
Since 0.62.0 if bash-completion scripts are being installed and the
shell is bash, they will be automatically sourced.
Since 0.62.0 when GDB helper scripts (-gdb.py, -gdb.gdb, and *-gdb.csm)
are installed with a library name that matches one being built, Meson adds the
needed auto-load commands into <builddir>/.gdbinit file. When running gdb fromPYTHONPATH
top build directory, that file is loaded by gdb automatically. In the case of
python scripts that needs to load other python modules, may needmeson.add_devenv()
to be modified using .
Since 0.63.0 when cross compiling for Windows WINEPATH is used insteadPATH
of which allows running Windows executables using wine. Note that sinceWINEPATH size is currently limited to 1024 characters, paths relative to the
root of build directory are used. That means current workdir must be the root of
build directory when running wine.
Since 1.1.0 meson devenv --dump [<filename>] command takes an optional
filename argument to write the environment into a file instead of printing to
stdout.
Since 1.1.0 --dump-format argument has been added to select which shellsh
format should be used. There are currently 3 formats supported:
- : Lines are in the format VAR=/prepend:$VAR:/append.export
- : Same as sh but with extra export VAR lines.vscode
- : Same as sh but without $VAR substitution because they do not
seems to be properly supported by vscode.
{{ devenv_arguments.inc }}
format
(since 1.5.0)
{{ format_usage.inc }}
Format specified meson.build documents. For compatibility with muon, fmtformat
is an alias to .
{{ format_arguments.inc }}
The configuration file is a .ini file. If a meson.format file existsmeson.format
beside the provided build file to analyze, and no configuration file is
provided on the command line, the file is automatically used.
If no build file is provided on the command line, the meson.build file in
current directory is analyzed.
The following options are recognized:
- max_line_length (int): When an array, a dict, a function or a method
would be longer that this, it is formatted one argument per line
(Default is 80).
- indent_by (str): Indentation to use (Default is four spaces ' ').[]
- space_array (bool): Whether to add spaces between and array--output
arguments (default is false).
- kwargs_force_multiline (bool): If true, arguments are formatted one per
line as soon as there is a keyword argument (default is false).
- wide_colon (bool): If true, a space is placed before colon in dict
and in keyword arguments (default is false).
- no_single_comma_function (bool): If true, a comma is never appended
to function arguments if there is only one argument, even if
using multiline arguments (default is false).
- end_of_line ('cr', 'lf', 'crlf', 'native'): Line ending to use
(applied when using or --inline argument) (default' '
is 'native).
- indent_before_comments (str): Indentation to use before inline comments
(default is two spaces ).meson.build
- simplify_string_literals (bool): When true, multiline strings are
converted to single line strings if they don't contain newlines.
Formatted strings are converted to normal strings if they don't
contain substitutions (default is true).
- insert_final_newline (bool): If true, force the fileindent_by
to end with a newline character (default is true).
- tab_width (int): Width of tab stops, used to compute line length
when uses tab characters (default is 4).files()
- sort_files (bool): When true, arguments of function are--
sorted (default was true before 1.11.0; since 1.11.0 it is false).
Since 1.11.0, arguments are sorted
naturally rather than
alphabetically.
- group_arg_value (bool): When true, string argument with prefix--
followed by string argument without prefix are grouped on the
same line, in multiline arguments (default is false).
- use_editor_config (bool): When true, also uses config from .editorconfig .
The first six options are the same than for the muon fmt command.
It is also possible to use a .editorconfig file, by providing--editor-config
the option on the command line, or with theuse_editor_config option in the config file.
When --recursive option is specified, meson.build files fromsubdir are also analyzed (must be used in conjunction with --inplace--check-only
or option).
Since 1.7.0 You can use - as source file name to read source from standard--recursive
input instead of reading it from a file. This cannot be used with --inline
or arguments.
Since 1.9.0 Using - as source file with --editor-config now requires--source-file-path argument to ensure consistent results.
Since 1.10.0 When --check-diff is specified, instead of silently exitingmeson format
with an error code, will print a diff of the formatting changes.
#### Differences with muon fmt
The meson format command should be compatible with the muon fmt command.
However, it has more features, and some differences:
- By default, meson format put two spaces before inline comments,muon fmt
while only puts one.muon fmt
- can potentially mix crlf and lf end-of-lines, as it is not awaremeson format
of them. will always be consistent in the output it produces.muon fmt
- only recognize the indent_by option from .editorconfig files.meson format
also recognizes max_line_length, end_of_line,insert_final_newline
and tab_width options.meson format
- has many additional format rules (see option list above).
---
Markdown/Comparisons
---
title: Comparisons
...
Comparing Meson with other build systems
A common question is *Why should I choose Meson over a different build
system X?* There is no one true answer to this as it depends on the
use case. Almost all build systems have all the functionality needed
to build medium-to-large projects so the decision is usually made on
other points. Here we list some pros and cons of various build systems
to help you do the decision yourself.
GNU Autotools
Pros
Excellent support for legacy Unix platforms, large selection of
existing modules.
Cons
Needlessly slow, complicated, hard to use correctly, unreliable,
painful to debug, incomprehensible for most people, poor support for
non-Unix platforms (especially Windows).
CMake
Pros
Great support for multiple backends (Visual Studio, XCode, etc).
Cons
The scripting language is cumbersome to work with. Some simple things
are more complicated than necessary.
SCons
Pros
Full power of Python available for defining your build.
Cons
Slow. Requires you to pass your configuration settings on every
invocation. That is, if you do scons OPT1 OPT2 and then justscons, it will reconfigure everything without settings OPT1 andOPT2. Every other build system remembers build options from the
previous invocation.
Bazel
Pros
Proven to scale to very large projects.
Cons
Implemented in Java. Poor Windows support. Heavily focused on Google's
way of doing things (which may be a good or a bad thing). Contributing
code requires signing a CLA.
Meson
Pros
The fastest build system see
measurements, user friendly, designed to
be as invisible to the developer as possible, native support for
modern tools (precompiled headers, coverage, Valgrind etc). Not Turing
complete so build definition files are easy to read and understand.
Cons
Relatively new so it does not have a large user base yet, and may thus
contain some unknown bugs. Visual Studio and XCode backends not as
high quality as Ninja one.
---
Markdown/Compiler Properties
Compiler properties
Not all compilers and platforms are alike. Therefore Meson provides
the tools to detect properties of the system during configure time. To
get most of this information, you first need to extract the *compiler
object* from the main
meson variable.
compiler = [[#meson.get_compiler]]('c')Here we extract the C compiler. We could also have given the argument
cpp to get the C++ compiler, objc to get the objective C compiler
and so on. The call is valid for all languages specified in the
project declaration. Trying to obtain some other compiler will lead
to an unrecoverable error.
System information
This is a bit complex and more thoroughly explained on the page on
cross compilation. But if you just want to
know the operating system your code will run on, issue this command:
host_machine.system()Compiler id
The compiler object method [[compiler.get_id]] returns a
lower case string describing the "family" of the compiler. Since 0.53.0
[[compiler.get_linker_id]] returns a lower case string with the linker name. Since
compilers can often choose from multiple linkers depending on operating
system, get_linker_id can be useful for handling or mitigating effects
of particular linkers.
The compiler object also has a method [[compiler.get_argument_syntax]] which
returns a lower case string of gcc, msvc, or another undefined stringgcc
value; identifying whether the compiler arguments use the same syntax as
either or msvc, or that its arguments are not like either. This should
only be used to select the syntax of the arguments, such as those to test
with [[compiler.has_argument]].
See reference tables for a list of
supported compiler ids and their argument type.
Does code compile?
Sometimes the only way to test the system is to try to compile some
sample code and see if it works. For example, this can test that a
"C++17" compiler actually supports a particular C++17 feature,
without resorting to maintaining a feature list vs. compiler vendor,
compiler version and operating system.
Testing that a code snippet runs is a two-phase operation. First
we define some code using the multiline string operator:
code = '''#include<stdio.h>
void func() { printf("Compile me.\n"); }
'''Then we can run the test.
result = [[#compiler.compiles]](code, name : 'basic check')The variable result will now contain either true or falsename
depending on whether the compilation succeeded or not. The keyword
argument is optional. If it is specified, Meson will write the
result of the check to its log.
Does code compile and link?
Sometimes it is necessary to check whether a certain code fragment not
only compiles, but also links successfully, e.g. to check if a symbol
is actually present in a library. This can be done using the
[[compiler.links]] method like this:
code = '''#include<stdio.h>
void func() { printf("Compile me.\n"); }
'''Then we can run the test.
result = [[#compiler.links]](code, args : '-lfoo', name : 'link check')The variable result will now contain either true or falsename
depending on whether the compilation and linking succeeded or not. The
keyword argument is optional. If it is specified, Meson will
write the result of the check to its log.
Compile and run test application
Here is how you would compile and run a small test application.
Testing if a code snippets runs versus merely that it links
is particularly important for some dependencies such as MPI.
code = '''#include<stdio.h>
int main(int argc, char argv) {
printf("%s\n", "stdout");
fprintf(stderr, "%s\n", "stderr");
return 0;
}
'''
result = [[#compiler.run]](code, name : 'basic check')The result variable encapsulates the state of the test, which can bename
extracted with the following methods. The keyword argumentcompiles
works the same as with .
| Method | Return value |
| ------ | ------------ |
| compiled | True if compilation succeeded. If false then all other methods return undefined values. |
| returncode | The return code of the application as an integer |
| stdout | Program's standard out as text. |
| stderr | Program's standard error as text. |
Here is an example usage:
if result.stdout().strip() == 'some_value'
# do something
endifDoes a header exist?
Header files provided by different platforms vary quite a lot. Meson
has functionality to detect whether a given header file is available
on the system. The test is done by trying to compile a simple test
program that includes the specified header. The following snippet
describes how this feature can be used.
if [[#compiler.has_header]]('sys/fstat.h')
# header exists, do something
endifExpression size
Often you need to determine the size of a particular element (such as
int, wchar_t or char*). Using the compiler variable mentioned
above, the check can be done like this.
wcharsize = [[#compiler.sizeof]]('wchar_t', prefix : '#include<wchar.h>')This will put the size of wchar_t as reported by sizeof intowcharsize
variable . The keyword argument prefix is optional. If#include
specified its contents is put at the top of the source file. This
argument is typically used for setting directives in
configuration files.
In older versions (<= 0.30) Meson would error out if the size could
not be determined. Since version 0.31 it returns -1 if the size could
not be determined.
Does a function exist?
Just having a header doesn't say anything about its contents.
Sometimes you need to explicitly check if some function exists. This
is how we would check whether the function open_memstream exists instdio.h
header
if [[#compiler.has_function]]('open_memstream', prefix : '#include <stdio.h>')
# function exists, do whatever is required.
endifNote that, on macOS programs can be compiled targeting older macOS
versions than the one that the program is compiled on. It can't be
assumed that the OS version that is compiled on matches the OS version
that the binary will run on.
Therefore when detecting function availability with [[compiler.has_function]], it
is important to specify the correct header in the prefix argument.
In the example above, the function open_memstream is detected, which-mmacosx-version-min=10.11
was introduced in macOS 10.13. When the user builds on macOS 10.13,
but targeting macOS 10.11 (), this will
correctly report the function as missing. Without the header however,
it would lack the necessary availability information and incorrectly
report the function as available.
Is a macro defined?
Macro detection can often be useful to determine if non-standard features
are supported on your target platform. Fortunately, Meson makes it
easy to check if a macro is defined:
if [[#compiler.has_define]]('__SIZEOF_INT128__')
# macro is defined, do whatever is required
endifDoes a structure contain a member?
Some platforms have different standard structures. Here's how one
would check if a struct called mystruct from header myheader.hsome_member
contains a member called .
if [[#compiler.has_member]]('struct mystruct', 'some_member', prefix : '#include<myheader.h>')
# member exists, do whatever is required
endifType alignment
Most platforms can't access some data types at any address. For
example it is common that a char can be at any address but a 32 bit
integer only at locations which are divisible by four. Determining the
alignment of data types is simple.
int_alignment = [[#compiler.alignment]]('int') # Will most likely contain the value 4.Has argument
This method tests if the compiler supports a given command line
argument. This is implemented by compiling a small file with the given
argument.
has_special_flags = [[#compiler.has_argument]]('-Wspecialthing')Note: some compilers silently swallow command line arguments they do
not understand. Thus this test cannot be made 100% reliable.
---
Markdown/Conference Presentations
Conference presentations on Meson
- FOSDEM 2014, Introducing the Meson build
system
(jpakkane)
- LCA 2015, Making build systems not
suck (jpakkane)
- GUADEC 2015, Improving the way Gnome apps are
built (jpakkane)
- GStreamer conference 2015, Done in 6.0
seconds
(jpakkane)
- LCA 2016, Builds, dependencies and deployment in the modern
multiplatform world
(jpakkane)
- GUADEC 2016, Making your GNOME app compile 2.4x
faster
(nirbheek)
- Libre Application Summit 2016, New world, new
tools (jpakkane)
- GStreamer conference 2016, GStreamer Development on Windows and
faster builds everywhere with
Meson
(tpm)
---
Markdown/Configuration
---
short-description: Build-time configuration options
...
Configuration
If there are multiple configuration options, passing them through
compiler flags becomes very burdensome. It also makes the
configuration settings hard to inspect. To make things easier, Meson
supports the generation of configure files. This feature is similar to
one found in other build systems such as CMake.
Suppose we have the following Meson snippet:
conf_data = [[#configuration_data]]
conf_data.set('version', '1.2.3')
[[#configure_file]](input : 'config.h.in',
output : 'config.h',
configuration : conf_data)and that the contents of config.h.in are
#define VERSION_STR "@version@"Meson will then create a file called config.h in the corresponding
build directory whose contents are the following.
#define VERSION_STR "1.2.3"More specifically, Meson will find all strings of the type @varname@conf_data
and replace them with respective values set in . You canconfiguration_data
use a single object as many times as you like,configure_file
but it becomes immutable after being passed to the set
function. That is, after it has been used once to generate output the function becomes unusable and trying to call it causes an error.configuration_data
Copy of immutable is still immutable.
For more complex configuration file generation Meson provides a second
form. To use it, put a line like this in your configuration file.
#mesondefine TOKEN
The replacement that happens depends on what the value and type of TOKEN is:
#define TOKEN // If TOKEN is set to boolean true.
#undef TOKEN // If TOKEN is set to boolean false.
#define TOKEN 4 // If TOKEN is set to an integer or string value.
/ undef TOKEN / // If TOKEN has not been set to any value.Note that if you want to define a C string, you need to do the quoting
yourself like this:
conf_data.set('TOKEN', '"value"')Since this is such a common operation, Meson provides a convenience
method:
plain_var = 'value'
conf_data.set_quoted('TOKEN', plain_var) # becomes #define TOKEN "value"Often you have a boolean value in Meson but need to define the C/C++
token as 0 or 1. Meson provides a convenience function for this use
case.
conf_data.set10(token, boolean_value)
The line above is equivalent to this:
if boolean_value
conf_data.set(token, 1)
else
conf_data.set(token, 0)
endifConfiguring without an input file
If the input file is not defined then Meson will generate a header
file with all the entries in the configuration data object. The
replacements are the same as when generating #mesondefine entries:
conf_data.set('FOO', '"string"') => #define FOO "string"
conf_data.set('FOO', 'a_token') => #define FOO a_token
conf_data.set('FOO', true) => #define FOO
conf_data.set('FOO', false) => #undef FOO
conf_data.set('FOO', 1) => #define FOO 1
conf_data.set('FOO', 0) => #define FOO 0In this mode, you can also specify a comment which will be placed
before the value so that your generated files are self-documenting.
conf_data.set('BAR', true, description : 'Set BAR if it is available')Will produce:
/ Set BAR if it is available /
#define BARDealing with file encodings
The default Meson file encoding to configure files is utf-8. If you
need to configure a file that is not utf-8 encoded the encoding
keyword will allow you to specify which file encoding to use. It is
however strongly advised to convert your non utf-8 file to utf-8
whenever possible. Supported file encodings are those of python3, see
standard-encodings.
Using dictionaries
Since 0.49.0 [[configuration_data]] takes an optional dictionary as
first argument. If provided, each key/value pair is added into the
configuration_data as if set() method was called for each of them.configuration
[[configure_file]]'s kwarg also accepts a dictionary
instead of a configuration_data object.
Example:
cdata = configuration_data({
'STRING' : '"foo"',
'INT' : 42,
'DEFINED' : true,
'UNDEFINED' : false,
})configure_file(output : 'config1.h',
configuration : cdata,
)
configure_file(output : 'config2.h',
configuration : {
'STRING' : '"foo"',
'INT' : 42,
'DEFINED' : true,
'UNDEFINED' : false,
}
)
A full example
Generating and using a configuration file requires the following steps:
- generate the file
- create an include directory object for the directory that holds the file
- use it in a target
We are going to use the traditional approach of generating a header
file in the top directory. The common name is config.h but we're
going to use an unique name. This avoids the problem of accidentally
including the wrong header file when building a project with many
subprojects.
At the top level we generate the file:
conf_data = configuration_data()
Set data
configure_file(input : 'projconfig.h.in',
output : 'projconfig.h',
configuration : conf_data)Immediately afterwards we generate the include object.
configuration_inc = include_directories('.')Finally we specify this in a target that can be in any subdirectory.
executable(..., include_directories : configuration_inc)Now any source file in this target can include the configuration
header like this:
#include<projconfig.h>---
Markdown/Configuring A Build Directory
---
short-description: Configuring a pre-generated build directory
...
Configuring a build directory
Often you want to change the settings of your build after it has been
generated. For example you might want to change from a debug build
into a release build, set custom compiler flags, change the build
options provided in your meson.options file and so on.
The main tool for this is the meson configure command.
You invoke meson configure by giving it the location of your build
dir. If omitted, the current working directory is used instead. Here's
a sample output for a simple project.
Core properties
Source dir /home/jpakkane/clangdemo/2_address
Build dir /home/jpakkane/clangdemo/2_address/buildmeson
Core options:
Option Current Value Possible Values Description
------ ------------- --------------- -----------
auto_features auto [enabled, disabled, auto] Override value of all 'auto' features
backend ninja [ninja, vs, vs2010, vs2015, vs2017, vs2019, vs2022, xcode] Backend to use
buildtype release [plain, debug, debugoptimized, release, minsize, custom] Build type to use
debug false [true, false] Debug
default_library shared [shared, static, both] Default library type
install_umask 0022 [preserve, 0000-0777] Default umask to apply on permissions of installed files
layout mirror [mirror, flat] Build directory layout
optimization 3 [plain, 0, g, 1, 2, 3, s] Optimization level
prefer_static false [true, false] Whether to try static linking before shared linking
strip false [true, false] Strip targets on install
unity off [on, off, subprojects] Unity build
warning_level 1 [0, 1, 2, 3, everything] Compiler warning level to use
werror false [true, false] Treat warnings as errors
Backend options:
Option Current Value Possible Values Description
------ ------------- --------------- -----------
backend_max_links 0 >=0 Maximum number of linker processes to run or 0 for no limit
Base options:
Option Current Value Possible Values Description
------ ------------- --------------- -----------
b_asneeded true [true, false] Use -Wl,--as-needed when linking
b_colorout always [auto, always, never] Use colored output
b_coverage false [true, false] Enable coverage tracking.
b_lto false [true, false] Use link time optimization
b_lundef true [true, false] Use -Wl,--no-undefined when linking
b_ndebug false [true, false, if-release] Disable asserts
b_pch true [true, false] Use precompiled headers
b_pgo off [off, generate, use] Use profile guided optimization
b_sanitize none [none, address, thread, undefined, leak, memory, address,undefined] Code sanitizer to use
b_staticpic true [true, false] Build static libraries as position independent
Compiler options:
Option Current Value Possible Values Description
------ ------------- --------------- -----------
c_args [] Extra arguments passed to the C compiler
c_link_args [] Extra arguments passed to the C linker
c_std c99 [none, c89, c99, c11, c17, c18, c2x, c23, c2y, gnu89, gnu99, gnu11, gnu17, gnu18, gnu2x, gnu23, gnu2y] C language standard to use
cpp_args [] Extra arguments passed to the C++ compiler
cpp_debugstl false [true, false] STL debug mode
cpp_link_args [] Extra arguments passed to the C++ linker
cpp_std c++11 [none, c++98, c++03, c++11, c++14, c++17, c++1z, c++2a, c++20, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z, gnu++2a, gnu++20] C++ language standard to use
fortran_std [] [none, legacy, f95, f2003, f2008, f2018] language standard to use
Directories:
Option Current Value Description
------ ------------- -----------
bindir bin Executable directory
datadir share Data file directory
includedir include Header file directory
infodir share/info Info page directory
libdir lib/x86_64-linux-gnu Library directory
libexecdir libexec Library executable directory
localedir share/locale Locale data directory
localstatedir /var/local Localstate data directory
mandir share/man Manual page directory
prefix /usr/local Installation prefix
sbindir sbin System executable directory
sharedstatedir /var/local/lib Architecture-independent data directory
sysconfdir etc Sysconf data directory
Project options:
Option Current Value Possible Values Description
------ ------------- --------------- -----------
array_opt [one, two] [one, two, three] array_opt
combo_opt three [one, two, three] combo_opt
free_array_opt [one, two] free_array_opt
integer_opt 3 >=0, <=5 integer_opt
other_one false [true, false] other_one
some_feature enabled [enabled, disabled, auto] some_feature
someoption optval An option
Testing options:
Option Current Value Possible Values Description
------ ------------- --------------- -----------
errorlogs true [true, false] Whether to print the logs from failing tests
stdsplit true [true, false] Split stdout and stderr in test logs
These are all the options available for the current project arranged
into related groups. The first column in every field is the name of
the option. To set an option you use the -D option. For example,/usr/local
changing the installation prefix from to /tmp/testroot
you would issue the following command.
meson configure -Dprefix=/tmp/testroot
Then you would run your build command (usually meson compile), which
would cause Meson to detect that the build setup has changed and do
all the work required to bring your build tree up to date.
Since 0.50.0, it is also possible to get a list of all build options
by invoking meson configure with the
project source directory or the path to the root meson.build. In
this case, Meson will print the default values of all options similar
to the example output from above.
Per project subproject options rewrite (Since 1.8)
A common requirement when building large projects with many
subprojects is to build some (or all) subprojects with project options
that are different from the "main project". This has been sort of
possible in a limited way but is now natively supported. Per project
options can be added, changed and removed at runtime using the command
line, in other words, without editing existing meson.build files.
Starting with version 1.8 you can specify per-project option settings.
These can be specified for every top level (i.e. not project) options.
Suppose you have a project that has a single subproject called
numbercruncher that does heavy computation. During development you
want to build that subproject with optimizations enabled but your main
project without optimizations. This can be done by specifying a custom
value to the given subproject:
meson configure -Dnumbercruncher:optimization=3
Another case might be that you want to build with warnings as errors,
but some subproject does not support it. To configure werror per
subproject you can do:
meson configure -Dwerror=true -Dnaughty:werror=false
You can also specify a different value on the top level project. For
example you could enable optimizations on all subprojects but not the
top level project:
meson configure -Doptimization=2 -D:optimization=0
Note the colon after the second D.
Subproject specific values can be removed with -U
meson configure -Usubproject:optionnname
---
Markdown/Contact Information
Contact information
For general discussion and questions, it is strongly recommended that
you use the mailing
list.
If you find bugs, please file them in the issue
tracker.
The maintainer of Meson is Jussi Pakkanen. You should usually not
contact him privately but rather use the channels listed above.
However if such a need arises, he can be reached at gmail where his
username is jpakkane (that is not a typo, the last letter is indeed
e).
---
Markdown/Continuous Integration
Continuous Integration
Here you will find snippets to use Meson with various CI such as
Travis and AppVeyor.
Please file an issue
if these instructions don't work for you.
Travis-CI with Docker
Travis with Docker gives access to newer non-LTS Ubuntu versions with
pre-installed libraries of your choice.
This yml file is derived from the
configuration used by Meson
for running its own tests.
os:
- linux
- osxlanguage:
- cpp
services:
- docker
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python3 ninja; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then pip3 install meson; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull YOUR/REPO:eoan; fi
script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo FROM YOUR/REPO:eoan > Dockerfile; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo ADD . /root >> Dockerfile; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker build -t withgit .; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && TRAVIS=true CC=$CC CXX=$CXX meson setup builddir && meson test -C builddir"; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) meson setup builddir && meson test -C builddir; fi
CircleCI for Linux host (with custom Docker images)
CircleCi can work for spinning all of the
Linux images you wish. Here's a sample yml file for use with that.
/ Detailed source-code truncated for AI context efficiency. /CircleCI for Linux host (without custom Docker images)
This CircleCI configuration defines two jobs, build-linux and build-macos,build
within a workflow named . The build-linux job utilizes a Docker imagebuild-macos
with Python 3.12.3, while runs on macOS with Xcode 15.3.0. Each
job involves checking out the code, installing Meson and Ninja, configuring the
project, compiling it, and running tests using Meson.
version: 2.1jobs:
build-linux:
docker:
- image: cimg/python:3.12.3
steps:
- checkout
- run:
name: Install Meson and Ninja
command: |
python -m pip install --user meson ninja
- run:
name: Configure Project
command: |
meson setup builddir
- run:
name: Compile Project
command: |
meson compile -C builddir
- run:
name: Run Tests
command: |
meson test -C builddir
build-macos:
macos:
xcode: 15.3.0
steps:
- checkout
- run:
name: Install Meson and Ninja
command: |
python -m pip install meson ninja
- run:
name: Configure Project
command: |
meson setup builddir
- run:
name: Compile Project
command: |
meson compile -C builddir
- run:
name: Run Tests
command: |
meson test -C builddir
workflows:
version: 2.1
build:
jobs:
- build-linux
- build-macos
AppVeyor for Windows
For CI on Windows, AppVeyor has a wide
selection of default
configurations.
AppVeyor also has
MacOS and
Linux CI
images. This is a sample appveyor.yml file for Windows with Visual
Studio 2017, 2019, and 2022.
version: 1.0.{build}
image:
- Visual Studio 2022
- Visual Studio 2019
- Visual Studio 2017install:
- cmd: python -m pip install meson ninja
build_script:
- cmd: >-
meson setup builddir
meson compile -C builddir
test_script:
- cmd: meson test -C builddir
Qt
For Qt 5, add the following line near the PYTHON_ROOT assignment:
- cmd: if %arch%==x86 (set QT_ROOT=C:\Qt\5.11\%compiler%) else (set QT_ROOT=C:\Qt\5.11\%compiler%_64)And afterwards add %QT_ROOT%\bin to the PATH variable.
You might have to adjust your build matrix as there are, for example,
no msvc2017 32-bit builds. Visit the Build
Environment page in
the AppVeyor docs for more details.
Boost
The following statement is sufficient for Meson to find Boost:
- cmd: set BOOST_ROOT=C:\Libraries\boost_1_67_0GitHub Actions
GitHub Actions provides a versatile platform for continuous integration
(CI). This example workflow file, ci_meson.yml, is tailored for C-based
projects utilizing GCC on Linux, macOS, and Windows. Triggered by changes
to C code files, it automates building and testing processes using different
versions of Meson (1.0.0, 1.1.0, 1.2.0, 1.3.0, 1.4.0) across various operating
systems. Each job in the workflow handles checkout, dependency installation,
project configuration, test execution, and optional test log uploads upon
failure.
name: CI Mesonon:
push:
paths:
- ".c"
- ".h"
pull_request:
paths:
- ".c"
- ".h"
jobs:
build:
name: Build and Test on ${{ matrix.os }} with Meson v${{ matrix.meson_version }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
meson_version: ["1.2.0", "1.3.0", "1.4.0"]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: python -m pip install meson==${{ matrix.meson_version }} ninja
- name: Configure Project
run: meson setup builddir/
env:
CC: gcc
- name: Run Tests
run: meson test -C builddir/ -v
- name: Upload Test Log
uses: actions/upload-artifact@v4
if: failure()
with:
name: ${{ matrix.os }}_Meson_Testlog
path: builddir/meson-logs/testlog.txt
---
Markdown/Contributing
---
short-description: Contributing to Meson
...
Contributing to Meson
A large fraction of Meson is contributed by people outside the core
team. This documentation explains some of the design rationales of
Meson as well as how to create and submit your patches for inclusion
to Meson.
Thank you for your interest in participating to the development.
Submitting patches
All changes must be submitted as pull requests to
GitHub. This causes them
to be run through the CI system. All submissions must pass a full CI
test run before they are even considered for submission.
Keeping pull requests up to date
It is possible that while your pull request is being reviewed, other
changes are committed to master that cause merge conflicts that must
be resolved. The basic rule for this is very simple: keep your pull
request up to date using rebase _only_.
Do not merge head back to your branch. Any merge commits in your pull
request make it not acceptable for merging into master and you must
remove them.
Special procedure for new features
Every new feature requires some extra steps, namely:
- Must include a project test under test cases/, or if that's notrun_unittests.py
possible or if the test requires a special environment, it must go
into .docs/markdown/snippets/
- Must be registered with the FeatureChecks
framework
that will warn the user if they try to use a new feature while
targeting an older Meson version.
- Needs a release note snippet inside with
a heading and a brief paragraph explaining what the feature does
with an example.
Acceptance and merging
The kind of review and acceptance any merge proposal gets depends on
the changes it contains. All pull requests must be reviewed and
accepted by someone with commit rights who is not the original
submitter. Merge requests can be roughly split into three different
categories.
The first one consists of MRs that only change the markdown
documentation under docs/markdown. Anyone with access rights can
push changes to these directly to master. For major changes it is
still recommended to create a MR so other people can comment on it.
The second group consists of merges that don't change any
functionality, fixes to the CI system and bug fixes that have added
regression tests (see below) and don't change existing
functionality. Once successfully reviewed anyone with merge rights can
merge these to master.
The final kind of merges are those that add new functionality or
change existing functionality in a backwards incompatible way. These
require the approval of the project lead.
In a simplified list form the split would look like the following:
- members with commit access can do:
- documentation changes (directly to master if warranted)
- bug fixes that don't change functionality
- refactorings
- new dependency types
- new tool support (e.g. a new Doxygen-kind of tool)
- support for new compilers to existing languages
- project leader decision is needed for:
- new modules
- new functions in the Meson language
- syntax changes for Meson files
- changes breaking backwards compatibility
- support for new languages
A green CI run is mandatory for merging
No merge request may be merged until it has a fully green CI run. It
does not matter why CI fails, it is a hard blocker. Even if the MR
could possibly not have anything to do with the failure and clearly
should be permitted, it may not be merged. Only MRs that fix the CI
issue are allowed to land in trunk.
There is one, and only one, exception to this. At the time of writing
the Apple CI is unreliable and sometimes fails with clock skew errors.
If a merge causes CI failure any developer can revert it out of
master. It is then the responsibility of the original submitter to
resubmit a fixed version.
Strategy for merging pull requests to trunk
Meson's merge strategy should fulfill the following guidelines:
- preserve as much history as possible
- have as little junk in the repo as possible
- everything in the "master lineage" should always pass all tests
These goals are slightly contradictory so the correct thing to do
often requires some judgement on part of the person doing the
merge. GitHub provides three different merge options, The rules of
thumb for choosing between them goes like this:
- single commit pull requests should always be rebased
- a pull request with one commit and one "fixup" commit (such as
testing something to see if it passes CI) should be squashed
- large branches with many commits should be merged with a merge
commit, especially if one of the commits does not pass all tests
(which happens in e.g. large and difficult refactorings)
If in doubt, ask for guidance on IRC.
Tests
All new features must come with automatic tests that thoroughly prove
that the feature is working as expected. Similarly bug fixes must come
with a unit test that demonstrates the bug, proves that it has been
fixed and prevents the feature from breaking in the future.
Sometimes it is difficult to create a unit test for a given bug. If
this is the case, note this in your pull request. We may permit bug
fix merge requests in these cases. This is done on a case by case
basis. Sometimes it may be easier to write the test than convince the
maintainers that one is not needed. Exercise judgment and ask for help
in problematic cases.
The tests are split into two different parts: unit tests and full
project tests. To run all tests, execute ./run_tests.py. Unit tests./run_unittests.py
can be run with and project tests with./run_project_tests.py.
Project tests
Subsets of project tests can be selected with
./run_project_tests.py --only option. This can save a great deal ofFC=ifort
time when only a certain part of Meson is being tested.
For example, a useful and easy contribution to Meson is making
sure the full set of compilers is supported. One could for example test
various Fortran compilers by setting , FC=flang orFC=flang-new or similar with ./run_project_test.py --only fortran../run_project_tests.py --only cuda --backend ninja
Some families of tests require a particular backend to run.
For example, all the CUDA project tests run and pass on Windows via
Each project test is a standalone project that can be compiled on its
own. They are all in the test cases subdirectory. The simplest way to./meson.py test\
run a single project test is to do something like
cases/common/1\ trivial builddir. The one exception to this is test
cases/unit directory discussed below.
The test cases in the common subdirectory are meant to be run alwaystest cases/frameworks
for all backends. They should only depend on C and C++, without any
external dependencies such as libraries. Tests that require those are
in the directory. If there is a need for an
external program in the common directory, such as a code generator, it
should be implemented as a Python script. The goal of test projects is
also to provide sample projects that end users can use as a base for
their own projects.
All project tests follow the same pattern: they are configured,
compiled, tests are run and finally install is run. Passing means that
configuring, building and tests succeed and that installed files match
those expected.
Any tests that require more thorough analysis, such as checking that
certain compiler arguments can be found in the command line or that
the generated pkg-config files actually work should be done with a
unit test.
Additionally:
* crossfile.ini and nativefile.ini are passed to the configure step with--cross-file and --native-file options, respectively.
* mlog.cmd_ci_include() can be called from anywhere inside Meson to
capture the contents of an additional file into the CI log on failure.
Projects needed by unit tests are in the test cases/unit./run_project_tests.py
subdirectory. They are not run as part of .
Configuring project tests
The (optional) test.json file, in the root of a test case, is usedtest.json
for configuring the test. All of the following root entries in the
are independent of each other and can be combined as needed.
Example test.json:
{
"env": {
"VAR": "VAL"
},
"installed": [
{ "type": "exe", "file": "usr/bin/testexe" },
{ "type": "pdb", "file": "usr/bin/testexe" },
{ "type": "shared_lib", "file": "usr/lib/z", "version": "1.2.3" },
],
"matrix": {
"options": {
"opt1": [
{ "val": "abc" },
{ "val": "qwert" },
{ "val": "bad" }
],
"opt2": [
{ "val": null },
{ "val": "true" },
{ "val": "false" },
]
},
"exclude": [
{ "opt1": "qwert", "opt2": "false" },
{ "opt1": "bad" }
]
},
"tools": {
"cmake": ">=3.11"
}
}#### env
The env key contains a dictionary which specifies additional
environment variables to be set during the configure step of the test.
There is some basic support for configuring the string with the @<VAR>@ syntax:
- @ROOT@: absolute path of the source directory@PATH@
- : current value of the PATH env variable
#### installed
The installed dict contains a list of dicts, describing which files are expected
to be installed. Each dict contains the following keys:
- filetype
- platform
- (optional)version
- (optional)language
- (optional)
The file entry contains the relative path (from the install root) to the
actually installed file.
The type entry specifies how the file path should be interpreted based on the
current platform. The following values are currently supported:
| type | Description |
| ------------- | ------------------------------------------------------------------------------------------------------- |
| file | No postprocessing, just use the provided path |python_file
| | Use the provided path while replacing the python directory. |dir
| | To include all files inside the directory (for generated docs, etc). The path must be a valid directory |exe
| | For executables. On Windows the .exe suffix is added to the path in file |shared_lib
| | For shared libraries, always written as name. The appropriate suffix and prefix are added by platform |python_lib
| | For python libraries, while replacing the python directory. The appropriate suffix is added by platform |pdb
| | For Windows PDB files. PDB entries are ignored on non Windows platforms |implib
| | For Windows import libraries. These entries are ignored on non Windows platforms |py_implib
| | For Windows import libraries. These entries are ignored on non Windows platforms |implibempty
| | Like implib, but no symbols are exported in the library |expr
| | file is an expression. This type should be avoided and removed if possible |
Except for the file, python_file and expr types, all paths should be provided without a suffix.
| Argument | Applies to | Description |
| -----------|----------------------------|-------------------------------------------------------------------------------|
| version | shared_lib, pdb | Sets the version to look for appropriately per-platform |language
| | pdb | Determines which compiler/linker determines the existence of this file |
The shared_lib and pdb types takes an optional additionalversion
parameter, , this is us a string in X.Y.Z format that will
be applied to the library. Each version to be tested must have a
single version. The harness will apply this correctly per platform:
The python_file, python_lib, and py_implib types have basic support for configuring the string with the @<VAR>@ syntax:
- @PYTHON_PLATLIB@: python get_install_dir directory relative to prefix@PYTHON_PURELIB@
- : python get_install_dir(pure: true) directory relative to prefix
pdb takes an optional language argument. This determines which
compiler/linker should generate the pdb file. Because it's possible to
mix compilers that do and don't generate pdb files (dmd's optlink
doesn't). Currently this is only needed when mixing D and C code.
{
"type": "shared_lib", "file": "usr/lib/lib",
"type": "shared_lib", "file": "usr/lib/lib", "version": "1",
"type": "shared_lib", "file": "usr/lib/lib", "version": "1.2.3.",
}This will be applied appropriately per platform. On windows this
expects lib.dll and lib-1.dll. on MacOS it expects liblib.dylibliblib.1.dylib
and . On other Unices it expects liblib.so,liblib.so.1, and liblib.so.1.2.3.
If the platform key is present, the installed file entry is onlyplatform
considered if the platform matches. The following values for are currently supported:
| platform | Description |
| ---------- | -------------------------------------------------------------------- |
| msvc | Matches when a msvc like compiler is used (msvc, clang-cl, etc.) |gcc
| | Not msvc |cygwin
| | Matches when the platform is cygwin |!cygwin
| | Not cygwin |windows
| | Matches when the platform is windows or cygwin |!windows
| | Not windows |
#### matrix
The matrix section can be used to define a test matrix to run
project tests with different Meson options.
In the options dict, all possible options and their values areoptions
specified. Each key in the dict is a Meson option. It stores
a list of all potential values in a dict format.
Each value must contain the val key for the value of the option.null can be used for adding matrix entries without the current
option.
The skip_on_env key (as described below) may be used in the value to skip that
matrix entry, based on the current environment.
The expect_skip_on_jobname and expect_skip_on_os keys (as described below)
may be used to expect that the test will be skipped, based on the current environment.
Similarly, the compilers key can be used to define a mapping of
compilers to languages that are required for this value.
{
"compilers": {
"c": "gcc",
"cpp": "gcc",
"d": "gdc"
}
}Specific option combinations can be excluded with the excludeexclude
section. It should be noted that does not require exactexclude
matches. Instead, any matrix entry containing all option value
combinations in will be excluded. Thus an empty dict ({})
to will match all elements in the test matrix.
The above example will produce the following matrix entries:
- opt1=abcopt1=abc opt2=true
- opt1=abc opt2=false
- opt1=qwert
- opt1=qwert opt2=true
-
#### do_not_set_opts
Currently supported values are:
- prefixlibdir
-
#### tools
This section specifies a dict of tool requirements in a simple
key-value format. If a tool is specified, it has to be present in the
environment, and the version requirement must be fulfilled. Otherwise,
the entire test is skipped (including every element in the test
matrix).
#### stdout
The stdout key contains a list of dicts, describing the expected
stdout.
Each dict contains the following keys:
- linematch
- (optional)count
- (optional)
Each item in the list is matched, in order, against the remaining
actual stdout lines, after any previous matches. If the actual stdout
is exhausted before every item in the list is matched, the expected
output has not been seen, and the test has failed.
The match element of the dict determines how the line element is
matched:
| Type | Description |
| -------- | ----------------------- |
| literal | Literal match (default) |re
| | regex match |
The count element determines how many times the line is expected, and allowed,
to be in the output. If unspecified, it must appear "any number of times, but at
least once".
#### skip_on_env
The skip_on_env key can be used to specify a list of environment variables. Ifskip_on_env
at least one environment variable in the list is present, the test
is skipped.
#### expect_skip_on_jobname
The expect_skip_on_jobname key contains a list of strings. If the MESON_CI_JOBNAMEMESON_SKIP_TEST
environment variable is set, and any of them are a sub-string of it, the test is
expected to be skipped (that is, it is expected that the test will output, because the CI environment is not one in which it can run,
for whatever reason).
The test is failed if it either skips unexpectedly or runs unexpectedly.
#### expect_skip_on_os
The expect_skip_on_os key can be used to specify a list of OS names (or their!
negations, prefixed with a ). If at least one item in the expect_skip_on_os list
is matched, the test is expected to be skipped.
The test is failed if it either skips unexpectedly or runs unexpectedly.
Skipping integration tests
Meson uses several continuous integration testing systems that have
slightly different interfaces for indicating a commit should be
skipped.
Continuous integration systems currently used:
- Azure Pipelines
allows NO_CI in the commit message.
- Sider
runs Flake8 (see below)
To promote consistent naming policy, use:
- [skip ci] in the commit title if you want to disable all
integration tests
Documentation
The docs directory contains the full documentation that will be used
to generate the Meson web site. Line length
in most cases should not exceed 70 characters (lines containing links
or examples are usually exempt). Every change in functionality must
change the documentation pages. In most cases this means updating the
reference documentation page but bigger changes might need changes in
other documentation, too.
All new functionality needs to have a mention in the release
notes. These features should be written in standalone files in the
docs/markdown/snippets directory. The release manager will combine
them into one page when doing the release.
Python Coding style
Meson follows the basic Python coding style. Additional rules are the
following:
- indent 4 spaces, no tabs ever
- indent meson.build files with two spaces
- try to keep the code as simple as possible
- contact the mailing list before embarking on large scale projects
to avoid wasted effort
Meson uses Flake8 for style guide enforcement. The Flake8 options for
the project are contained in .flake8.
To run Flake8 on your local clone of Meson:
$ python3 -m pip install flake8
$ cd meson
$ flake8To run it automatically before committing:
$ flake8 --install-hook=git
$ git config --bool flake8.strict trueC/C++ coding style
Meson has a bunch of test code in several languages. The rules for
those are simple.
- indent 4 spaces, no tabs ever
- brace always on the same line as if/for/else/function definition
Dependency support policy
The goal of Meson is to be as easily usable as possible. The user
experience should be "get Python3 and Ninja, run", even on
Windows.
Additionally, Meson is popularly used in many core infrastructure packages in a
Unix (and particularly, Linux) userland. This includes:
- package managers, such as pacman (Arch Linux) and portage (Gentoo)
- init systems (systemd, openrc, dinit)
- graphics stacks (xorg, wayland, libdrm, Mesa, gtk)
As such it needs to be able to run early on when bootstrapping a system from
scratch.
Python
We will always support all non EOL versions of CPython. Yes, there are people
out there using and depending on every old version of python. In fact, there
are people using and depending on systems that had a brand new python at the
time of release, but with a much longer support cycle than Python itself. We
need to balance the tradeoff between supporting those systems and being able to
improve our own codebase and code quality.
Meson will also be honest about what versions of python it supports. When a
version of CPython becomes EOL, it becomes eligible to be removed from our
support policy. We cannot guarantee continued support forever for software that
is not supported by its own developers, even if some deprecated LTS systems out
there still ship it. However, that doesn't mean we will drop support for those
versions simply because they are old. If we are not using new functionality
from new python versions, we will continue to mark Meson as compatible with the
older version -- and test it in CI!
(Note that contrary to popular belief, it is actually easier to test support
for very old versions of python than it is to drop support for it. We already
have the CI setup necessary for testing. Upgrading the CI to use newer versions
of python, on the other hand, represents mildly painful administrative work
that has to be done.)
So, in order to start requiring a newer version of python, one should check a
few factors:
- are the older versions being dropped, already EOL? Python EOL chart
- document the new minimum version of corresponding OSes
- rationalize the benefit of the change in terms of improvements to development
and maintenance of Meson. What new language features will be unlocked by the
upgrade, that Meson will be able to make good use of? Not every version has
new features requiring an upgrade, and not every new feature is so great we
need to drop everything to use it
External dependencies
Unfortunately this also means that we can't have dependencies on
projects outside of Python's standard library. This applies only to
core functionality, though. For additional helper programs etc the use
of external dependencies may be ok. If you feel that you are dealing
with this kind of case, please contact the developers first with your
use case.
Turing completeness
The main design principle of Meson is that the definition language is
not Turing complete. Any change that would make Meson Turing complete
is automatically rejected. In practice this means that defining your
own functions inside meson.build files and generalised loops will
not be added to the language.
Do I need to sign a CLA in order to contribute?
No you don't. All contributions are welcome.
No lingering state
Meson operates in much the same way as functional programming
languages. It has inputs, which include meson.build files, values of
options, compilers and so on. These are passed to a function, which
generates output build definition. This function is pure, which means that:
- for any given input the output is always the same
- running Meson twice in a row _always_ produce the same output in both runs
The latter one is important, because it enforces that there is no way
for "secret state" to pass between consecutive invocations of
Meson. This is the reason why, for example, there is no set_optionget_option
function even though there is a one.
If this were not the case, we could never know if the build output is
"stable". For example suppose there were a set_option function and aflipflop
boolean variable . Then you could do this:
set_option('flipflop', not get_option('flipflop'))This piece of code would never converge. Every Meson run would change
the value of the option and thus the output you get out of this build
definition would be random.
Meson does not permit this by forbidding these sorts of covert
channels.
There is one exception to this rule. Users can call into external
commands with run_command. If the output of that command does not
behave like a pure function, this problem arises. Meson does not try
to guard against this case, it is the responsibility of the user to
make sure the commands they run behave like pure functions.
Environment variables
Environment variables are like global variables, except that they are
also hidden by default. Envvars should be avoided whenever possible,
all functionality should be exposed in better ways such as command
line switches.
Random design points that fit nowhere else
- All features should follow the 90/9/1 rule. 90% of all use cases
should be easy, 9% should be possible and it is totally fine to not
support the final 1% if it would make things too complicated.
- Any build directory will have at most two toolchains: one native and
one cross.
- Prefer specific solutions to generic frameworks. Solve the end
user's problems rather than providing them tools to do it
themselves.
- Never use features of the Unix shell (or Windows shell for that
matter). Doing things like forwarding output with > or invoking&&
multiple commands with are not permitted. Whenever these sorts
of requirements show up, write an internal Python script with the
desired functionality and use that instead.
---
Markdown/Creating Linux Binaries
---
short-description: Creating universal Linux binaries
...
Creating Linux binaries
Creating Linux binaries that can be downloaded and run on any distro
(like .dmg packages for OSX or .exe installers for Windows) has
traditionally been difficult. This is even more tricky if you want to
use modern compilers and features, which is especially desired in game
development. There is still no simple turn-key solution for this
problem but with a bit of setup it can be relatively straightforward.
Installing system and GCC
First you need to do a fresh operating system install. You can use
spare hardware, VirtualBox, cloud or whatever you want. Note that the
distro you install must be at least as old as the oldest release you
wish to support. Debian stable is usually a good choice, though
immediately after its release you might want to use Debian oldstable
or the previous Ubuntu LTS. The oldest supported version of CentOS is
also a good choice.
Once you have installed the system, you need to install
build-dependencies for GCC. In Debian-based distros this can be done
with the following commands:
$ apt-get build-dep g++
$ apt-get install pkg-config libgmp-dev libmpfr-dev libmpc-devThen create a src subdirectory in your home directory. Copy-pasteinstall_gcc.sh
the following into and execute it.
#!/bin/shwget ftp://ftp.fu-berlin.de/unix/languages/gcc/releases/gcc-4.9.2/gcc-4.9.2.tar.bz2
tar xf gcc-4.9.2.tar.bz2
mkdir objdir
cd objdir
../gcc-4.9.2/configure --disable-bootstrap --prefix=${HOME}/devroot \
--disable-multilib --enable-languages=c,c++
make -j 4
make install-strip
ln -s gcc ${HOME}/devroot/bin/cc
Then finally add the following lines to your .bashrc.
$ export LD_LIBRARY_PATH=${HOME}/devroot/lib
$ export PATH=${HOME}/devroot/bin:$PATH
$ export PKG_CONFIG_PATH=${HOME}/devroot/lib/pkgconfigLog out and back in and now your build environment is ready to use.
Adding other tools
Old distros might have too old versions of some tools. For Meson this
could include Python 3 and Ninja. If this is the case you need to
download, build and install new versions into ~/devroot in the usual
way.
Adding dependencies
You want to embed and statically link every dependency you can
(especially C++ dependencies). Meson's Wrap package
manager might be of use here. This
is equivalent to what you would do on Windows, OSX, Android etc.
Sometimes static linking is not possible. In these cases you need to
copy the .so files inside your package. Let's use SDL2 as an example.
First we download and install it as usual giving it our custom install
prefix (that is, ./configure --prefix=${HOME}/devroot). This makes
Meson's dependency detector pick it up automatically.
Building and installing
Building happens in much the same way as normally. There are just two
things to note. First, you must tell GCC to link the C++ standard
library statically. If you don't then your app is guaranteed to break
as different distros have binary-incompatible C++ libraries. The
second thing is that you need to point your install prefix to some
empty staging area. Here's the Meson command to do that:
$ LDFLAGS=-static-libstdc++ meson --prefix=/tmp/myapp <other args>The aim is to put the executable in /tmp/myapp/bin and shared/tmp/myapp/lib
libraries to . The next thing you need is thelibSDL2-2.0.so.0
embedder. It takes your dependencies (in this case only) and copies them in the lib directory. Depending onldd binary_file
your use case you can either copy the files by hand or write a script
that parses the output of . Be sure not to copylibc
system libraries (, libpthread, libm etc). For an example,
see the sample
project.
Make the script run during install with this:
[[#meson.add_install_script]]('linux_bundler.sh')Final steps
If you try to run the program now it will most likely fail to start or
crashes. The reason for this is that the system does not know that the
executable needs libraries from the lib directory. The solution formyapp.sh
this is a simple wrapper script. Create a script called
with the following content:
#!/bin/bashcd "${0%/*}"
export LD_LIBRARY_PATH="$(pwd)/lib"
bin/myapp
Install it with this Meson snippet:
[[#install_data]]('myapp.sh', install_dir : '.')And now you are done. Zip up your /tmp/myapp directory and you havemyapp.sh
a working binary ready for deployment. To run the program, just unzip
the file and run .
---
Markdown/Creating OSX Packages
---
short-description: Tools to create OS X packages
...
Creating OSX packages
Meson does not have native support for building OSX packages but it
does provide all the tools you need to create one yourself. The reason
for this is that it is a very hard task to write a system that
provides for all the different ways to do that but it is very easy to
write simple scripts for each application.
Sample code for this can be found in the Meson manual test
suite.
Creating an app bundle
OSX app bundles are actually extremely simple. They are just a
directory of files in a certain format. All the details you need to
know are on this
page
and it is highly recommended that you read it first.
Let's assume that we are creating our app bundle into
/tmp/myapp.app. Suppose we have one executable, so we need toContents/MacOS
install that into . If we define the executable like
this:
executable('myapp', 'foo1.c', ..., install : true)then we just need to initialize our build tree with this command:
$ meson --prefix=/tmp/myapp.app \
--bindir=Contents/MacOS \
builddir \
<other flags you might need>Now when we do meson install the bundle is properly staged. If youContents/Resources
have any resource files or data, you need to install them into either by custom install commands or specifying
more install paths to the Meson command.
Next we need to install an Info.plist file and an icon. For those we
need the following two Meson definitions.
install_data('myapp.icns', install_dir : 'Contents/Resources')
install_data('Info.plist', install_dir : 'Contents')The format of Info.plist can be found in the link or the sampleicns
project linked above. The simplest way to get an icon in the tiff2icns
format is to save your image as a tiff an then use the helper
application that comes with XCode.
Some applications assume that the working directory of the app process
is the same where the binary executable is. If this is the case for
you, then you need to create a wrapper script that looks like this:
#!/bin/bashcd "${0%/*}"
./myapp
install it with this:
install_data('myapp.sh', install_dir : 'Contents/MacOS')and make sure that you specify myapp.sh as the executable to run inInfo.plist
your .
If you are not using any external libraries, this is all you need to
do. You now have a full app bundle in /tmp/myapp.app that you can
use.
External libraries
Most applications use third party frameworks and libraries.
If it is the case for your project, you need to add them to
the bundle so it will work on other peoples' machines.
As an example we are going to use the SDL2
framework. In order to bundle it in our app, we first specify an
installer script to run.
[[#meson.add_install_script]]('install_script.sh')The install script does two things. First it copies the whole
framework into our bundle.
$ mkdir -p ${MESON_INSTALL_PREFIX}/Contents/Frameworks
$ cp -R /Library/Frameworks/SDL2.framework \
${MESON_INSTALL_PREFIX}/Contents/FrameworksThen it needs to alter the library search path of our
executable(s). This tells OSX that the libraries your app needs are
inside your bundle. In the case of SDL2, the invocation goes like
this:
$ install_name_tool -change @rpath/SDL2.framework/Versions/A/SDL2 \
@executable_path/../FrameWorks/SDL2.framework/Versions/A/SDL2 \
${MESON_INSTALL_PREFIX}/Contents/MacOS/myappThis is the part of OSX app bundling that you must always do
manually. OSX dependencies come in many shapes and forms and
unfortunately there is no reliable automatic way to determine how each
dependency should be handled. Frameworks go to the Frameworks.dylib
directory while plain files usually go toContents/Resources/lib (but you can put them wherever you like). Tootool -L /path/to/binary
get this done you have to check what your program links against with and manually add the copy and fix steps to
your install script. Do not copy system libraries inside your bundle,
though.
After this you have a fully working, self-contained OSX app bundle
ready for distribution.
#### Qt
Qt offers a deployment tool,
called macdeployqt, that automates bundling Qt's libraries in your application folder and.dmg
optionally create the final installer
myapp.appcd into the folder that contains the
folder
macdeployqt myapp.app -executable=myapp.app/Contents/MacOS/myapp
This copies the needed Qt libraries to the correct subfolders within myapp.app.-executable=myapp.app/Contents/MacOS/myapp
The argument ismyapp.app/Contents/MacOS/myapp
to automatically alter the search path of the executable for the Qt libraries. One can also pass the -dmg.dmg
argument to create a installer from the updated myapp.app folder.
More information is available on the tool's documentation page.
Creating a .dmg installer
A .dmg installer is similarly quite simple, at its core it is
basically a fancy compressed archive. A good description can be found
on this page. Please read it
and create a template image file according to its instructions.
The actual process of creating the installer is very simple: you mount
the template image, copy your app bundle in it, unmount it and convert
the image into a compressed archive. The actual commands to do this
are not particularly interesting, feel free to steal them from either
the linked page above or from the sample script in Meson's test suite.
Putting it all together
There are many ways to put the .dmg installer together and different
people will do it in different ways. The linked sample code does it by
having two different scripts. This separates the different pieces
generating the installer into logical pieces.
install_script.sh only deals with embedding dependencies and fixing
the library paths.
build_osx_installer.sh sets up the build with the proper paths,
compiles, installs and generates the .dmg package.
The main reasoning here is that in order to build a complete OSX
installer package from source, all you need to do is to cd into the
source tree and run ./build_osx_installer.sh. To build packages onbuild_windows_installer.bat
other platforms you would write scripts such as and so on.
---
Markdown/Creating Releases
---
short-description: Creating releases
...
Creating releases
In addition to development, almost all projects provide periodical
source releases. These are standalone packages (usually either in
tar or zip format) of the source code. They do not contain any
revision control metadata, only the source code. Meson provides
a simple way of generating these, with the meson dist command.
Meson provides a simple way of generating these. It consists of a
single command (available since 0.52.0):
meson distor alternatively (on older Meson versions with ninja backend):
ninja distThis creates a file called projectname-version.tar.xz in the buildmeson-dist
tree subdirectory . This archive contains the fullcompile
contents of the latest commit in revision control including all the
submodules (recursively). All revision control metadata is removed.
Meson then takes this archive and tests that it works by doing a full + test + install cycle. If all these pass, Meson willSHA-256
then create a checksum file next to the archive.
Modifying the dist directory before creating the archive
Modification to the checked out files like generating files or
setting version info can be done with dist scripts:
[[#meson.add_dist_script]]('distscript.sh')Autotools dist VS Meson dist
Meson behaviour is different from Autotools. The Autotools "dist"
target packages up the current source tree. Meson packages the latest
revision control commit. The reason for this is that it prevents
developers from doing accidental releases where the distributed
archive does not match any commit in revision control (especially the
one tagged for the release).
Include subprojects in your release
The meson dist command has --include-subprojects command line--wrap-mode=nodownload
option. When enabled, the source tree of all subprojects used by the
current build will also be included in the final tarball. This is
useful to distribute self contained tarball that can be built offline
(i.e. ).
Skip build and test with --no-tests
The meson dist command has a --no-tests option to skip build and
tests steps of generated packages. It can be used to not waste time
for example when done in CI that already does its own testing.
So with --no-tests you can tell Meson "Do not build and test generated
packages.".
Use --allow-dirty to override error when git repository contains uncommitted changes
Since 0.62.0 Instead of emitting a warning when a repository contains
uncommitted changes, Meson will produce an error message notifying the
user and immediately exit. If --allow-dirty is given as an option tomeson dist, a warning will be emitted instead and Meson will proceed
as usual.
Release a subproject separately
Since 0.57.0 the meson dist command can now create a distribution tarballsubprojects/mysub
for a subproject in the same git repository as the main project. This can be
useful if parts of the project (e.g. libraries) can be built and distributed
separately. In that case they can be moved into and runningmeson dist in that directory will now create a tarball containing only the
source code from that subdir and not the rest of the main project or other
subprojects.
For example:
git clone https://github.com/myproject
cd myproject/subprojects/mysubproject
meson setup builddir
meson dist -C builddirThis produces builddir/meson-dist/mysubproject-1.0.tar.xz
tarball.Cement a version obtained from VCS
Since 1.4.0 the
meson dist command enables rewriting the build
configuration of the distribution tarball. This is needed when the
configuration depends on metadata from revision control such as in the
following example.meson.build:
mesonproject('tig', 'c',
version : run_command('version.sh', 'get-vcs').stdout().strip())meson.add_dist_script('version.sh', 'set-dist', meson.project_version())
version.sh:
sh#!/bin/shif [ "$1" = "get-vcs" ]; then
git -C "$MESON_SOURCE_ROOT" describe --always --dirty
elif [ "$1" = "set-dist" ]; then
$MESONREWRITE --sourcedir="$MESON_PROJECT_DIST_ROOT" kwargs set project / version "$2"
else
exit 1
fi
---
Markdown/Cross Compilation
---
short-description: Setting up cross-compilation
...
Cross compilation
Meson has full support for cross compilation through the use of
a cross build definition file. An minimal example of one such
file
x86_64-w64-mingw32.txt for a GCC/MinGW cross compiler
targeting 64-bit Windows could be:ini[binaries]
c = 'x86_64-w64-mingw32-gcc'
cpp = 'x86_64-w64-mingw32-g++'
ar = 'x86_64-w64-mingw32-ar'
windres = 'x86_64-w64-mingw32-windres'
strip = 'x86_64-w64-mingw32-strip'
exe_wrapper = 'wine64'[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
Which is then used during the
setup phase.shmeson setup --cross-file x86_64-w64-mingw32.txt build-mingw
meson compile -C build-mingw
Since cross compiling is
more complicated than native building, let's first go over some
nomenclature. The three most important definitions are traditionally
called build, host and target. This is confusing because those
terms are used for quite many different things. To simplify the issue,
we are going to call these the build machine, host machine and
target machine. Their definitions are the following:
build machine* is the computer that is doing the actual compiling.
host machine* is the machine on which the compiled binary will run.
target machine* is the machine on which the compiled binary's
output will run, only meaningful if the program produces
machine-specific output.
The
tl/dr summary is the following: if you are doing regular cross
compilation, you only care about [[@build_machine]] and
[[@host_machine]]. Just ignore [[@target_machine]] altogether and you will
be correct 99% of the time. Only compilers and similar tools care
about the target machine. In fact, for so-called "multi-target" tools
the target machine need not be fixed at build-time like the others but
chosen at runtime, so target_machine still doesn't matter. If your
needs are more complex or you are interested in the actual details, do
read on.This might be easier to understand through examples. Let's start with
the regular, not cross-compiling case. In these cases all of these
three machines are the same. Simple so far.
Let's next look at the most common cross-compilation setup. Let's
suppose you are on a 64 bit OSX machine and you are cross compiling a
binary that will run on a 32 bit ARM Linux board. In this case your
build machine is 64 bit OSX, your host machine is 32 bit ARM Linux
and your target machine is irrelevant (but defaults to the same
value as the host machine). This should be quite understandable as
well.
The usual mistake in this case is to call the OSX system the host
and the ARM Linux board the target. That's because these were their
actual names when the cross-compiler itself was compiled! Let's assume
the cross-compiler was created on OSX too. When that happened the
build and host machines were the same OSX and different from the
ARM Linux target machine.
In a nutshell, the typical mistake assumes that the terms build,
host and target refer to some fixed positions whereas they're
actually relative to where the current compiler is running. Think of
host as a child of the current compiler and target as an
optional grand-child. Compilers don't change their terminology when
they're creating another compiler, that would at the very least make
their user interface much more complex.
The most complicated case is when you cross-compile a cross compiler.
As an example you can, on a Linux machine, generate a cross compiler
that runs on Windows but produces binaries for MIPS Linux. In this case
build machine is x86 Linux, host machine is x86 Windows and
target machine is MIPS Linux. This setup is known as the Canadian
Cross.
As a side note, be careful when reading cross compilation articles on
Wikipedia or the net in general. It is very common for them to get
build, host and target mixed up, even in consecutive sentences, which
can leave you puzzled until you figure it out.
Again note that when you cross-compile something, the 3 systems
(build, host, and target) used when building the cross compiler
don't align with the ones used when building something with that
newly-built cross compiler. To take our Canadian Cross scenario from
above (for full generality), since its host machine is x86 Windows,
the build machine of anything we build with it is x86 Windows. And
since its target machine is MIPS Linux, the host machine of
anything we build with it is MIPS Linux. Only the target machine
of whatever we build with it can be freely chosen by us, say if we
want to build another cross compiler that runs on MIPS Linux and
targets Aarch64 iOS. As this example hopefully makes clear to you, the
machine names are relative and shifted over to the left by one
position.
If you did not understand all of the details, don't worry. For most
people it takes a while to wrap their head around these concepts.
Don't panic, it might take a while to click, but you will get the hang
of it eventually.
Defining the environment
Meson requires you to write a cross build definition file. It defines
various properties of the cross build environment. The cross file
consists of different sections.
There are a number of options shared by cross and native files,
here. It is assumed that you have read that
section already, as this documentation will only call out options
specific to cross files.
Binaries
ini[binaries]
exe_wrapper = 'wine' # A command used to run generated executables.
The
exe_wrapper option defines a wrapper command that can be used
to run executables for this host. In this case we can use Wine, which
runs Windows applications on Linux. Other choices include running the
application with qemu or a hardware simulator. If you have this kind
of a wrapper, these lines are all you need to write. Meson will
automatically use the given wrapper when it needs to run host
binaries. This happens e.g. when running the project's test suite.Note that
exe_wrapper in the cross file is handled separately
from the exe_wrapper argument in
add_test_setup
and meson test --wrapper
command line argument. Meson must have exe_wrapper specified in the
cross file or else it will skip tests that attempt to run cross
compiled binaries. Only the cross file exe_wrapper value will be
stored in the MESON_EXE_WRAPPER environment variable. If another
wrapper is given in the test setup with exe_wrapper or as a
meson test --wrapper command line argument, then meson will prepend
the additional wrapper before the cross file wrapper like the
following command:
text[prepend_wrapper] <cross_file_wrapper> <exe_binary> <args...>
Properties
In addition to the properties allowed in all machine
files, the cross file may contain
specific information about the cross compiler or the host machine. It
looks like this:
ini[properties]
sizeof_int = 4
sizeof_wchar_t = 4
sizeof_void* = 4alignment_char = 1
alignment_void* = 4
alignment_double = 4
has_function_printf = true
sys_root = '/some/path'
pkg_config_libdir = '/some/path/lib/pkgconfig'
In most cases you don't need the size and alignment settings, Meson
will detect all these by compiling and running some sample programs.
If your build requires some piece of data that is not listed here,
Meson will stop and write an error message describing how to fix the
issue. If you need extra compiler arguments to be used during cross
compilation you can set them with
[langname]_args = [args]. Just
remember to specify the args as an array and not as a single string
(i.e. not as '-DCROSS=1 -DSOMETHING=3').Since 0.52.0 The
sys_root property may point to the root of the
host system path (the system that will run the compiled binaries).
This is used internally by Meson to set the PKG_CONFIG_SYSROOT_DIR
environment variable for pkg-config. If this is unset the host system
is assumed to share a root with the build system.Since 0.54.0 The
pkg_config_libdir property may point to a list of
path used internally by Meson to set the PKG_CONFIG_LIBDIR environment
variable for pkg-config. This prevents pkg-config from searching cross
dependencies in system directories.One important thing to note, if you did not define an
exe_wrapper in
the previous section, is that Meson will make a best-effort guess at
whether it can run the generated binaries on the build machine. It
determines whether this is possible by looking at the system and
cpu_family of build vs host. There will however be cases where they
do match up, but the build machine is actually not compatible with the
host machine. Typically this will happen if the libc used by the build
and host machines are incompatible, or the code relies on kernel
features not available on the build machine. One concrete example is a
macOS build machine producing binaries for an iOS Simulator x86-64
host. They're both darwin and the same architecture, but their
binaries are not actually compatible. In such cases you may use the
needs_exe_wrapper property to override the auto-detection:ini[properties]
needs_exe_wrapper = true
Machine Entries
The next bit is the definition of host and target machines. Every
cross build definition must have one or both of them. If it had
neither, the build would not be a cross build but a native build. You
do not need to define the build machine, as all necessary information
about it is extracted automatically. The definitions for host and
target machines look the same. Here is a sample for host machine.
ini[host_machine]
system = 'windows'
subsystem = 'windows'
kernel = 'nt'
cpu_family = 'x86'
cpu = 'i686'
endian = 'little'
These values define the machines sufficiently for cross compilation
purposes. The corresponding target definition would look the same but
have
target_machine in the header. These values are available in
your Meson scripts. There are three predefined variables called,
surprisingly, [[@build_machine]], [[@host_machine]] and
[[@target_machine]]. Determining the operating system of your host
machine is simply a matter of calling host_machine.system().
Starting from version 1.2.0 you can get more fine grained information
using the .subsystem() and .kernel() methods. The return values of
these functions are documented in the reference table
page.There are two different values for the CPU. The first one is
cpu_family. It is a general type of the CPU. This should have a
value from the CPU Family table.
Note that Meson does not add el to end cpu_family value for little
endian systems. Big endian and little endian mips are both just
mips, with the endian field set appropriately.The second value is
cpu which is a more specific subtype for the
CPU. Typical values for a x86 CPU family might include i386 or
i586 and for arm family armv5 or armv7hl. Note that CPU type
strings are very system dependent. You might get a different value if
you check its value on the same machine but with different operating
systems.If you do not define your host machine, it is assumed to be the build
machine. Similarly if you do not specify target machine, it is assumed
to be the host machine.
Starting a cross build
Once you have the cross file, starting a build is simple
console$ meson setup builddir --cross-file cross_file.txt
Once configuration is done, compilation is started by invoking
meson compile
in the usual way.Introspection and system checks
The main meson object provides two functions to determine cross
compilation status.
meson[[#meson.is_cross_build]] # returns true when cross compiling
[[#meson.can_run_host_binaries]] # returns true if the host binaries can be run, either with a wrapper or natively
You can run system checks on both the system compiler or the cross
compiler. You just have to specify which one to use.
mesonbuild_compiler = [[#meson.get_compiler]]('c', native : true)
host_compiler = [[#meson.get_compiler]]('c', native : false)build_int_size = build_compiler.sizeof('int')
host_int_size = host_compiler.sizeof('int')
Mixing host and build targets
Sometimes you need to build a tool which is used to generate source
files. These are then compiled for the actual target. For this you
would want to build some targets with the system's native compiler.
This requires only one extra keyword argument.
mesonnative_exe = executable('mygen', 'mygen.c', native : true)
You can then take
native_exe and use it as part of a generator rule or anything else you might want.Using a custom standard library
Sometimes in cross compilation you need to build your own standard
library instead of using the one provided by the compiler. Meson has
built-in support for switching standard libraries transparently. The
invocation to use in your cross file is the following:
ini[properties]
c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, variable name
This specifies that C standard library is provided in the Meson
subproject
mylibc in internal dependency variable mylibc_dep. It
is used on every cross built C target in the entire source tree
(including subprojects) and the standard library is disabled. The
build definitions of these targets do not need any modification.Note that it is supported for any language, not only
c, using <lang>_stdlib
property.Since 0.56.0 the variable name parameter is no longer required as long as the
subproject calls
meson.override_dependency('c_stdlib', mylibc_dep).
The above example becomes:ini[properties]
c_stdlib = 'mylibc'
Changing cross file settings
Cross file settings are only read when the build directory is set up
the first time. Any changes to them after the fact will be ignored.
This is the same as regular compiles where you can't change the
compiler once a build tree has been set up. If you need to edit your
cross file, then you need to wipe your build tree and recreate it from
scratch.
Custom data
You can store arbitrary data in
properties and access them from your
Meson files. As an example if your cross file has this:ini[properties]
somekey = 'somevalue'
then you can access that using the
meson object like this:mesonmyvar = meson.get_external_property('somekey')
myvar now has the value 'somevalue'
Cross file locations
As of version 0.44.0 Meson supports loading cross files from system
locations (except on Windows). This will be
$XDG_DATA_DIRS/meson/cross, or if XDG_DATA_DIRS is undefined, then
/usr/local/share/meson/cross and /usr/share/meson/cross will be tried
in that order, for system wide cross files. User local files can be
put in $XDG_DATA_HOME/meson/cross, or ~/.local/share/meson/cross if
that is undefined.The order of locations tried is as follows:
- A file relative to the local dir
- The user local location
- The system wide locations in order
Distributions are encouraged to ship cross files either with their
cross compiler toolchain packages or as a standalone package, and put
them in one of the system paths referenced above.
These files can be loaded automatically without adding a path to the
cross file. For example, if a ~/.local/share/meson/cross contains a
file called x86-linux, then the following command would start a cross
build using that cross files:
shmeson setup builddir/ --cross-file x86-linux
---
Markdown/Cuda Module
---
short-description: CUDA module
authors:
- name: Olexa Bilaniuk
years: [2019]
has-copyright: false
...
Unstable CUDA Module
_Since: 0.50.0_This module provides helper functionality related to the CUDA Toolkit and
building code using it.
Note: this module is unstable. It is only provided as a technology preview.
Its API may change in arbitrary ways between releases or it might be removed
from Meson altogether.
Importing the module
The module may be imported as follows:
` meson
cuda = [[#import]]('unstable-cuda')
textIt offers several useful functions that are enumerated below.
Functions
nvcc_arch_flags()
_Since: 0.50.0_
meson
cuda.nvcc_arch_flags(cuda_version_string, ...,
detected: string_or_array)
textReturns a list of -gencode flags that should be passed to cuda_args: in
order to compile a "fat binary" for the architectures/compute capabilities
enumerated in the positional argument(s). The flags shall be acceptable to
an NVCC with CUDA Toolkit version string cuda_version_string.A set of architectures and/or compute capabilities may be specified by:
- The single positional argument
'All', 'Common' or 'Auto'
- As (an array of)
- Architecture names ('Kepler', 'Maxwell+Tegra', 'Turing') and/or
- Compute capabilities ('3.0', '3.5', '5.3', '7.5')A suffix of
+PTX requests PTX code generation for the given architecture.
A compute capability given as A.B(X.Y) requests PTX generation for an older
virtual architecture X.Y before binary generation for a newer architecture
A.B.Multiple architectures and compute capabilities may be passed in using
- Multiple positional arguments
- Lists of strings
- Space (
), comma (,) or semicolon (;)-separated stringsThe single-word architectural sets
'All', 'Common' or 'Auto'
cannot be mixed with architecture names or compute capabilities. Their
interpretation is:| Name | Compute Capability |
|-------------------|--------------------|
|
'All' | All CCs supported by given NVCC compiler. |
| 'Common' | Relatively common CCs supported by given NVCC compiler. Generally excludes Tegra and Tesla devices. |
| 'Auto' | The CCs provided by the detected: keyword, filtered for support by given NVCC compiler. |The supported architecture names and their corresponding compute capabilities
are:
| Name | Compute Capability |
|-------------------|----------------------------|
|
'Fermi' | 2.0, 2.1(2.0) |
| 'Kepler' | 3.0, 3.5 |
| 'Kepler+Tegra' | 3.2 |
| 'Kepler+Tesla' | 3.7 |
| 'Maxwell' | 5.0, 5.2 |
| 'Maxwell+Tegra' | 5.3 |
| 'Pascal' | 6.0, 6.1 |
| 'Pascal+Tegra' | 6.2 |
| 'Volta' | 7.0 |
| 'Xavier' | 7.2 |
| 'Turing' | 7.5 |
| 'Ampere' | 8.0, 8.6 |
| 'Orin' | 8.7 |
| 'Lovelace' | 8.9 |
| 'Hopper' | 9.0 |
| 'Hopper(A)' | 9.0a |
| 'Thor' | 10.1, 11.0 |
| 'Thor(A)' | 10.1a, 11.0a |
| 'Blackwell' | 10.0, 10.3, 12.0, 12.1 |
| 'Blackwell(A)' | 10.0a, 10.3a, 12.0a, 12.1a |The
'(A)' names select the architecture-specific (a-suffixed) compute
capabilities of their family. Code built for these can use
architecture-specific features, but runs only on exactly that architecture:
it has no forward compatibility, so it cannot be combined with +PTX.
The family-specific f-suffixed compute capabilities introduced with
CUDA 12.9 (e.g. 10.0f, which runs on all later members of the same
family) may be requested explicitly, but are not part of any named set.Note: the
f-suffixed capabilities only benefit kernels that use
architecture-conditional features (such as the 5th-generation tensor core
instructions), which plain compute capabilities cannot express. For all
other code they gain nothing: a plain capability plus +PTX is compatible
beyond the family, and NVCC refuses to combine X.Yf with plain X.Y
in the same build. Prefer the plain capabilities unless you know your
kernels require family-specific features.
Examples:
cuda.nvcc_arch_flags('10.0', '3.0', '3.5', '5.0+PTX')
cuda.nvcc_arch_flags('10.0', ['3.0', '3.5', '5.0+PTX'])
cuda.nvcc_arch_flags('10.0', [['3.0', '3.5'], '5.0+PTX'])
cuda.nvcc_arch_flags('10.0', '3.0 3.5 5.0+PTX')
cuda.nvcc_arch_flags('10.0', '3.0,3.5,5.0+PTX')
cuda.nvcc_arch_flags('10.0', '3.0;3.5;5.0+PTX')
cuda.nvcc_arch_flags('10.0', 'Kepler 5.0+PTX')
# Returns ['-gencode', 'arch=compute_30,code=sm_30',
# '-gencode', 'arch=compute_35,code=sm_35',
# '-gencode', 'arch=compute_50,code=sm_50',
# '-gencode', 'arch=compute_50,code=compute_50']
cuda.nvcc_arch_flags('10.0', '3.5(3.0)')
# Returns ['-gencode', 'arch=compute_30,code=sm_35']
cuda.nvcc_arch_flags('8.0', 'Common')
# Returns ['-gencode', 'arch=compute_30,code=sm_30',
# '-gencode', 'arch=compute_35,code=sm_35',
# '-gencode', 'arch=compute_50,code=sm_50',
# '-gencode', 'arch=compute_52,code=sm_52',
# '-gencode', 'arch=compute_60,code=sm_60',
# '-gencode', 'arch=compute_61,code=sm_61',
# '-gencode', 'arch=compute_61,code=compute_61']
cuda.nvcc_arch_flags('9.2', 'Auto', detected: '6.0 6.0 6.0 6.0')
cuda.nvcc_arch_flags('9.2', 'Auto', detected: ['6.0', '6.0', '6.0', '6.0'])
# Returns ['-gencode', 'arch=compute_60,code=sm_60']
cuda.nvcc_arch_flags(nvcc, 'All')
# Returns ['-gencode', 'arch=compute_20,code=sm_20',
# '-gencode', 'arch=compute_20,code=sm_21',
# '-gencode', 'arch=compute_30,code=sm_30',
# '-gencode', 'arch=compute_32,code=sm_32',
# '-gencode', 'arch=compute_35,code=sm_35',
# '-gencode', 'arch=compute_37,code=sm_37',
# '-gencode', 'arch=compute_50,code=sm_50', # nvcc.version() < 7.0
# '-gencode', 'arch=compute_52,code=sm_52',
# '-gencode', 'arch=compute_53,code=sm_53', # nvcc.version() >= 7.0
# '-gencode', 'arch=compute_60,code=sm_60',
# '-gencode', 'arch=compute_61,code=sm_61', # nvcc.version() >= 8.0
# '-gencode', 'arch=compute_70,code=sm_70',
# '-gencode', 'arch=compute_72,code=sm_72', # nvcc.version() >= 9.0
# '-gencode', 'arch=compute_75,code=sm_75'] # nvcc.version() >= 10.0
_Note:_ This function is intended to closely replicate CMake's FindCUDA module
function
CUDA_SELECT_NVCC_ARCH_FLAGS(out_variable, [list of CUDA compute architectures])
nvcc_arch_readable()
_Since: 0.50.0_
meson
cuda.nvcc_arch_readable(cuda_version_string, ...,
detected: string_or_array)
textHas precisely the same interface as nvcc_arch_flags(),
but rather than returning a list of flags, it returns a "readable" list of
architectures that will be compiled for. The output of this function is solely
intended for informative message printing. archs = '3.0 3.5 5.0+PTX'
readable = cuda.nvcc_arch_readable('10.0', archs)
message('Building for architectures ' + ' '.join(readable))
This will print
Message: Building for architectures sm30 sm35 sm50 compute50
_Note:_ This function is intended to closely replicate CMake's
FindCUDA module function
CUDA_SELECT_NVCC_ARCH_FLAGS(out_variable,
[list of CUDA compute architectures])
min_driver_version()
_Since: 0.50.0_
meson
cuda.min_driver_version(cuda_version_string)
``Returns the minimum NVIDIA proprietary driver version required, on the
host system, by kernels compiled with a CUDA Toolkit with the given
version string.
The output of this function is generally intended for informative
message printing, but could be used for assertions or to conditionally
enable features known to exist within the minimum NVIDIA driver
required.
---