New features

run_target can now be used as a dependency

A run_target() can now be saved in a variable and reused as a dependency in an alias_target(). This can be used to create custom alias rules that ensure multiple other targets are run, even if those targets don't produce output files.

For example:

i18n = import('i18n')

all_pot_targets = []

foo_i18n = i18n.gettext('foo')

all_pot_targets += foo_i18n[1]

alias_target('all-pot', all_pot_targets)

The Python Modules dependency method no longer accepts positional arguments

Previously these were ignored with a warning, now they're a hard error.


unset_variable() can be used to unset a variable. Reading a variable after calling unset_variable() will raise an exception unless the variable is set again.

# tests/
tests = ['test1', 'test2']

# ...


# tests is no longer usable until it is set again

Override python installation paths

The python module now has options to control where modules are installed:

  • python.platlibdir: Directory for site-specific, platform-specific files.
  • python.purelibdir: Directory for site-specific, non-platform-specific files.

Those options are used by python module methods python.install_sources() and python.get_install_dir(). By default Meson tries to detect the correct installation path, but make them relative to the installation prefix, which will often result in installed python modules to not be found by the interpreter unless prefix is /usr on Linux, or for example C:\Python39 on Windows. These new options can be absolute paths outside of prefix.

New subprojects packagefiles subcommand

It is now possible to re-apply overlays (patch_filename or patch_directory in the wrap ini file) after a subproject was downloaded and set up, via meson subprojects packagefiles --apply <wrap-name>.

It is also possible for patch_directory overlays in a [wrap-file], to copy the packagefiles out of the subproject and back into packagefiles/<patch_directory>/ via meson subprojects packagefiles --save <wrap-name>. This is useful for testing an edit in the subproject and then saving it back to the overlay which is checked into git.

Deprecated project options

Project options declared in meson_options.txt can now 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'})

More efficient static linking of uninstalled libraries

Note: This change had to be reverted in 0.60.1 because it caused regressions. New API will likely be introduced in 0.61.0 to have better control whether or not to create thin archive.

A somewhat common use case of static_library() is to create uninstalled internal convenience libraries which are solely meant to be linked to other targets. Some build systems call these "object libraries". Meson's implementation does always create a static archive.

This will now check to see if the static linker supports "thin archives" (archives which do not contain the actual object code, only references to their location on disk) and if so, use them to minimize space usage and speed up linking.

gnome.yelp variadic argument deprecation

gnome.yelp previously allowed sources to be passed either as variadic arguments or as a keyword argument. If the keyword argument was given the variadic arguments would be silently ignored. This has changed in 0.60.0, the variadic form has been deprecated, and a warning is printed if both are given.

static keyword argument to meson.override_dependency()

It is now possible to override shared and/or static dependencies separately. When the static keyword argument is not specified in dependency(), the first override will be used (static_dep in the example below).

static_lib = static_library()
static_dep = declare_dependency(link_with: static_lib)
meson.override_dependency('foo', static_dep, static: true)

shared_lib = shared_library()
shared_dep = declare_dependency(link_with: shared_lib)
meson.override_dependency('foo', shared_dep, static: false)

# Returns static_dep

# Returns static_dep
dependency('foo', static: true)

# Returns shared_dep
dependency('foo', static: false)

When the static keyword argument is not specified in meson.override_dependency(), the dependency is assumed to follow the value of default_library option.

dep = declare_dependency(...)
meson.override_dependency('foo', dep)

# Always works

# Works only if default_library is 'static' or 'both'
dependency('foo', static: true)

# Works only if default_library is 'shared' or 'both'
dependency('foo', static: false)

dependency() sets default_library on fallback subproject

When the static keyword argument is set but default_library is missing in default_options, dependency() will set it when configuring fallback subproject. dependency('foo', static: true) is now equivalent to dependency('foo', static: true, default_options: ['default_library=static']).

install_emptydir function

It is now possible to define a directory which will be created during installation, without creating it as a side effect of installing files into it. This replaces custom meson.add_install_script() routines. For example:

meson.add_install_script('sh', '-c', 'mkdir -p "$DESTDIR/@0@"'.format(path))

can be replaced by:


and as a bonus this works reliably on Windows, prints a sensible progress message, will be uninstalled by ninja uninstall, etc.

Cython can now transpile to C++ as an intermediate language

Built-in cython support currently only allows C as an intermediate language, now C++ is also allowed. This can be set via the cython_language option, either on the command line, or in the files.

  default_options : ['cython_language=cpp'],

or on a per target basis with:

  override_options : ['cython_language=cpp'],

New custom dependency for iconv


will now check for the functionality of, but first check if it is provided in the libc (for example in glibc or musl libc on Linux).

Unknown options are now always fatal

Passing unknown options to "meson setup" or "meson configure" is now always fatal. That is, Meson will exit with an error code if this happens. Previous Meson versions only showed a warning message.

Install DESTDIR relative to build directory

When DESTDIR environment or meson install --destdir option is a relative path, it is now assumed to be relative to the build directory. An absolute path will be set into environment when executing scripts. It was undefined behavior in prior Meson versions but was working as relative to build directory most of the time.

Java Module

The Java module has been added to Meson. The Java module allows users to generate native header files without needing to use a custom_target().

jmod = import('java')

native_header = jmod.generate_native_header('', package: 'com.mesonbuild')
native_header_includes = include_directories('.')

jdkjava = shared_module(
  [native_header_includes, other_sources],
  dependencies : [jdk],
  include_directories : [native_header_includes]

Usually, the links method of the compiler object uses a single program invocation to do both compilation and linking. Starting with this version, whenever the argument to links is a file, Meson will check if the file suffix matches the compiler object's language. If they do not match, as in the following case:

cxx = meson.get_compiler('cpp')

then Meson will separate compilation and linking. In the above example test.c will be compiled with a C compiler and the resulting object file will be linked with a C++ compiler. This makes it possible to detect misconfigurations of the compilation environment, for example when the C++ runtime is not compatible with the one expected by the C compiler.

For this reason, passing file arguments with an unrecognized suffix to links will cause a warning.

Relax restrictions of str.join()

Since 0.60.0, the str.join() method can take an arbitrary number of arguments instead of just one list. Additionally, all lists past to str.join() will now be flattened.

Improvements for the Rustc compiler

  • Werror now works, this set's -D warnings, which will cause rustc to error for every warning not explicitly disabled
  • warning levels have been implemented
  • support for meson's pic has been enabled

The qt modules now accept generated outputs as inputs for qt.compile_*

This means you can uset custom_target, custom_target indices (custom_target[0], for example), or the output of generator.process as inputs to the various qt.compile_* methods.

qt = import('qt5')

ct = custom_target(...)

out = qt.compile_ui(sources : ct)

Waf support in external-project module

If the first argument is 'waf', special treatment is done for the waf build system. The waf executable must be found either in the current directory, or in system PATH.

Comparing two objects with different types is now an error

Using the == and != operators to compare objects of different (for instance [1] == 1) types was deprecated and undefined behavior since 0.45.0 and is now a hard error.

Installation tags

It is now possible to install only a subset of the installable files using meson install --tags tag1,tag2 command line.

See documentation for more details.

Compiler.unittest_args has been removed

It's never been documented, and it's been marked deprecated for a long time, so let's remove it.

Dependencies with multiple names

More than one name can now be passed to dependency(), they will be tried in order and the first name to be found will be used. The fallback subproject will be used only if none of the names are found on the system. Once one of the name has been found, all other names are added into the cache so subsequent calls for any of those name will return the same value. This is useful in case a dependency could have different names, such as png and libpng.

i18n module now returns gettext targets

r = i18n.gettext('mydomain') will now provide access to:

  • a list of built .mo files
  • the mydomain-pot maintainer target which updates .pot files
  • the mydomain-update-po maintainer target which updates .po files

Added support for CLA sources when cross-compiling with the C2000 toolchain

Support for CLA sources has been added for cross-compilation with the C2000 toolchain.

Support for clippy-driver as a rustc wrapper

Clippy is a popular linting tool for Rust, and is invoked in place of rustc as a wrapper. Unfortunately it doesn't proxy rustc's output, so we need to have a small wrapper around it so that Meson can correctly detect the underlying rustc, but still display clippy

Force Visual Studio environment activation

Since 0.59.0, meson automatically activates Visual Studio environment on Windows for all its subcommands, but only if no other compilers (e.g. gcc or clang) are found, and silently continue if Visual Studio activation fails.

meson setup --vsenv command line argument can now be used to force Visual Studio activation even when other compilers are found. It also make Meson abort with an error message when activation fails. This is especially useful for Github Action because their Windows images have gcc in their PATH by default.

--vsenv is set by default when using vs backend.

Only setup, compile, dist and devenv subcommands now activate Visual Studio.

MSVC compiler now assumes UTF-8 source code by default

Every project that uses UTF-8 source files had to add manually /utf-8 C/C++ compiler argument for MSVC otherwise they wouldn't work on non-English locale. Meson now switched the default to UTF-8 to be more consistent with all other compilers.

This can be overridden but using /source-charset:

if cc.get_id() == 'msvc'
  add_project_arguments('/source-charset:.XYZ', language: ['c', 'cpp'])

See Microsoft documentation for details:

Add support for find_library in Emscripten

The find_library method can be used to find your own JavaScript libraries. The limitation is that they must have the file extension .js. Other library lookups will look up "native" libraries from the system like currently. A typical usage would look like this:

glue_lib = cc.find_library('gluefuncs.js',
                           dirs: meson.current_source_dir())
executable('prog', 'prog.c',
           dependencies: glue_lib)

Optional custom_target() name

The name argument is now optional and defaults to the basename of the first output.

The results of the search are