> Before mesom/ninja, you had one problem - install gmake.
No, you had as many problems as there are '%' and '$' symbols in this web page : http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ multiplied by the number of permutations of tools in the different platforms you want to support, e.g. (gcc-mingw-windows, clang-cl-windows, msvc-windows (this one counts as 10), xcode-macos, gcc-macos). And let's not even get started with cross-compiling.
Ninja is generic and minimalist. You can use it for anything that can be defined as a command with inputs and outputs.
Writing ninja files by hand is tedious and those extra features make provides can make it easier to use, but in principle ninja should be able to handle anything make could.
I tried using meson for https://github.com/shlomif/mini-factor , and while it worked fine locally it turned out to require python 3.6 which made it hard to install on Travis-CI. I ended up created a complementary cmake build system.
Make is a much of a build system as C++ as you can call stat() and system() from it.
A modern build system by default should be able to provide utilities to make sure your build is correct and reproducible. Those features need to be coded into your Makefile and aren't available easily or by default.
If you need to code those rules, then you don't have a build system, just a way to run commands and possibly add some (usually poor) logic around them.
A typical example that most handcrafted Makefiles will fail is that changing a build flag should only rebuild the files affected. Most will either require a full clean (aka ignoring the flag change) or rebuild everything.
I've noticed a plethora of build options over the past decades. I keep hearing how they are all "better" than make.
Then to build one particular bit of software, there is a dependency upon a particular version of cmake, which you don't have.
Or you have to upgrade Maven. Or install some software you do not have by default on your environment.
I've never had to do that with make.
I've been told that other tools are better because the are simpler ... that is ... until you run into one of those aforementioned compatibility issues with the build tool.
This isn't an infrequent occurrence for me, I see lots of hardwiring for various packages that I don't have installed by default in some projects.
Then you get the gophers/rust folk, and their need to run on the most recently released kit. With all its undiscovered bugs. The gophers want to replace make with mage ... well, to be more correct, they want to replace every non-go based tool with one built in go, because ... go. A modern version of the insufferable pythonistas of years past.
Throughout this, I've been using and building with Make just fine. My make files do the heavy lifting in my projects. And I get a good laugh each time I hear "oh I have to fix my magefile/CMakeFile.txt/yadda yadda yadda".
As the great philosopher Inigo Montoya once opined ... you keep using that word [better]. I do not think it means what you think it means.
I find gnu make very usable and very clear on its purpose. Sometimes I have used cmake and it was uglier, more complicated, and harder to understand. What would you suggest as a modern, usable build system?
This will compile the code from lib*.c into libmine.a, and then compile the source code of a few test executables from foo.c, bar.c and baz.c
The .a is useless often, but there you have it just in case.
Otherwise, just remove all references to $(LIB) and get a shorter makefile.
> you can't seriously say that this (which covers an immense part of software project needs) is easier to do in make, right ?
This is rather subjective. In my case the makefile seems easier. It will work for all unices, but probably not for windows, and will not create an "app" package, your are right about that.
But the makefile covers indeed all my personal needs, and it is much more powerful and easier to use than the cmake/make combo. For example, you can test multiple compilers and compiler options with a shell loop:
# test all compilers in debug and release modes
for i in gcc clang tcc icc; do
for m in "-O3 -DNDEBUG" "-g"; do
make clean check CC=$i CFLAGS=$m
done
done
doing that in cmake would be a nightmare, wouldn't it?
> You just compile with -lpng. If libpng is available, it will work, otherwise it will fail with a clear error message. What else do you need?
well, no you don't "just compile", because one of the most used compilers out there does not support "-l". Also because you may have multiple libpng versions on your machine - debug, with special testing flags, in your ~/work/libpng_build, etc.
Also, you may have libpng.so but not the headers. You may be compiling on Nix or GoboLinux or whatever system which does not respect the FHS. It won't work as is on OS X because you have to add -L/usr/local/lib. Users won't know what to do when they see whatever missing include error the compiler spits out.
> doing that in cmake would be a nightmare, wouldn't it?
.. it would be mostly the same than your example ? just tested and this works fine (normal practice with cmake is to build outside of src which helps):
for i in gcc clang; do
for m in "-DCMAKE_BUILD_TYPE=Debug" "-DCMAKE_BUILD_TYPE=Release"; do #not using -g because that's something compiler-specific
rm -rf ** ; CC=$i cmake ../ $m ; cmake --build .
done
done
Spare your fingers ;) - you'll never convince anybody of the value of cmake by telling them about it. You just have to put them in a situation where they're looking after a program that has to build on multiple desktop platforms, and they'll figure it out eventually...
(The combination I've always had to deal with is Linux, OS X and Windows/VC++ - but any combination that includes both Windows/VC++ and a POSIX-type OS is probably enough to make it worthwhile. The POSIX/non-POSIX differences are rather annoying to deal with otherwise, and that quite apart from how most Windows programmers will quite reasonably want to use a Visual Studio project rather than a Makefile.)
Yeah, CMake and autotools solve different problems than make. I'm definitely not a fan of either one but if I need to really distribute and compile something on more than one OS there isn't much of a choice.
The posted makefile example fails right away on multiple platforms since headers are often in somewhere else than in /usr/include directly, for example in Debian the right (atm) path would be /usr/include/libpng16 and Makefile does not handle that.
> The posted makefile example fails right away on multiple platforms since headers are often in somewhere else
And that's the intended behavior. Finding system headers around your disk is not a problem that a build system must try to solve. This is the task of a distribution or a packaging system, which is a different problem as you say.
Yeah I agree, it's not the ideal situation but it is the real world. Simple makefiles do not work often and there are systems that can solve the problem. Not elegant, brilliantly designed tools but ones that work anyway.
I hope this day never arrives for me... In any case, if I ever had to compile something for windows I would rather install cygwin and a posix toolchain than cmake and visual studio.
Thanks for your answer, I see that cmake is not as cumbersome as I thought.
> Also, you may have libpng.so but not the headers.
Then how on earth are you supposed to compile it? You write the definitions verbatim on your code?
> It won't work as is on OS X because you have to add -L/usr/local/lib.
For that case it is better to not mess with compiler options and set up the compiling environment so that -lpng works, e.g. by setting LIBRARY_PATH=/usr/local/lib, and similarly for C_INCLUDE_PATH. These variables are recognized by all unix linkers and compilers that I care about.
Of course, this attitude may not be appropriate for everyone. Yet, I am in the happy position to be able to say say "this program requires gcc, clang, tcc or icc to be compiled, otherwise, please edit the makefile to suit your needs". Are there really other C compilers around? (notice that visual studio is not a C compiler, and cannot compile modern C code, so it does not enter into the discussion if you are a C programmer).
For example it checks the last modified time on all your files, every build. This doesn’t scale at a certain point. More modern build systems have better ways of doing this.
[1] https://mesonbuild.com/
[2] https://ninja-build.org/