meson.build files
The Meson build system is mainly configured with meson.build
files.
In our example, there are three meson.build
files: in the top level directory, in the ./src
directory beneath (where main.c
and dynamic-library-loader.c
are located) and lastly in ./src/tq84
where the files for the shared objects are located (add.*
and answer.*
).
Top level meson.build file
Our top level
meson.build
uses the Meson function
project()
to name the project (
sum) and specify the
programming language for the project (in this case:
C). Also, the project's license and version are stated here.
The subdir()
function instructs Meson to enter into the specified directory (src
) and execute the meson.build
file in that subdirectory
project('sum', 'c',
version : '1.0.0',
license : 'GPL')
subdir('src')
./src/meson.build
The ./src/meson.build
file starts with the subdir()
function. So, Meson first descends into ./src/tq84
and executes that meson.file
which creates the static and shared object files.
It is necessary to build them first because the executables are dependent on it. More on this later.
After building the shared objects, control is returned to ./src/meson.build
. This file now instructs Meson to build three executables, each with the executable()
function.
The first argument indicates the name of the executable and the unnamed following (that is: positional) arguments the sources to be compiled. In our case, this is one file: main.c
.
The named argument link_with
is used to determine with which files the executable is to be linked.
Note that we use a variables here: tq84_lib_static
and tq84_lib_shared
. The values for these variables were previously set when running ./src/tq84/meson.build
.
The executable
dynamic-library-loader
uses the functions
dlsym()
,
dlopen()
and
dlerror()
which are found in
libdl
. Using the gnu
linker, this library would be linked with the
-ldl
flag.
In order for Meson to do the same thing, we first get a compiler object (cc
) through the meson
object's get_compiler('c')
function. Then, the compiler object can be queried for the correct ld
library with cc.find_library('dl')
.
With this information, we're ready to create the executable dynamic-library-loader
.
subdir('tq84')
executable('statically-linked', 'main.c',
link_with: tq84_lib_static)
executable('use-shared-library', 'main.c',
link_with: tq84_lib_shared)
cc = meson.get_compiler('c')
libdl = cc.find_library('dl')
executable('dynamic-library-loader', 'dynamic-library-loader.c',
dependencies: libdl)
./src/tq84/meson.build
The ./src/tq84/meson.build
file is responsible to create the shared and static shared objects.
The first line assigns the source names to the variable runtime_sources
so that they don't need to be repeated.
The static library is built with the static_library()
function, the shared library with the shared_library()
function.
The
install
flag set to
true
causes the target to be installed (probably to
/usr/lib
.
runtime_sources = ['add.c', 'add.h', 'answer.c', 'answer.h']
tq84_lib_static = static_library('runtime',
runtime_sources,
install : true)
# We use libtool-version numbers because it's easier to understand.
# Before making a release, the libruntime_so_*
# numbers should be modified. The components are of the form C:R:A.
# a) If binary compatibility has been broken (eg removed or changed interfaces)
# change to C+1:0:0.
# b) If interfaces have been changed or added, but binary compatibility has
# been preserved, change to C+1:0:A+1
# c) If the interface is the same as the previous version, change to C:R+1:A
libruntime_lt_c=1
libruntime_lt_r=0
libruntime_lt_a=0
libruntime_so_version = '@0@.@1@.@2@'.format((libruntime_lt_c - libruntime_lt_a),
libruntime_lt_a,
libruntime_lt_r)
tq84_lib_shared = shared_library('runtime',
runtime_sources,
version : libruntime_so_version,
install : true)