One of the main design goals of Meson has been to make the 95% use case as simple as possible. This means that rather than providing a framework that people can use to solve their problems themselves, we'd rather just provide the solution.
For a simple example let's look at using the address sanitizer. On other build systems you usually need to copy a macro that someone else has written into your build definition or write a toggle that adds the compiler flags manually. This is not a lot of work but everyone needs to do it and these things add up. Different projects might write different options for this feature so when switching between projects you always need to learn and remember what the option was called on each.
At its core this really is a one bit issue. Either you want to use address sanitizer or you don't. With this in mind, Meson provides an interface that is just as simple. You can either enable address sanitizer during build tree configuration:
meson -Db_sanitizer=address <source_dir> <build_dir>
Or you can configure it afterwards with the configuration tool:
mesonconf -Db_sanitizer=address <build_dir>
There are a bunch of other options that you can also enable with these commands (for the remainder of the document we only use the latter).
mesonconf -Db_lto=true <build_dir>
Warnings as errors:
mesonconf -Dwerror=true <build_dir>
mesonconf -Db_coverage=true <build_dir>
Profile guided optimization:
mesonconf -Dd_pgo=generate (or =use) <build_dir>
Compiler warning levels (1 is -Wall, 3 is almost everything):
mesonconf -Dwarning_level=2 <build_dir>
The basic goal of this option system is clear: you, the user, should only describe what you want to happen. It is the headache of the build system to make it happen.