Interrupt

GNU Make Overview and Guidelines | Interrupt

GNU Make is a popular and commonly used program for building C language software. It is used when building the Linux kernel and other frequently used GNU/Linux programs and software libraries.


This is a companion discussion topic for the original entry at https://interrupt.memfault.com/blog/gnu-make-guidelines

Great post! I really needed some explanation about the basics of Make.
I have one question: in the section about “Pattern Rules” there is this rule

# Use CC to link foo.o + bar.o into 'program'
program: $(OBJ_FILES)
	$(CC) -o $@ $<

I am not 100% sure, but shouldn’t it be like this (with the “$^” automatic variable so that it takes all the prerequisites)?

# Use CC to link foo.o + bar.o into 'program'
program: $(OBJ_FILES)
	$(CC) -o $@ $^
1 Like

Great catch! you’re right, the rule should take all the prerequisites in that example, I’ll update it now.

Hi! First of all, this is an excellent post. There is a lot of really great information about make here!

I could be wrong, but I may have identified an error or inconsistency. In discussing file dependencies, DEPFLAGS and DEP_FILES are defined one way in the first example and another way in the Git repo and in the full example. I tried both, and although they generated dependency files, they didn’t seem to work. By that I mean, when I modified the source files to include a “magic number” from “example.h”, changing the magic number didn’t cause a rebuild of the executable. I’d be happy to provide source code, if needed.

Thanks for doing the Interrupt blog! This is one of the best sources of information for embedded systems that I’ve yet found!!

1 Like

The two examples are a little confusing; the first one is this:

DEPFLAGS = -MMD -MP -MF $<.d

test.o: test.c
    $(CC) $(DEPFLAGS) $< -c $@

That’s building in-tree, so the test.c.d file is placed next to the test.c file. The test.c.d file might contain:

test.o: test.c test.h

test.h:

For the second example, it’s placing the .d files into the ./build output directory (out of tree). To make things simpler, the .d files are constructed for the .o targets, so they’re placed more easily into the ./build directory (which is also somewhat more idiomatic, since the .d files output by the compiler have rules for the .o file anyway!).

Those .o.d files look like:

build/src/example.o: src/example.c src/example.h

src/example.h:

Hope that helps! I’d be happy to take a look at the source if you want to share it :smile:

Thank you for that clarification! And I believe the error ended up being mine, not yours. I had thought when I was playing around with the example code the other night that the dependencies weren’t working correctly, but I just tried it again and it seems to be working fine. Probably just a loose screw between the chair and keyboard. :slight_smile:

Happy to help, and good luck… Dep files are a tricky thing to get right!