转帖:一辉的文章
在Linux下做开发难免要接触makefile,整个项目的构建都依赖于它。100个developer有100种makefile的写法,在一个较大的项目中,各种各样的makefile无论在开发、后期维护还是整个系统的持续集成都是一个负担。
有幸参与重构一个遗留系统的makefile,以下是一些心得和一个makefile模板。
重构目的:
1.清晰易懂、容易维护
2.方便系统的持续集成
重构原则:
1.子模块makefile模板化
2.外部依赖、通用宏定义集中化
3.中间和最终输出集中,便于系统构建
下面是总结出的一个makefile模板,我在日常的开发中都用它,其中加入了详细的注释。
- #Get the ROOT_PATH which common files located, assuming this makefile located in $(ROOT_PATH)/src/sub_module
- ROOT_PATH = $(shell cd ../..; pwd)
- #Where define the path of third party modules
- include $(ROOT_PATH)/path
- #Where define common macros such as CC=gcc, CXX=g++ and so on
- include $(ROOT_PATH)/common
- #Set target output path and the path of intermidiate object
- #The path macros should include in $(ROOT_PATH)/path
- OUT_PATH = $(OUTPUT_PATH)/submodule
- OBJ_PATH = $(TMPOBJ_PATH)/submodule
- TARGET = $(OUT_PATH)/targe
- #If the targe is share object then set corresponding flags
- #which should define in $(ROOT_PATH)/common
- CFLAGS += $(CFLAGS_SO)
- LDFLAGS += $(LDFLAGS_SO)
- #Custom Predefines
- CFLAGS += -DXXXXXXXX
- CFLAGS += -DYYYYYYYY
- #Dependent header files
- #The path macros should include in $(ROOT_PATH)/path
- CFLAGS += -I. /
- -I$(XXXX_INC) /
- -I$(YYYY_INC) /
- -I$(ZZZZ_INC)
- #Dependent libraries
- #The path macros should include in $(ROOT_PATH)/path
- LDFLAGS += -L$(XXXX_LIB) -lxxxx /
- -L$(YYYY_LIB) -lyyyy
- #Set CPP source directory
- CPP_SRCDIR = .
- #Or set specific CPP Source files
- ADDITIONAL_CPP_SOURCES = /
- $(PATH_A)/a.cpp /
- $(PATH_B)/b.cpp
- #Traverse every directory in $(CPP_SRCDIR), and find every cpp file
- CPP_SOURCES = $(foreach d,$(CPP_SRCDIR),$(wildcard $(d)/*.cpp) ) $(ADDITIONAL_CPP_SOURCES)
- #Traverse every cpp file in $(CPP_SOURCES) and get corresponding object file(.o)
- CPP_OBJFILES = $(patsubst %.cpp,$(OBJ_PATH)/%.o,$(notdir $(CPP_SOURCES)))
- #Set C source directory
- C_SRCDIR =
- #Or set specific C Source files
- ADDITIONAL_C_SOURCES = /
- $(PATH_A)/a.c /
- $(PATH_B)/b.c
- #C Source files
- C_SOURCES = $(foreach d,$(C_SRCDIR),$(wildcard $(d)/*.c) ) $(ADDITIONAL_C_SOURCES)
- C_OBJFILES = $(patsubst %.c,$(OBJ_PATH)/%.o,$(notdir $(C_SOURCES)))
- #Set vpath where to find these types of files
- vpath %.cpp $(dir $(CPP_SOURCES))
- vpath %.c $(dir $(C_SOURCES))
- vpath %.o $(OBJ_PATH)
- #The first target to be executed
- all: target
- target: $(TARGET)
- #Static dependecy pattern
- #$(OBJ_PATH)/%.o define the pattern of target and %.c or %.cpp is the final dependency
- $(C_OBJFILES): $(OBJ_PATH)/%.o: %.c
- -mkdir -p $(OBJ_PATH)
- $(CXX) -c $(CFLAGS) -o $@ $<
- $(CPP_OBJFILES): $(OBJ_PATH)/%.o: %.cpp
- -mkdir -p $(OBJ_PATH)
- $(CXX) -c $(CFLAGS) -o $@ $<
- $(TARGET): $(CPP_OBJFILES) $(C_OBJFILES)
- -mkdir -p $(OUT_PATH)
- $(CXX) -o $@ $^ $(LDFLAGS)
- clean:
- -rm -rf $(OBJ_PATH)
- -rm -f $(TARGET)