1. 27

    1. 4

      While small on the surface, it can’t stand alone — it includes bsd.prog.mk has some, ahem, complexity.

      (I couldn’t tell if your comment implies BSD makefiles are hairballs or if it implies they’re simple ;))

      1. 3

        bsd.prog.mk is quite the library, but CMake is much larger; I think it was meant positively.

    2. 5

      I played around with Meson a bit, it is really nice!

      1. 5

        Several people here are recommending CMake as an alternative. I’ve only interacted with CMake at a fairly surface level, but found it pretty unwieldy and overcomplicated (failed the “simple things should be simple” test). Does it have merits that I wasn’t seeing?

        1. 3

          CMake can generate output both for Unix and for Windows systems. That’s one (good) reason lots of C++ libraries use CMake.

          1. 2

            CMake is pretty nice and has nice documentation. You can also pick stuff up from reading other people’s CMakeLists. For simple projects the CMake file can be pretty compact.

            1. 3

              I actually found the CMake documentation to be quite terrible for new users. The up-to-date documentation factually describes what the different functions do, but has very little examples of how to actually write real-world CMake scripts. There are a few official tutorials that try to do this, but they are made for ancient versions like CMake 2.6. So in order to learn how to use CMake, you are stuck reading through tons of other peoples scripts to try to deduce some common best practices.

              While modern CMake is not terrible, you often have to restrict yourself to some ancient version (2.8.6 I believe is common) in order to support certain versions of CentOS/RHEL/Ubuntu LTS (and there were some big changes in CMake around 2.8.12/3.0).

              Also, having string as the only data type has led to some absurd corner cases.

          2. 4

            I find the definition the author is hinting at for “simple” to be odd.

            1. 4

              The example given by the author sound hacky more than anything, to “discover” source files.

              I’ve been using makefiles of this kind for years now, and it works remarkably well. I do that so they’re easy to package, regardless of the distro. I must admit my projects are fairly simple, but I never missed any “feature” with this makefile. I’m probably missing something here though so feel free to tell me!

              1. 1

                I use a very similar makefile for my own projects. It doesn’t support header dependencies, though, and separate (out‐of‐tree) builds would be nice. I’ve been considering adding a (non‐autotools) configure script to the mix for that reason.

                1. 1

                  The example I gave doesn’t have header files, but you can easily add them to the mix (example). For out-of-tree build, I don’t get the point of it. Is it only to keep the source tree clean? I’ve seen some handmade configure script in the wild as well, pretty short ones (some only included the line “echo do not use autotools!”). In my case, they would generate the config.mk file, which includes all the customizable bits. IMO, customization should be done at the environment level, and with make -e. That is the reason why I like mk a lot, which does that by default (but that’s another topic!)

              2. 3

                I think I’m missing something here. A lot of the deficiencies for the simple examples he gives are pretty easily fixable. And his simple example is… not very simple.

                If you cargo cult a Makefile from a rando Internet page, and you have a big hairy project, then, yeah, it will be ugly.

                The only build system that has impressed me so far is Stack and Cargo, and they are confined to single language ecosystems. Perhaps a language agnostic build system is a better idea in theory than in practice?

                1. 1

                  The only build system that has impressed me so far is Stack and Cargo, and they are confined to single language ecosystems. Perhaps a language agnostic build system is a better idea in theory than in practice?

                  Have you tried nix?

                  1. 1

                    I’m interested in what impressed you about Cargo and stack. If you have time to elaborate (details please!), I’d appreciate it.

                    I ask as a Pony core team member who is quite satisfied with make but very interested in what people like and dislike in the single language tools they use.

                    1. 1

                      One good lesson is to have two files for dependencies, unlike Python pip for example.

                      One file should be a compact list of direct dependencies. Version numbers are optional. Use that to specify. Should be in version control with your code.

                      Another file contains all (transitive hull) dependencies with exactly the version numbers which are used. Use that to make builds repeatable. You may or may not check this file into version control.

                      (Technically, It is not necessary to use two files, but it seems pragmatic)

                  2. 2

                    I love make for automating data processing. Build stuff, measure something, generate report, then tweak something and repeat. The makefiles that grow there are simple.

                    Still, for building C code, I would try cmake in a greenfield project.

                    1. 1

                      I honestly haven’t done C/C++ programming in a while, but I also found autotools / the traditional configure/make to be a lot of code generation code smell.

                      Isn’t this why we have newer tooks like cmake? I’ve noticed a lot of projects I use today use cmake or some other non-terrible build tool.

                      I can see legacy projects keeping their makefiles and autotools, but if you’re green fielding, you should look at all the tools and try not to use ones that are decrepit and old or too new and shiny (unless you’re willing to invest a lot into helping the new and shiny took be better and contribute to it as part of your work). You want relatively new and lot of use and support.

                      I’ve found personally, don’t use Maven .. don’t even use SBT, use Gradel for JVM projects. Use cmake instead of autotools. Most modern languages have their build system built in (like cargo for rust or mix for Elixir), but if you’re doing node or electron, you probably want to use yarn instead of npm, and pip is pretty much the standard on Python instead of setuptools. Also don’t use virtualenvs for Python/Ruby; just use Docker containers and let them build out the requirements.txt or the gem bundle.

                      I should really do a blog post on build systems …

                      1. 4

                        I don’t think cmake is a good example here; it generates a lot of Makefile and associated stuff, and the language itself is kind of awful. It mostly benefits from not having to deal with the assumptions autotools was built on, like supporting SysVr3 on m88k or Pyramid.

                      2. 0

                        You don’t want to manually write makefiles. Use Autotools instead: https://autotools.io/index.html

                        1. 14

                          Why not, its completely fine to write “simple” makefiles for “simple” projects. I think the musl makefile is a good example for a not so simple but still simple makefile.

                          To me autotools generated makefiles are a hell to debug, just slightly less hellish than debugging cmake.

                          1. 5

                            The musl makefile is one of the cleanest production makefiles I’ve ever seen. But I note even its opening comment says, “This is how simple every makefile should be… No, I take that back - actually most should be less than half this size.”

                            I count, at least, 3 languages used:

                            1. GNU dialect of make
                            2. shell
                            3. sed

                            And hacks like this:

                            obj/musl-gcc: config.mak
                            	printf '#!/bin/sh\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@
                            	chmod +x $@
                            obj/%-clang: $(srcdir)/tools/%-clang.in config.mak
                            	sed -e 's!@CC@!$(WRAPCC_CLANG)!g' -e 's!@PREFIX@!$(prefix)!g' -e 's!@INCDIR@!$(includedir)!g' -e 's!@LIBDIR@!$(libdir)!g' -e 's!@LDSO@!$(LDSO_PATHNAME)!g' $< > $@
                            	chmod +x $@

                            Local legend @andyc of Oil Shell fame pushes the idea that Shell, Awk, and Make Should Be Combined. IMHO, the musl example is persuasive empirical evidence for his position.

                            (I’m hoping @stefantalpalaru is being sarcastic about Autotools and we’re all falling to Poe’s Law.)

                            1. 2

                              (I’m hoping @stefantalpalaru is being sarcastic about Autotools and we’re all falling to Poe’s Law.)

                              No, I’m not. I’ve worked with hand written Makefiles, Autotools and CMake on complex projects and I honestly think that Autotools is the lesser of all evils.

                              Local legend @andyc of Oil Shell fame

                              Now I hope you’re the one being sarcastic. Who exactly uses the Oil Shell?

                              1. 3

                                Now I hope you’re the one being sarcastic.

                                I was not being sarcastic. @andyc’s Oil Shell posts consistently do well in voting here.

                                Who exactly uses the Oil Shell?

                                Who uses a less than a year old shell that explicitly isn’t for public use yet? I’m hoping very few people.

                                What does the number of Oil Shell users have to do with his argument?

                          2. 7

                            Err. Last time I touched autotools it was a crawling horror.

                            Makefiles are fine. Just don’t write ones that call other makefiles (recursive make considered harmful and all that).

                            1. 4

                              Just don’t write ones that call other makefiles (recursive make considered harmful and all that).

                              Clearly someone needs to write “Make: The Good Parts” 😂

                              1. 2

                                Isn’t non-recursive make also considered harmful?

                                1. 2

                                  I think the ideal is a makefile that includes parts from all over your source tree, so that there’s one virtual Makefile (no recursive make invocation O(n^2) issues) but changes can be made locally. Best of both worlds!

                              2. 5

                                I’m no expert on Make or Autotools, but my response to building automation on top of an automation tool is: “Please, god, no!”

                                If your automation tool lacks the expressiveness to automate the problem your solving, the solution should never be to bolt another automation tool on top of it. It’s time to start over.

                                1. 2

                                  I’m going to take a guess that you’re not a DevOps engineer.

                                  1. 1

                                    “Lets just use another layer of automation!” is the DevOps version of solving every problem with another layer of indirection clearly! :)

                                  2. 1

                                    But why not? One tool (cmake, meson) checks dependencies and works on high-level concepts such as “binary”, “library”. Other tool (make, ninja) is low-level and operates on building individual files. It’s sane separation of concerns.

                                    Make, however, tries to be high-level (at least GNU make, it even has built-in Scheme), but not enough high-level and it might be better at low level (that’s why ninja was invented).

                                    Monolith build tools like Bazel might better handle invalidation but this class of tools is not explored enough (existing tools are designed for specific Google/Facebook’s use cases).

                                  3. [Comment removed by author]

                                    1. 3

                                      Autotools is terrible.

                                      Yes, but all the alternatives are worse.

                                    2. 1



                                      And look how complicated this configure script is which doesn’t take 60 seconds to run: