|
|
@ -551,4 +551,81 @@ libA = library('libA', 'fileA.cpp', link_with : []) |
|
|
|
This means that you HAVE to write your `library(...)` calls in the order that the |
|
|
|
This means that you HAVE to write your `library(...)` calls in the order that the |
|
|
|
dependencies flow. While ideas to make arbitrary orders possible exist, they were |
|
|
|
dependencies flow. While ideas to make arbitrary orders possible exist, they were |
|
|
|
rejected because reordering the `library(...)` calls was considered the "proper" |
|
|
|
rejected because reordering the `library(...)` calls was considered the "proper" |
|
|
|
way. See [here](https://github.com/mesonbuild/meson/issues/8178) for the discussion. |
|
|
|
way. See [here](https://github.com/mesonbuild/meson/issues/8178) for the discussion. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Why doesn't meson have user defined functions/macros? |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The tl;dr answer to this is that meson's design is focused on solving specific |
|
|
|
|
|
|
|
problems rather than providing a general purpose language to write complex |
|
|
|
|
|
|
|
code solutions in build files. Build systems should be quick to write and |
|
|
|
|
|
|
|
quick to understand, functions muddle this simplicity. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The long answer is twofold: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
First, Meson aims to provide a rich set of tools that solve specific problems |
|
|
|
|
|
|
|
simply out of the box. This is similar to the "batteries included" mentality of |
|
|
|
|
|
|
|
Python. By providing tools that solve common problems in the simplest way |
|
|
|
|
|
|
|
possible *in* Meson we are solving that problem for everyone instead of forcing |
|
|
|
|
|
|
|
everyone to solve that problem for themselves over and over again, often |
|
|
|
|
|
|
|
badly. One example of this are Meson's dependency wrappers around various |
|
|
|
|
|
|
|
config-tool executables (sdl-config, llvm-config, etc). In other build |
|
|
|
|
|
|
|
systems each user of that dependency writes a wrapper and deals with the |
|
|
|
|
|
|
|
corner cases (or doesn't, as is often the case), in Meson we handle them |
|
|
|
|
|
|
|
internally, everyone gets fixes and the corner cases are ironed out for |
|
|
|
|
|
|
|
*everyone*. Providing user defined functions or macros goes directly against |
|
|
|
|
|
|
|
this design goal. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Second, functions and macros makes the build system more difficult to reason |
|
|
|
|
|
|
|
about. When you encounter some function call, you can refer to the reference |
|
|
|
|
|
|
|
manual to see that function and its signature. Instead of spending |
|
|
|
|
|
|
|
frustrating hours trying to interpret some bit of m4 or follow long include |
|
|
|
|
|
|
|
paths to figure out what `function1` (which calls `function2`, which calls |
|
|
|
|
|
|
|
`function3`, ad infinitum), you know what the build system is doing. Unless |
|
|
|
|
|
|
|
you're actively developing Meson itself, it's just a tool to orchestrate |
|
|
|
|
|
|
|
building the thing you actually care about. We want you to spend as little |
|
|
|
|
|
|
|
time worrying about build systems as possible so you can spend more time on |
|
|
|
|
|
|
|
*your code*. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Many times user defined functions are used due to a lack of loops or |
|
|
|
|
|
|
|
because loops are tedious to use in the language. Meson has both arrays/lists |
|
|
|
|
|
|
|
and hashes/dicts natively. Compare the following pseudo code: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```meson |
|
|
|
|
|
|
|
func(name, sources, extra_args) |
|
|
|
|
|
|
|
executable( |
|
|
|
|
|
|
|
name, |
|
|
|
|
|
|
|
sources, |
|
|
|
|
|
|
|
c_args : extra_args |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
endfunc |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func(exe1, ['1.c', 'common.c'], []) |
|
|
|
|
|
|
|
func(exe2, ['2.c', 'common.c'], []) |
|
|
|
|
|
|
|
func(exe2_a, ['2.c', 'common.c'], ['-arg']) |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```meson |
|
|
|
|
|
|
|
foreach e : [['1', '1.c', []], |
|
|
|
|
|
|
|
['2', '2.c', []], |
|
|
|
|
|
|
|
['2', '2.c', ['-arg']]] |
|
|
|
|
|
|
|
executable( |
|
|
|
|
|
|
|
'exe' + e[0], |
|
|
|
|
|
|
|
e[1], |
|
|
|
|
|
|
|
c_args : e[2], |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
endforeach |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The loop is both less code and is much easier to reason about than the function |
|
|
|
|
|
|
|
version is, especially if the function were to live in a separate file, as is |
|
|
|
|
|
|
|
common in other popular build systems. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Build system DSLs also tend to be badly thought out as generic programming |
|
|
|
|
|
|
|
languages, Meson tries to make it easy to use external scripts or programs |
|
|
|
|
|
|
|
for handling complex problems. While one can't always convert build logic |
|
|
|
|
|
|
|
into a scripting language (or compiled language), when it can be done this is |
|
|
|
|
|
|
|
often a better solution. External languages tend to be well-thought-out and |
|
|
|
|
|
|
|
tested, generally don't regress, and users are more likely to have domain |
|
|
|
|
|
|
|
knowledge about them. They also tend to have better tooling (such as |
|
|
|
|
|
|
|
autocompletion, linting, testing solutions), which make them a lower |
|
|
|
|
|
|
|
maintenance burden over time. |
|
|
|