1606351745173.png
[Hide] (366.4KB, 1242x691) >>5666
Meson produces a compile_commands.json https://clang.llvm.org/docs/JSONCompilationDatabase.html which helps you run linters and use clangd's language server features.
Meson is much faster than every other build system, accelerating the work-build-test cycle. It automatically handles rebuilding the relevant files when you change compile flags or a header (Make doesn't), it doesn't relink if a symbol table hasn't changed, and parallel compilation always works (you can break thread safety in Make by not specifying the dependencies between your source files properly).
In Meson, you specify what you want, not how you want. In Make, if you want to install a file for instance, you write an install step and then you create the right directories, copy the files, set the right permissions, and specify a DESTDIR variable so the user can set it and install to the right directory (/usr/pkg on NetBSD, /mingw64 on MINGW64, / on most Linux distros, and so on). In Meson, you set a boolean that says "please install this executable I told you to build," and it has the right path for the current system baked in and also allows the user to specify his own. This is true for every other aspect of the build system and the main cause for its build definitions being much superior, as Meson is much faster and easier to learn and use while only gaining good features.
Meson automatically handles linker order.
Meson partially abstracts dependencies. The main function for asking for a dependency first checks if the dependency is a special case (OpenGL, pthreads, SDL and many others all greatly vary between systems or have their own unique configuration tool for getting the linker and compiler flags, Meson has special cases for those); then it tries to use pkg-config, then it falls back to linking whatever library has the same name, and lastly, it tries to download, compile, and use a dependency from its repository if you told it to. In essence, you have to know what it does there, it just abstracts away the part where you would write the build definitions to do all of that. It also lets you manually and/or conditionally specify which dependencies get statically or dynamically linked or let Meson's defaults or the user specify them. This is important on say Windows, there you probably want to statically link everything that can be statically linked (Cygwin can't for instance) and that has a compatible license, except for the C library.
Meson abstracts the compiler, but still allows manually specifying compiler flags, both the user and the developer can do this. For instance, I check if I'm using a MSVC-like compiler, and if I am, I manually add /Qspectre to the compiler flags because Spectre mitigations are off by default on Windows for some god forsaken reason.
Meson supports feature testing. You don't write an #ifdef for every single platform, C library, and their versions if you want to do something in case a feature is available or missing. You can ask "If this platform has strlcpy, use it, else if it has libbsd, depend on libbsd-overlay; else if it has libstrl, depend on it and include its header; else add this source file with the implementation to the program". That's also more useful than merely using #ifdef, and it's less work while simultaneously producing better results, because you'll have to maintain those #ifdefs as platforms evolve and you'll have to write new ones for every platform you add. With feature testing, chances are, any platform you add will just work, unless you don't have enough fallbacks for missing features.
Meson has a test framework.
Meson exclusively works with a build directory. You don't have to write a clean step, just rm -rf the build directory. This is also important because package systems nowadays want out of tree builds.
Seriously, I've used CMake, POSIX Make, BSD Make, Autotools, and Meson is the only good build system I know. The others don't even compete. You have to ask yourself how you would even do most of the above with Autotools or Make. Most of it is doable with CMake, but you have to be very careful with CMake and the CMake DSL is inferior to Meson's.
There's an APUE exercise that involved writing a library and some tests, I made the mistake of using Make because I hadn't even heard of Meson back then, just writing the Makefile took more time than I would have taken to learn Meson and write better build definitions with Meson.
>>5664
>I'm reluctant to add an extra dependency since the program compiles fine without it on both Windows and Linux
True, but it's a build time dependency that makes a platform work without breaking others.
>What's wrong with using parg? Also getopt is not on Windows.
I don't see anything wrong with it, but I don't see anything right with it. It's best to use the standard interface in such a case because it's less code for you to maintain, every C programmer knows the standard interface, and it leads to smaller binaries.
Less lines of code, less to learn, smaller binaries, that's a better program.
MinGW bakes a getopt() into your executable if you use it. Your program already doesn't work on Visual Studio because the program wants a GCC-like compiler command line interface and the Unix rm command, and the list of things VS doesn't have is only going to grow as you add targets to the make file and the program grows. Either way, you could simply plug in a getopt() implementation on Visual Studio. I think musl's getopt() is the best.
>You're free to remove the -static flag.
True, but the issue here is that it requires a patch. A patch might break every release. It should be settable through the make command, without touching the source code.
The things that need to be patched to get the program to build or do something essential like supporting dynamic linking grow with the program, there's going to come a point where people won't know what to do anymore. Even if they know what to do, not everyone is going to give it the time of day, and they shouldn't have to.
You should look at the repositories of good distros and systems like say OpenWRT and pkgsrc, and look at the package for programs written in the same language and with the same build system as yours, and then look at the kind of patching they do to have the program the way they want. Ideally, you should learn from their build fixes and implement them without breaking other platforms, and come up with a way for them to do whatever else they want to do without touching the source code. A program should build by default on as many platforms as possible. Most customizations are easy to parametrize. Every time your source needs to be touched to build, or an option needs to be set to make the build work, that's a portability bug. Every time someone has to touch your source to enable debug symbols or set the optimization flags they want, that's a bug.
>Could you elaborate?
Put a line break in your Markdown before you reach 80 columns. That hard line break won't show up when converted to other formats. Format Markdown documents like you format source code.
>Do I need to cast the *a==*b line as well?
No. tolower()'s argument needs to be EOF or a value that can fit inside an unsigned char, otherwise it's UB.
Any char with the high bit set on a platform where char is signed is going to trigger that. That happens for instance with UTF-8 text on x86. Technically, the code doesn't work with Unicode in general even after that fix because it won't lowercase Unicode, but that's impossible to fix in Standard C, although you can come closer to something that works with the wide character interfaces. I wouldn't bother.
>>5669
I write mdoc by hand. It takes about a day to read the man page, copy a template, and fill it out to while using someone else's man page as a reference. It's not a complicated format. If you run into a system that doesn't support mdoc (you won't), it can be converted to the older, inferior Unix man format.
I recommend using OpenBSD man pages as a reference (all of its man pages use mdoc), the system also has a template in /usr/share/misc/mdoc.template
https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/share/misc/mdoc.template
https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/env/env.1