1. 51
  1.  

  2. 10

    Is your Make­file a GNU make­file, or BSD make­file?

    This question is why I recommend mk (the successor to Make).

    1. 8

      The best successor to Make I’ve seen is redo. State maintenance is much more explicit and the shell DSL is beautiful.

      1. 3

        djb writes embarassingly good software.

        1. 3

          This DJB writes embarrassingly good drafts. Then he leaves the rest of us to actually turn that into a product. 3 examples:

          • NaCl signature code is to this day marked as “experimental”
          • TweetNaCl has two uncorrected instances of undefined behaviour (left shifts of negative integers, lines 281 and 685).
          • the Redo link above is not from DJB, it’s from someone who re-implemented DJB’s idea.

          This is not a criticism. He’s very good at leading the way, and time taken to polish software is time not taken to lead the way.

        1. 4

          Better than 14 mutually incompatible implementations of the same standard.

          1. 7

            Yeah, but you can solve that with a make file. ;)

          2. 5

            Sure, and we should be okay with that. Competition is healthy.

            1. 4

              In what way do build systems “compete”? The fragmented ecosystem of open source build systems appears nothing like a market to me, it’s really strange to ascribe the ideals of markets onto that ecosystem, especially when people just use/build the toolchain that makes them happy and nearly never worry about other toolchains. There’s no real social impetus between each system.

              1. 1

                They compete for your attention, that’s really the point in writing a “new, improved” build system. It doesn’t have anything to do with market economics, aside from the concept being relevant in both it’s not something exclusive to markets

                1. 2

                  If nobody is paying attention, what attention are you competing for? What’s the point? How is that good?

                  1. 1

                    So why is it healthy?

                    I want competition when the existing solutions are poor. When the existing solutions are good, or even fine, I would much prefer standardization.

                    1. 1

                      It’s healthy because it leads to people implementing solutions that are better than the preexisting solutions. If something becomes standardised across an industry, I think we call that winning…

                      1. 1

                        So if existing solutions are good, but nonetheless 30 more less effective but specialized solutions pop up you consider that winning?

                2. 3

                  I’m not saying that it’s bad, just that the way you phrased your comment sounded a lot like “If you have to choose between A and B, take C” for any value of A, B, C.

                  But otherwise, I’ve never really recognized any major benefit that GNU Makefiles (since I use those the most) offer over Plan9’s mk. A quick look at Hume’s paper on the topic didn’t really convince me that it’s so much more advanced, especially when considering that GNU has Functions like Guile Integration.

              2. 2

                Could you share a link to it? I tried searching, and all I get are Micheal Kors, Mario Kart, Macedonia related articles and some android build system…

                1. 7

                  mk is available in plan9port (my preferred version). There is a standalone version written in Go, but is marginally incompatible (changes regex, allows for extra whitespace) which I don’t recommend (Go regex sux) but would be fine with becoming the default.

                  1. 2

                    Neat, thanks. Indeed it is way simpler and with clean semantics, which I appreciate a lot. Make has so many special cases that after a month of not using it, I have to reach for documentation to understand even simple things like assignment :/

                    I would note a nice parallel in implementing Mk in go — both assume multiple platforms and are small.

                    1. 2

                      Go regexps are guaranteed to not be stuck in an eternal loop, which is nice.

                      1. 1

                        It’s a bit sad to reflect that mk already has two incompatible variants, despite being much newer and less adopted than Make.

                        (Not meaning to bash mk specifically here, this is not a make-specific problem as much as a universal problem.)

                        1. 2

                          mk appeared in Unix version 9, more than 30 years ago. Not that much newer :-)

                          1. 1

                            Ah, right. It’s doing OK, then :)

                          2. 2

                            honestly I think the developer of the Golang version didn’t want to implement a plan 9 regex engine (probably the simplest regex i’ve ever used)

                    2. 14

                      But does it support i.e. Visual Studio?

                      “i.e.” means id est i.e., “that is”. You want “e.g.”, exempli gratia i.e., “for example”.

                      1. 6

                        For those who have trouble remembering, you can use an English mnemonic:

                        i.e. “in essence,”

                        e.g. “for eggzample,”

                        1. 2

                          Thanks!

                        2. 5

                          This is a nice overview of what some newer build systems give you. I begrudgingly switched from make to CMake at $work. I lost about a day moving a fairly simple cross-compilation workflow to CMake, but I haven’t had any issues since. However, I still disliked CMake fairly intensely due to the fact that it acted as a meta-build system; I worried that I’d run into build problems that would only be fixed I remembered the magic incantation of regenerating the Makefiles via CMake.

                          Switching to using Ninja for builds fixed that problem. If I had to do it again I think I’d try something like Meson in the hopes it’d be less goopy than CMake, but, it is more than good enough.

                          1. 12

                            Does your makefile support Windows at all?

                            This seems like a non-issue – who builds on Windows outside of an environment like cygwin EDIT: who builds non-windows-first applications on windows using windows-specific build systems, rather than unix emulation layers? Supporting users of visual studio is a project in of itself, & while there are lots of Windows users around, there are very few who have a compiler installed or are liable to want to build anything from source. It makes more sense to do builds for windows via a cross-compiler & ask folks who want to build on windows to use cygwin – both of which are substantially less effort than getting VS to build an already-working project.

                            1. 15

                              I believe that’s your experience, but you and I have radically different experiences as Windows users.

                              First, to be very blunt: Cygwin is truly awful. It needs to die. Cygwin is not a port of *nix tools to Windows; that’s MSYS. Cygwin is a really weird hacky port of a *nix to Windows. It’s basically WSL 0.0. It does not play well with native Windows tooling. It honestly doesn’t play well with Windows in general. And it’s comically slow, even compared to vaguely similar solutions such as WSL1. If I see a project that claims Windows support, and see Cygwin involved, I don’t even bother. And while I don’t know if a majority of devs feel similarly, a substantial enough group of Windows devs agree that I know my opinion’s not rare, either.

                              You’re right that Visual Studio is the go-to IDE on Windows, in the same way that Xcode is on Mac. But just as Mac users don’t necessarily bust out Xcode for everything, Windows devs don’t necessarily bust out Visual Studio. Using nmake from the command line is old as dirt and still common (it’s how we build Factor on Windows, for instance), and I’ve seen mingw-based Windows projects that happily use cross-platform gnumake Makefiles. CMake is also common, and has the benefit that you can generate Visual Studio projects/solution when you want, and drive everything easily from the command line when you want. These and similar tools designed to be used without Visual Studio are heavily used enough and common enough that Microsoft continues to release the command-line-only Windows SDK for the most recent Windows 10–and they do that because plenty of devs really do only want that, not all of Visual Studio.

                              For reasons you point out elsewhere, there’s a lot that goes into supporting Windows beyond the Makefile, to the point that concerns about cross-platform make may be moot, but “Windows devs will use Cygwin” seems reductionist.

                              1. 5

                                I don’t think windows devs use cygwin. I think that non-windows devs use cygwin (or mingw or one of the ten other unix-toolchain-for-windows environments) so that they don’t need to go through the hoops to become windows devs.

                                In other words, I’m not really sure who the audience is for OP’s argument re: building on windows.

                                If you’re building on windows & you are a windows dev, why care about make at all? If you’re building on windows & you are not a windows dev, why care about the first group at all? In my (dated & limited) experience these two ecosystems hardly interact & the tooling to make such interaction easier is mostly done by unix-first developers who want to check windows builds off the list with a minimum of effort.

                                1. 3

                                  I think you need to take into consideration that there are also libraries. Sure, if you have an application developed on non-Windows, the easiest way to port it to Windows is building it in MSYS, with MinGW, or possibly Clang. But if you develop a library that you wish Windows developers be able to use in their projects, you have to support them building it with their tools, which is often MSVC.

                              2. 8

                                who builds on Windows outside of an environment like cygwin?

                                I don’t understand this question. There are lots of software applications for Windows, each one has to be built, and cygwin is used really rarely. And CMake is precisely for supporting Visual Studio and gcc/clang at the same time, this is one of the purposes of the tool.

                                1. 2

                                  In software applications that are only for windows, supporting unix make isn’t generally even on the table. Why would you, when a lot more than the build system would need to change to make a C or C++ program aimed at windows run on anything else?

                                  It only really makes sense to consider make for code on unix-like systems. It’s very easy to cross-compile code intended for unix-like systems to windows without actually buying a copy of windows, and it’s very easy for windows users to compile these things on windows using mechanisms to simulate a unix-like system, such as cygwin.

                                  There are a lot of alternative build systems around, including things like cmake and autotools that ultimately produce makefiles on unix systems. If your project actually needs these tools, there are probably design issues that need to be resolved (like overuse of unreliable third party dependencies). These build systems do a lot of very complicated things that developers ought not to depend upon build systems for, like generating files that play nice with visual studio.

                                  1. 2

                                    In software applications that are only for windows, supporting unix make isn’t generally even on the table.

                                    Every team I’ve been on which used C++ has used CMake or FASTBuild, so supporting Unix builds at some point isn’t off the table, and it makes builds a lot easier to duplicate and simplifies CI/CD. Every project I’ve seen with build configuration in a checked-in Visual Studio solution makes troubleshooting build issues a complete nightmare since diffs in the configs can be hard to read. CMake’s not great, but it’s one of the more commonly supported tools.

                                    If your project actually needs these tools, there are probably design issues that need to be resolved (like overuse of unreliable third party dependencies).

                                    I’m not sure how this logically follows.

                                    These build systems do a lot of very complicated things that developers ought not to depend upon build systems for, like generating files that play nice with visual studio.

                                    Using CMake (or something else which generates solution files for Visual Studio), provides developers options on how they want to work. If they want to develop on Linux with vim (or emacs), that’s fine. If they want to use CLion (Windows, Mac or Linux), that’s also fine. There really isn’t that much extra to do to support Visual Studio solution generation. Visual Studio has a fine debugger and despite many rough edges is a pretty decent tool.

                                2. 2

                                  This seems like a non-issue – who builds on Windows outside of an environment like cygwin?

                                  Most Windows developers and cross-platform frameworks that I can tell.

                                  1. 4

                                    I should rephrase:

                                    Who builds cross-platform applications not originally developed on windows outside of an environment like cygwin?

                                    Windows developers don’t, as a rule, care about the portability concerns that windows-first development creates, & happily use tools that make windows development easier even when it makes portability harder. And cross-platform frameworks tend to do at least some work targeting these developers.

                                    But, although no doubt one could, I don’t think (say) GIMP and Audacity builds are done through VS. For something intended to be built with autotools+make, it’s a lot easier to cross-compile with winecc or build on windows with cygwin than to bring up an IDE with its own distinct build system – you can even integrate it with your normal build automation.

                                    1. 2

                                      I work on software that is compiled on Windows, Mac, and Linux, and is generally developed by people on Windows. We do not use Cygwin, which as gecko point out above, is truly awful. If I need to use Linux, I use WSL or a VirtualBox VM. And yes, I and my team absolutely care about portability, despite the fact that we develop primarily on Windows.

                                3. 4

                                  Thank you. Make might be a simple and elegant tool, but when you start having complex requirements like those your makefile will quickly become bloated, and when you find yourself reaching for recursive make or autotools or configure scripts… I think it’s time to throw it away and use something better. Seriously, please stop using autotools.

                                  1. 4

                                    I get that this is not the thrust of the article, but

                                    Does your Makefile support out-of-source build?

                                    Does your Makefile support cleaning the project from all autogenerated artifacts?

                                    I wonder if something like a fuse-overlayfs is a better solution than out of the tree builds. When you want to clean, simply unmount the upper directory. Now that I think about it, it may be possible to do this as an extension to GNU Make, and dynamically load it.

                                    1. 2

                                      How’s unmounting a directory easier than rm -rf’ing it? ;)

                                      1. 4

                                        If you do out of tree builds on a separate directory, then certainly rm -rf tree/build is pretty similar to umount tree. However, if you are working on an already implemented system, using overlay would be faster than figuring out how to do out of tree builds.

                                        1. 1

                                          OK, but still:

                                          • You have to remember to mount an overlay if the build system doesn’t support it automatically. In case you forget just once, then it’s probably rm -rf && git clone again,
                                          • Your OS has to support such overlays (does Windows support it?),
                                          • You have to have a very complete .gitignore file that lists all autogenerated file groups, so that git status output will be clean,
                                          • You have to actually learn how to use overlayfs,
                                          • You can only have 1 configuration of the project active at the same time. I.e. switching Debug/Release/ReleaseWithLogs builds require recompilation of the whole project (at least for some languages like C++).

                                          In case of out-of-tree builds, I think there are no dependencies at all, it’s just a different directory than the source code directory. It can be on tmpfs, a network share, an encrypted container, and you can have multiple build directories with different configurations of the project at the same time, and then changing 1 thing in the source code would only compile missing pieces in each of the out-of-tree build dirs.

                                          1. 2

                                            You have to remember to mount an overlay if the build system doesn’t support it automatically. In case you forget just once, then it’s probably rm -rf && git clone again,

                                            Probably just git clean -xfd if you forget :).

                                            You can execute the mounting it as the first dependency for all targets. Also, I propose to autoload it in Makefiles, which can remove all such problems.

                                            Your OS has to support such overlays (does Windows support it?),

                                            Windows filesystem proxy.

                                            You have to have a very complete .gitignore file that lists all autogenerated file groups, so that git status output will be clean,

                                            What I am suggesting is a build directory that has the checked out tree as the lower directory, and actual build directory as the upper directory. So one can simply do git status on the tree directly.

                                            You have to actually learn how to use overlayfs,

                                            It is much more simpler than learning to use cmake. Also, it might be possible to make it automatic – see first point.

                                            You can only have 1 configuration of the project active at the same time. I.e. switching Debug/Release/ReleaseWithLogs builds require recompilation of the whole project (at least for some languages like C++).

                                            Not really. You can have multiple overlays for different phases of compilation.

                                    2. 2

                                      Might be worth using Make in addition with Nix, so many of the questions become irrelevant, for example out of tree build.

                                      1. 2

                                        Overall, I think the answer is yes, at least for the types of projects I work on.

                                        Which compiler does your Makefile support?

                                        One that accepts the POSIX-specified options, and also supports common warning flags like -Wall, -Wextra, and -pedantic. But at least I can choose whatever compiler I wish, meson only accepts a hard-coded list of compilers: https://github.com/mesonbuild/meson/issues/5406

                                        Does your Makefile support out-of-source build?

                                        No, this is difficult with POSIX make, and something I wish could be done easily.

                                        Does your Makefile support Windows at all?

                                        Usually I’m not concerned with this, since my projects don’t target Windows. Does nmake support POSIX makefiles?

                                        Is your Makefile a GNU makefile, or BSD makefile?

                                        Both, just make sure to follow the POSIX standard.

                                        Does your Makefile support cleaning the project from all autogenerated artifacts?

                                        Yes, with a phony clean target.

                                        Do you support a situation when the compiler/SDK will be upgraded on the system?

                                        Do you track the dependencies on the libraries installed in the system?

                                        No, the user will have to clean and rebuild.

                                        Do you support setting a Release/Debug build of your project?

                                        Any build-type is supported, the user just sets the CFLAGS and LDFLAGS they want.

                                        Does your Makefile support passing custom CFLAGS or LDFLAGS?

                                        Yes, they can set them in the environment.

                                        Are you using thirdparty libraries in your project?

                                        Preferably not, but if I do, they are detected with a small configure script using pkg-config, flags, and/or environment variables.

                                        I don’t want to use CMake, because the project is small and it’s not worth it.

                                        If I use CMake, that’s an additional build-type dependency, and also one that requires a C++ compiler, even if my project is in C. make is available almost everywhere.

                                        What if someone just wants to use Eclipse, Xcode, Visual Studio, CodeBlocks, etc?

                                        I’m not familiar with those tools, but surely they have a way to invoke make and show the output somewhere?

                                        Does your Makefile support showing the full command line used to compile a compilation unit?

                                        Yes, make does this by default.

                                        1. 1

                                          Just two points:

                                          1. Even if you’ll get it right, it doesn’t mean that other people will also get it right,
                                          2. For each ‘no’ in this list, there’s a CMake build script that makes you forget the issue exists, it just supports it.
                                          1. 1

                                            It’s just as easy to get a CMake build script wrong as it is to get a Makefile wrong. I’ve seen some atrocious CMake build scripts, and some brilliant Makefiles. I’ve also seen great CMake scripts and awful Makefiles!

                                            Just because you get CMake right doesn’t mean others will.

                                            1. 1

                                              That’s true.

                                              But it’s easier to write a good CMake script than a good Makefile script, even only because CMake has a lot of things already implemented, and people don’t need to re-do it in a wrong way.

                                        2. 1

                                          nothing is easier than simply removing the build directory with rm -rf

                                          make clean may not be easier, but it is safer. Type a * or ~ by accident, or insert a space by accident, and unfortunate things may happen.

                                          rm -rf . ./build for instance

                                          1. 1

                                            For C projects, I use a very very simple Makefile that starts off as basically the following:

                                            ifeq ($(BUILD),release)
                                            	CFLAGS += -O3 -s -DNDEBUG
                                            else
                                            	CFLAGS += -O0 -g
                                            endif
                                            
                                            TARGET    := a.out
                                            
                                            PC_DEPS   := sdl2
                                            PC_CFLAGS := $(shell pkg-config --cflags $(PC_DEPS))
                                            PC_LIBS   := $(shell pkg-config --libs $(PC_DEPS))
                                            
                                            SRCS      := $(shell find src -name *.c)
                                            OBJS      := $(SRCS:%=build/%.o)
                                            DEPS      := $(OBJS:%.o=%.d)
                                            
                                            INCS      := $(addprefix -I,$(shell find ./include -type d))
                                            
                                            CFLAGS    += $(PC_CFLAGS) $(INCS) -MMD -MP -pedantic -pedantic-errors -std=c89
                                            LDLIBS    += $(PC_LIBS) -lm
                                            
                                            build/$(TARGET): $(OBJS)
                                            	$(CC) $(OBJS) -o $@ $(LDFLAGS) $(LDLIBS)
                                            
                                            build/%.c.o: %.c
                                            	mkdir -p $(dir $@)
                                            	$(CC) -c $(CFLAGS) $< -o $@
                                            	@$(RM) *.d
                                            
                                            .PHONY: clean syntastic
                                            clean:
                                            	rm -f build/$(TARGET) $(OBJS) $(DEPS)
                                            
                                            syntastic:
                                            	echo $(CFLAGS) | tr ' ' '\n' > .syntastic_c_config
                                            
                                            release:
                                            	-$(MAKE) "BUILD=release"
                                            
                                            -include $(DEPS)
                                            

                                            That should be sufficient for pretty much any C project, frankly.

                                            If I need anything extra, it’s very simple to add. For example, one project needs to run a third-party assembler to generate object files, then uses a python script to convert those binary object files to hexadecimal text files that can be #included into a .c file. If the assembly file is changed, it should be handled automatically like any other dependency. For that I only need to add the following, and add $(EX_BINS) to clean:

                                            EX_SRCS   := $(shell find asm -name *.dasm16)
                                            EX_BINS   := $(EX_SRCS:.dasm16=.bin)
                                            EX_HEXS   := $(EX_BINS:.bin=.hex)
                                            
                                            %.bin: %.dasm16
                                            	dtasm --binary $< -o $@
                                            
                                            %.hex: %.bin
                                            	python3 utils.py $< > $@
                                            

                                            Which compiler does your Makefile support?

                                            Does your Makefile support Windows at all?

                                            Is your Makefile a GNU makefile, or BSD makefile?

                                            GNU/GCC and everything that supports their most basic extensions, like -MMD -MP. A lot of GNU extensions have become the de facto standard. I have zero interest in writing a more complicated Makefile or using the overly complicated mess that is CMake to support Windows or barebones hobbyist project C compilers.

                                            Does your Makefile support out-of-source build?

                                            Yes. build/.

                                            Does your Makefile support cleaning the project from all autogenerated artifacts?

                                            Do you support a situation when the compiler/SDK will be upgraded on the system?

                                            Do you track the dependencies on the libraries installed in the system?

                                            Yes. clean.

                                            Do you support setting a Release/Debug build of your project?

                                            Does your Makefile support passing custom CFLAGS or LDFLAGS?

                                            Does your Makefile support showing the full command line used to compile a compilation unit?

                                            Yes.

                                            Are you using thirdparty libraries in your project?

                                            Yes. Add the library to PC_DEPS. pkgconfig is used, hence the name.

                                            I don’t want to use CMake, because the project is small and it’s not worth it.

                                            The example given doesn’t support third-party libraries, doesn’t support generating .syntastic_c_config so that my editor knows what cflags to compile files with to generate the correct set of syntax errors in my editor, doesn’t have any CFLAGS set, etc.

                                            What if someone just wants to use Eclipse, Xcode, Visual Studio, CodeBlocks, etc?

                                            Do they support running make? Yes if so.

                                            1. 1

                                              Do they support running make? Yes if so.

                                              Useful IDE support is not that simple.

                                              In order to perform autocomplete, the IDE needs to be able to load all of the header files that will be included from your currently open C file, so that it can figure out all functions that are in-scope.

                                              • This means it needs to be able to figure out all of the -I parameters that you are passing to your compiler, to actually find the headers.

                                              • It is also useful to know all preprocessor definitions, like the -D flags and platform-default ones like __linux (meaning the IDE needs to know the target platform), and the version of C that you’re targeting, so that it can actually parse those header files correctly.

                                              • The IDE also wants to know the full set of C source files, for jump-to-definition purposes.

                                              In other words, an IDE basically has to have access to all of the information that’s necessary to actually compile your code, in order to correctly parse your C code the same way a compiler does, in order to provide correct and complete autocomplete and jump-to-definition. If I don’t get those two features, there’s not much point in using an IDE.

                                              A naive approach would be to override PATH before running make, so that instead of calling the compiler, make would instead call a wrapper that sneaks the compiler flags over to the IDE for its use. I doubt actual IDEs do this, if only because that would prevent you from editing the project until after the code has been compiled at least once.

                                              1. 1

                                                autocomplete, jump-to-definition

                                                That’s what ctags is for.

                                                It is also useful to know all preprocessor definitions, like the -D flags and platform-default ones like __linux (meaning the IDE needs to know the target platform), and the version of C that your targeting, so that it can actually parse those header files correctly.

                                                Conditionally including headers is a kind of fucking awful idea that leads to people wanting to use overly complicated build systems.

                                                1. 1

                                                  That’s what ctags is for.

                                                  Let’s say my application wants to link to the Ruby interpreter. I would, presumably, add it to the PKG_SRC section of the makefile. This results in -I/usr/include/x86_64-linux-gnu/ruby-2.3.0/ being passed to my compiler parameters. My code can now use #include <ruby/config.h>, and the compiler will find it. Awesome.

                                                  But your makefile only makes that information available to the compiler. How’s ctags going to know to include the symbols in the ruby installation in its tagslist?

                                                  Conditionally including headers is a kind of fucking awful idea that leads to people wanting to use overly complicated build systems.

                                                  You got a better way to have my application use epoll on linux and kqueue on freebsd?

                                                  1. 1

                                                    You got a better way to have my application use epoll on linux and kqueue on freebsd?

                                                    include/networking.h
                                                    src/networking-linux.c
                                                    src/networking-freebsd.c
                                                    

                                                    The whole point of header files is that they’re an interface that can have more than one implementation.

                                                    But your makefile only makes that information available to the compiler. How’s ctags going to know to include the symbols in the ruby installation in its tagslist?

                                                    .PHONY ctags
                                                    ctags:                                                                                                                                                     
                                                            gcc -M $(INCS) $(PC_CFLAGS) $(SRCS) | sed -e 's/[\ ]/\n/g' | \                                                                                     
                                                                    sed -e '/^$$/d' -e '/\.o:[ \t]*$$/d' | \                                                                                                   
                                                                    ctags -L - $(CTAGS_FLAGS)
                                                    
                                                    1. 1

                                                      And now you’re adding ctags support to the makefile. Which was exactly my point; either the makefile needs to support the IDE, or the IDE needs to do a lot more than “just call make.”

                                                      1. 1

                                                        ctags isn’t an IDE. It’s a universal standard, much like pkg-config. Adding a couple of lines to a Makefile to support something like ctags or pkg-config is fine to me because it’s the same for every project and it should work with every development environment, integrated into one program or not.

                                                        The real question is: does your proprietary IDE support ctags? Does it support running make? Does it support lots of other universal standards? Or does it insist on proprietary crap like Visual Studio does?

                                              2. 1

                                                I’ve no idea why you think your GNU-only UNIX-only Makefile template is better than a universal all-system 3-line CMakeLists.txt script.

                                                The example given doesn’t support third-party libraries

                                                This is a common problem in C and C++. It is handled by CMake by using add_subdirectory (concept similar to recursive make), or e.g. externalproject_add if the thirdparty library uses a different build system than cmake.

                                                doesn’t support generating .syntastic_c_config

                                                It supports generation of compile_commands.json by adding 1 line:

                                                set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
                                                

                                                It seems that syntastic supports compile_commands.json generated by CMake as well as 10 other tools… IDEs included.

                                                Does your Makefile support out-of-source build?

                                                Yes. build/.

                                                I’m not sure this counts, as it depends on generation of dependency files inside the source tree and deletes them after generation.

                                                That should be sufficient for pretty much any C project, frankly.

                                                Not if you try to build multi-platform software that supports non-Unix systems.

                                                By releasing your Makefile in your projects you’re simply making it harder for people to use your project.

                                                1. 0

                                                  I’ve no idea why you think your GNU-only UNIX-only Makefile template is better than a universal all-system 3-line CMakeLists.txt script.

                                                  Because in practice, a GNU-only UNIX-only Makefile works on everything that isn’t Windows. And because the CMakeLists.txt script doesn’t do anything this does. It doesn’t support dependencies, multiple source files, pkg-config or anything else it needs to support.

                                                  This is a common problem in C and C++. It is handled by CMake by using add_subdirectory (concept similar to recursive make), or e.g. externalproject_add if the thirdparty library uses a different build system than cmake.

                                                  That requires the third-party library to support CMake: you have to have a FindXXXX.cmake file. Meanwhile, using pkg-config, which is the standard for handling dependencies, is trivial. Relying on third-party projects to support every list of random build systems is crazy, and relying on the build system and community around it to support every library under the sun is also crazy.

                                                  There’s already a standard: pkg-config. Use it.

                                                  I’m not sure this counts, as it depends on generation of dependency files inside the source tree and deletes them after generation.

                                                  No, it does not. The dependency files go in build/. I can show you the output of ls -lR if you’d like. You should probably learn how it works before you comment inaccurately about it.

                                                  Not if you try to build multi-platform software that supports non-Unix systems.

                                                  So in other words: not if you write software for Windows that for some reason can’t rely on WSL. Even Microsoft understand that Windows needs to catch up with the rest of the universe and support basic standard shit every other operating system supports.

                                                  By releasing your Makefile in your projects you’re simply making it harder for people to use your project.

                                                  My projects don’t support Windows anyway. Why would I care if my build script works on Window if the bloody software it’s building doesn’t? Try to think before you comment next time.

                                                  1. 1

                                                    Your lack of comprehension of this issue is troubling. You’re asserting arguments which are simply far from truth. I’ll refrain from answering those arguments because up to the half of your comment, literally every sentence is dead wrong. You also seem to have little idea how Windows development looks like.

                                                    It’s true that I’ve only skimmed over your build script instead of analyzing it, because I don’t want to waste time on it. It might be a surprise to you, but your script contains lots of hidden complexity in it, and lots of hidden concepts. If you fail to see this, it might suggest you simply don’t have as much experience in professional programming as you think, and I’m not saying this to try to offend you. This is the reason I prefer cleaner solutions that abstract complexity as much as possible. Tools like CMake or Meson offer many tools to do this. They’re far from perfect, but they’re a start.

                                                    The thing is, I’m not trying to convince you to switch to CMake. I’m simply not interested in what you use. I’m interested in not having to rewrite build scripts of people who think other people should use their programming environment, and who think that introducing a mammoth dependency like WSL even resembles a sane idea. I’ll benefit if I’ll be able to convince a large group of people to use tools like CMake. You don’t have to be a part of this group, and that’s fine.

                                                    1. 0

                                                      God you really are incredibly confused, aren’t you? You’re reminding me why I stopped commenting here a while ago: it’s full of people that can’t read. I don’t care how Windows development looks or works. I don’t do it. I don’t intend to do it. I don’t use a Makefile for Windows development, clearly and obviously. I have stated that extremely clearly, and here you are continuing to claim that it’s wrong because it doesn’t support Windows.

                                                      Well guess what, buddy, there’s no point making your Makefile more portable than the software it’s building! Not sure why you fail to understand this so spectacularly. I don’t need to know ‘how Windows development looks like’ to know that writing a perfectly portable build system for software that isn’t actually portable is pretty bloody pointless.

                                                      Literally every sentence I wrote in my entire comment were objectively correct, and if you pick one I will happily explain to you why. I’m not going to go through and defend them without you prompting me to properly though. There’s very little point explaining why they’re correct to someone so stupid that the best thing they can come up with is simply describing them as ‘dead wrong’. If you think they’re wrong, explain to me why you think they’re wrong and it’ll be a learning experience for at least one of us. :)

                                                      If you genuinely believe that there’s value in having a build system more portable than the software it actually builds, at the cost of introducing a huge overly complex dependency like CMake that requires lines upon lines upon lines of code to do anything remotely useful vs. just using a simple tool like make that does everything CMake does in what, 20 lines? Then I don’t know what to say. You must have some serious issues. CMake does not ‘abstract complexity’ and nothing about it is ‘clean’. It litters useless shitty files all over the place, it requires every single dependency you have to also use it, it’s just a mess. A damn mess.

                                              3. 1

                                                I’ve ran into every single one of these problems :(

                                                I don’t really like any of the alternative C build systems, so I keep trying to get make “right”, but it just always ends up being a pain point.