Live data from Hacker News

Practical Makefiles, by example

nuclear.mutantstargoat.com

21–29 of 29 posts

Re: Practical Makefiles, by example

#21
post #3

I disagree with this. I don't find CMake any less easy to use than make in the simple case, but it is far better than Autotools in the complex case. Just learn CMake and be done with it. As a bonus, it saves you some typing making your program cross-platform, although that is a pain no matter what tool you're using.

CMake works really well when you are building a normal user space application with only popular libraries (or ones that use CMake themselves) as dependencies that CMake can find and configure. Some CMake generators are better than others (e.g. ninja-build is really nice with CMake). Creating MSVC Project files was badly broken the last time I tried and even when it worked, the resulting project files are awkward for MSVC IDE users (I prefer nmake makefiles if compiling on Windows with MSVC).

CMake falls apart when you try to do something more complicated, e.g. building a bootable kernel image which requires special handling for compiling and/or linking. I have done a bare metal project using CMake and GNU Make and the latter was a lot easier.

To name a few other platforms where using GNU Make works better: Android NDK (default Android.mk build system is GNU Make, there are CMake-based hacks for Android but they were atrocious) and doing micro controller work like Arduino (when writing C, not using the Arduino language).

To give an example where CMake works a lot better than GNU Make is cross compiling, e.g. building Windows binaries on a Linux host. All it takes is a few lines of "toolchain specs" and apt-getting the mingw toolchain. But even this falls apart when you need to build both, "host" and "target" binaries like you often need with hardware projects.

CMake is by no means perfect and GNU Make is still a very useful tool to know.

Re: Practical Makefiles, by example

#23
post #19
post #5

One other dependency often forgotten is on the Makefile itself. This way if the Makefile changes, everything gets rebuilt: DEPS = Makefile %.o: %.c $(DEPS) $(CC) $(CCFLAGS) -o $@ -c $

This may or may not be what you want, depending on the use case. If you change an important variable in the Makefile (e.g. CFLAGS), you might want to recompile everything. However, if you're just adding a new source file to the Makefile, you definitely do not want to rebuild everything. I prefer to run `make clean` manually when necessary rather than adding a rule to rebuild everything "just in case". But I can imagi…

I like to put CFLAGS/CXXFLAGS et al in separate files that just define the corresponding macro. These get included in the makefile which has dependencies added to rules that reference such a macro on the file that defines the macro. E.g. the .o rule for C++ has a dependency on the CXXFLAGS which defines CXXFLAGS. Change CXXFLAGS and things rebuild, mess with LDFLAGS and you re-link etc... Handy if you need it but you can end up with lots of little files.

Re: Practical Makefiles, by example

#25
post #18

To anyone implementing the automatic dependency generation mentioned in this article, you can actually make things even simpler by combining the compiling and dependency steps. This works because if you add a new dependency to a file, that information will only be needed for the next build - the current file will already be considered out of date seeing as it was edited to add the #include. gcc -MD -MP foo.c -o foo.o…

I second this, using CFLAGS=-MMD or -MD makes writing a Makefile a lot more simpler. This also gets rid of the need to add a rule for building dependency files and you can rely on the built-in rules (see `make -p`) to build object files. A good Makefile should have any rules for building object files if you're using a language like C or C++, which Make has built-in rules for. If using another language, adding a few g…

I can't say I share your love for make's built in rules. I find using them often just makes the build system harder to understand and debug. I usually disable all of the built in ones using:

  # Disable built in suffix rules
  .SUFFIXES:

  # Disable builtin pattern rules
  MAKEFLAGS+=-r

Re: Practical Makefiles, by example

#26
post #18

Earlier quoted context omitted.

I second this, using CFLAGS=-MMD or -MD makes writing a Makefile a lot more simpler. This also gets rid of the need to add a rule for building dependency files and you can rely on the built-in rules (see `make -p`) to build object files. A good Makefile should have any rules for building object files if you're using a language like C or C++, which Make has built-in rules for. If using another language, adding a few g…

I can't say I share your love for make's built in rules. I find using them often just makes the build system harder to understand and debug. I usually disable all of the built in ones using: # Disable built in suffix rules .SUFFIXES: # Disable builtin pattern rules MAKEFLAGS+=-r

> I can't say I share your love for make's built in rules.

Yes they can be a bit limiting, but even if you do not want to use built-in rules it's still a good idea to use generic rules using wildcards.

This is what lots of "Makefile tutorials" get wrong, they start by writing rules to build individual object files and targets.

Even if you want to write your own build rules, you should not need more than a few good rules for building and linking your object files.

Re: Practical Makefiles, by example

#28
post #17

Is anyone aware of the reasons for choosing the particular symbols that Make uses i.e. '@' (targets), '^' (list of dependencies) and ' I have admittedly limited experience with make and I always seem to forget what symbol stood for what. They don't seem to be particularly intuitive mnemonics to me. For example, one could argue that ' ' for dependencies would be a tad clearer.

I always think of '^' and ' I'm not sure what the deal is with '@' though.

I have always thought of '@' as an archery target.

Re: Practical Makefiles, by example

#29
post #26

Earlier quoted context omitted.

I can't say I share your love for make's built in rules. I find using them often just makes the build system harder to understand and debug. I usually disable all of the built in ones using: # Disable built in suffix rules .SUFFIXES: # Disable builtin pattern rules MAKEFLAGS+=-r

> I can't say I share your love for make's built in rules. Yes they can be a bit limiting, but even if you do not want to use built-in rules it's still a good idea to use generic rules using wildcards. This is what lots of "Makefile tutorials" get wrong, they start by writing rules to build individual object files and targets. Even if you want to write your own build rules, you should not need more than a few good ru…

Completely agree with you here - there should never be the need to hardcode file names in a makefile or repeat a rule multiple times - just use pattern rules.
Post reply on HN