Previous Post | Top | Next Post |
TOC
Since around 2017, GNOME has pushed to use Meson to build its associated programs. I now have no choice but to learn Meson.
Here is my learning process note.
Build infrastructure history
GNU Autotools on top of Make has been the de facto standard for the portable build infrastructure since 1990s.
Configure script generation utility, GNU Autoconf has been a core part of GNU Autotools but it was extremely slow to execute and was not intuitive to customize. Root cause of problem were requirements for:
- writing portable Bourne shell script snippets to customize it
- relying on text substitutions by not-so-much-used M4
- generating configuration files by the slow Bourne shell
- relying on Make as the final build infrastructure
- supporting only string as the configuration data type
CMake initially release in 2000, addressed the first 3 issues listed in the above.
Ninja initially release in 2012, addressed the 4th issue by offering the alternative smaller and faster low level build tool of Make.
Meson initially release in 2013, is a higher level build tool in line with the functionalities of GNU Autotools and CMake. It used Ninja as its low level build infrastructure and supports string, list and dictionary data types.
(Some of the configuration syntax of Meson seems to resemble SCons initially release in 2000.)
(Since around 2016, CMake also supports the use of Ninja as its low level build infrastructure but still limited to the string data type.)
Meson using Ninja as its backend seems to me the winner these days with its modular and declarative simple configuration file syntax and its execution speed.
See:
Learning Meson
Command line options and the environment variables of Meson
are very similar to what we use in more traditional
GNU Autotools and
CMake, including DESTDIR
and
prefix
.
I read the following basic documents first:
Meson has a well documented native support of most compiler languages. But for building documentation, HotDoc documentation is the only documentation platform with the native support on Meson by the Hotdoc module.
Many document building activities usually involve processing files with sed/perl/python-scripts, or XSLT-transformation-scripts. The answer to “How do I build documents with Meson?” involves running external commands, creating custom targets, and creating generator objects. The followings seem to be useful.
As for i18n, I18n module provides internationalization and localization functionality. An implementation example can be found at Localization.
Note on recent feature enhancements
Meson is still in pre-1.0 stage as of July 2021 and is evolving quickly.
Since the Meson version of Debian Bullseye/11 (stable) is 0.56.2, some features may not work on Debian Bullseye/11 (stable). Notable ones are:
- Support of reading files at configuration time with the fs module (0.57 feature)
- Support of multiple append() and prepend() in environment() object (0.58 feature)
- Support of format string (0.58 feature)
- Support of String .replace() (0.58 feature)
- Support of range() function (0.58 feature)
- Support of feed for custom_target() (0.59 feature)
- Support of accepting files objects by the fs module (0.59 feature)
- Support of required and disabler arguments by the import() function (0.59 feature)
The current Debian Bookworm/12 in testing has 0.59.1, so the above issues are solved.
Learning Ninja
In order to grok Meson generated
build.ninja
, I browsed The Ninja build system.
Note on Meson
Basics
Meson is for out-of-tree building. Meson uses single quotations for the string.
For the cross platform customization, tutorial documents tend to use:
- Python3 scripts for Meson/Ninja
- POSIX shell scripts for Autotools/Makefile
Functionalities
meson setup
configures the project –autoreconf -ivf
meson configure
changes project options –./configure --prefix=/usr ...
meson compile
builds the project –make
meson install
installs the project –make install
Please note setup is configure. (confusing…)
Example for run_command()
and custom_target()
Here is a text conversion example to generate a shell script:
project('foo', version : '0.1')
# run in setup
date = find_program('date')
sed = find_program('sed')
sh = find_program('sh')
cat = find_program('cat')
datex = 's/@timestamp@/' + run_command(date, '--iso=sec', '-u').stdout().strip() + '/'
versionx = 's/@version@/' + meson.project_version() + '/'
hellox = 's/@msg@/date=@timestamp@ version=@version@ -- Hello World!/'
# run in compile
date1 = custom_target('date1',
capture : true,
output : 'date1',
command : [ date, '--iso=sec', '-u' ])
date2 = custom_target('date2',
input : date1,
capture : true,
output : 'date2',
command : [ sed, '-e', 's/^/echo "date=/', '-e', 's/$/"/', '@INPUT@' ])
foo1 = custom_target('foo1',
input : 'foo0',
capture : true,
output : 'foo1',
command : [ sed, '-e', hellox , '-e', datex, '-e', versionx, '@INPUT@'])
sh1 = custom_target('sh1',
input : '/etc/motd',
capture : true,
output : 'sh1',
command : [ sh, '-c',
'cat /etc/motd | grep -e GNU | sed -e \'s/^/echo "motd=/\' -e \'s/$/"/\' '
])
foo = custom_target('default',
input : [foo1, date2, sh1],
build_by_default: true,
capture : true,
install : true,
install_dir : 'bin',
install_mode : 'rwxr-xr-x',
output : 'foo',
command : [ cat, '@INPUT@'])
(Please note, new feed
feature is not used to be compatible with Meson
version 0.56.2)
This starts with this template file:
#!/bin/sh
echo "@msg@"
Let’s configure and build script foo
:
$ meson setup build # configure
$ cd build
$ meson configure --prefix=~
$ meson compile # build
$ meson install
This generates foo
with meson compile
and install it to ~/bin/foo
with meson install
:
#!/bin/sh
echo "date=2021-08-22T07:24:15+00:00 version=0.1 -- Hello World!"
echo "date=2021-08-22T07:25:13+00:00"
echo "motd=The programs included with the Debian GNU/Linux system are free software;"
echo "motd=Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent"
Most compilers are well supported by Meson and there are many examples.
Abusing meson with shell codes
Please note that if we don’t worry about Windows, we can embed shell codes
almost as in the case of Makefile
.
Notable things are:
- You should not have multiple lines between a set of single quotes.
- New line between a set of triple quotes are mere whitespaces to the shell.
Here is an example of handling of long lines and quoted lines.
project('foo', version : '0.1')
# run in setup
date = find_program('date')
sed = find_program('sed')
sh = find_program('sh')
cat = find_program('cat')
datex = 's/@timestamp@/' + run_command(date, '--iso=sec', '-u').stdout().strip() + '/'
versionx = 's/@version@/' + meson.project_version() + '/'
hellox = 's/@msg@/date=@timestamp@ version=@version@ -- Hello World!/'
# run in compile
date1 = custom_target('date1',
capture : true,
output : 'date1',
command : [ date, '--iso=sec', '-u' ])
date2 = custom_target('date2',
input : date1,
capture : true,
output : 'date2',
command : [ sed, '-e', 's/^/echo "date=/', '-e', 's/$/"/', '@INPUT@' ])
# Some NLs are OK and act as just whitespaces
foo1 = custom_target('foo1',
input : 'foo0',
capture : true,
output : 'foo1',
command : [ sh, '-c',
'sed -e \'' + hellox + '\' -e \'' + datex + '\' -e \''
+ versionx + '\' @INPUT@'
])
# Triple-single-quote disables escaping
# NLs in triple-single-quotes become just whitespaces
sh1 = custom_target('sh1',
input : '/etc/motd',
capture : true,
output : 'sh1',
command : [ sh, '-c',
'''cat /etc/motd |
grep -e GNU |
sed -e 's/^/echo "motd=/' -e 's/$/"/' '''
])
foo = custom_target('default',
input : [foo1, date2, sh1],
build_by_default: true,
capture : true,
install : true,
install_dir : 'bin',
install_mode : 'rwxr-xr-x',
output : 'foo',
command : [ cat, '@INPUT@'])
Previous Post | Top | Next Post |