Hacker News new | ask | show | jobs
by danaliv 3085 days ago
I am by no means a make expert but this is how I would write it:

  CC = clang
  CFLAGS += -Wall -Wextra
  
  libs = -lm
  objs = hellomake.o
  
  hellomake: $(objs)
  	$(CC) $(CFLAGS) -o $@ $(objs) $(libs)
  
  .PHONY: clean
  
  clean:
  	rm -f hellomake *.o *.d
  
  deps := $(objs:.o=.d)
  
  %.d: %.c
  	$(CC) $(CFLAGS) -MM -MF $@ $<
  
  -include $(deps)
The first two lines tell us which compiler we're using and set up some extra compiler warnings. Then we specify which libraries we use (it's a matter of taste whether this is a variable or just spelled out later) and the names of our object files.

The first target, hellomake, is our executable. This is the default target, so it's the one that'll be built if we run make with no arguments. It runs the C compiler with the flags we specified earlier. Its dependencies are the object files, which means they'll be built automatically and rebuilt when their dependencies change. As noted, there is a built-in rule to build the object files from the C source using our CC and CFLAGS. We don't need to tell make how to do that.

The next target, clean, is a "phony" target—it doesn't refer to a file. Normally a make target tells make how to build a file. A phony target, in contrast, is really just a shell script that doesn't produce any file output. This one deletes all the build products.

The remaining lines set up the dependency tracking for headers. This makes it so that a change in a header file will trigger a rebuild of any source that includes it. We begin by making a list of files by copying the list of object files and swapping in ".d" for the ".o" file extension. Next is a rule that tells how to build a .d file from a .c file. This rule runs the C compiler and tells it to output a dependency tracking file. The last line says to include each of the .d files in the Makefile. (The .d files contain Makefile syntax to specify the header dependencies.)

I omitted the IDIR and ODIR and such because in a project of this size I wouldn't bother putting includes and object files in separate directories from the source.

I hope that helps. I know make can seem outdated and weird but I think it really can be simple once you learn a few things about how it works. Hopefully this will get you started in that direction!

2 comments

Put -MMD to CFLAGS and you can drop the rules to build dependency files. The compiler will then generate the deps files when compiling.

Don't use wildcards in clean target. Use $(RM) $(OBJS) $(DEPS) instead.

> $(CC) $(CFLAGS) -o $@ $(objs) $(libs)

Please honour LDFLAGS and LDLIBS here.

> $(CC) $(CFLAGS) -MM -MF $@ $<

Please honour CPPFLAGS here.