Makefiles are cool

Category: tools
Tags: tools make

Disclaimer

  1. One day I realized that I understanding 'make' could improve my productivity. So I decided to invest some time. It was well worth it.

  2. I probably need to learn more about modern builds systems: GN, Gyp, Ninja, Tup, Gradle, Ant, scons, etc.

  3. YMMV, but I like this method. I guess it is because my love for GNU make.

Background

Sometimes you are doing stuff in C/C++ when you want total control:

  • you know exactly what are the dependencies of each c/h file.
  • you want partial compliation to speed things up.
  • you want to finetune the parameters of compliation

Make has some nice features that can make your life easier

The setup

This Makefile is taken from an actual (dead) project.

Compliation flags

We can set the complilation flags on a 'per target basis'. Please note that depending on the compiler there can be concat'ed.

$(OBJ_DIR)/main_server.o:			EXCEPTION =
$(OBJ_DIR)/webserver.o	:			EXCEPTION = -Wno-strict-aliasing -Wno-sign-conversion -Wno-conversion -Wno-array-bounds
$(OBJ_DIR)/webclient.o	:			EXCEPTION = -Wno-strict-aliasing -Wno-sign-conversion -Wno-conversion
$(OBJ_DIR)/sqlclient.o:				EXCEPTION = -Wno-conversion
$(OBJ_DIR)/javascript.o:			EXCEPTION = -Wno-aggregate-return -Wno-unused-function -Wno-unused-variable -Wno-unused-macros
$(OBJ_DIR)/core.o:				EXCEPTION = -Wno-unused-result
$(OBJ_DIR)/utils.o:				EXCEPTION = -Wno-unused-result
ifeq ($(CC),gcc)
$(OBJ_DIR)/main_server.o:			EXCEPTION +=
$(OBJ_DIR)/webserver.o:				EXCEPTION += 
$(OBJ_DIR)/webclient.o:				EXCEPTION +=
$(OBJ_DIR)/sqlclient.o:				EXCEPTION += -Wno-suggest-attribute=noreturn
$(OBJ_DIR)/javascript.o:			EXCEPTION +=
$(OBJ_DIR)/core.o:				EXCEPTION += -Wno-suggest-attribute=pure
$(OBJ_DIR)/utils.o:				EXCEPTION += 
else
$(OBJ_DIR)/main_server.o:			EXCEPTION +=
$(OBJ_DIR)/webserver.o:				EXCEPTION += -Wno-unreachable-code -Wno-cast-align
$(OBJ_DIR)/webclient.o:				EXCEPTION += -Wno-unreachable-code -Wno-cast-align
$(OBJ_DIR)/sqlclient.o:				EXCEPTION += -Wno-unreachable-code -Wno-cast-align
$(OBJ_DIR)/javascript.o:			EXCEPTION += -Wno-cast-align
$(OBJ_DIR)/core.o:				EXCEPTION += -Wno-unreachable-code -Wno-cast-align -Wno-format-nonliteral
$(OBJ_DIR)/utils.o:				EXCEPTION += 
endif

Dependencies (input)

We can set the inputs on a 'per target basis'

$(OBJ_DIR)/utils.o:				$(CORE_DIR)/utils.c  $(CORE_DIR)/utils.h $(COMMON_HEADERS)
$(OBJ_DIR)/core.o:				$(CORE_DIR)/core.c $(CORE_DIR)/core.h $(CORE_DIR)/utils.h $(COMMON_HEADERS)
$(OBJ_DIR)/webserver.o:				$(FEAT_DIR)/webserver.c $(FEAT_DIR)/webserver.h $(FEAT_DIR)/webcommon.h $(CORE_DIR)/core.h $(CORE_DIR)/utils.h $(COMMON_HEADERS)
$(OBJ_DIR)/webclient.o:				$(FEAT_DIR)/webclient.c $(FEAT_DIR)/webclient.h $(FEAT_DIR)/webcommon.h $(CORE_DIR)/core.h $(CORE_DIR)/utils.h $(COMMON_HEADERS)
$(OBJ_DIR)/sqlclient.o:				$(FEAT_DIR)/sqlclient.c $(FEAT_DIR)/sqlclient.h $(CORE_DIR)/core.h $(CORE_DIR)/utils.h $(COMMON_HEADERS)
$(OBJ_DIR)/javascript.o:			$(GLOT_DIR)/javascript.cpp $(GLOT_DIR)/javascript.h $(CORE_DIR)/core.h $(CORE_DIR)/utils.h $(FEAT_DIR)/webserver.h $(FEAT_DIR)/webclient.h $(FEAT_DIR)/sqlclient.h $(COMMON_HEADERS) 
$(OBJ_DIR)/main_server.o:			$(MAIN_DIR)/main_server.cpp $(CORE_DIR)/core.h $(FEATURE_HEADERS) $(GLOT_HEADERS) $(COMMON_HEADERS)

Compiling and linking

We can still use generic targets, even withou '.SUFFIX'

$(OBJ_DIR)/main_%.o:				$(MAIN_DIR)/main_%.cpp
    @echo "\tCC\t"$@:
    @$(CC) -std=$(STDCPP) $(CC_FLAGS) 	-c $< -o $@ $(EXCEPTION) -I$(CORE_DIR) $(HAVES) $(INCS)

$(OBJ_DIR)/%.o:					$(FEAT_DIR)/%.c
    @echo "\tCC\t"$@
    @$(CC) -std=$(STDC) $(CC_FLAGS) -c $< -o $@ $(EXCEPTION) -I$(CORE_DIR) $(HAVES) $(INCS)

$(OBJ_DIR)/%.o:					$(CORE_DIR)/%.c
    @echo "\tCC\t"$@
    @$(CC) -std=$(STDC) $(CC_FLAGS) -c $< -o $@ $(EXCEPTION) -I$(CORE_DIR) $(HAVES) $(INCS)

$(OBJ_DIR)/%.o:					$(GLOT_DIR)/%.cpp
    @echo "\tCC\t"$@
    @$(CC) -std=$(STDCPP) $(CC_FLAGS) -c $< -o $@ $(EXCEPTION) -I$(CORE_DIR) $(HAVES) $(INCS)

This gives you control, flexibility, speed and Make-superpowers(TM)