要点
makefile的依赖规则,都是从前向后的。即当前依赖的向后找或写
- 在编写makefile时,一定要搞清楚依赖关系。
如:
.o 依赖的.cpp
.so依赖的.o
… - 链接时的依赖关系
链接的动态库有依赖关系时,要注意顺序,被依赖的放后面,相互没依赖,随便放。 - 工程文件的组织形式
好的文件组织形式,可以使我们的makefile文件更加清晰,写起来更顺心。 - .d文件很重要
配置了.d文件,我们就会在它里面看到该文件依赖的所有文件,只要这些文件发生变化时,就会识别出来,并重新编译;如果没有.d文件有些头文件的修改时,不会去重新编译。
示例
在工程根目录创建demo、include、src三个文件夹和一个makefile文件
demo include Makefile src
这里的demo中,可以有很多个包含main函数的demo文件,我们的makefile会一次全部编译出来。
这个makefile可以直接生成动态库、静态库和可执行文件
CXX=g++
CPPFLAGS := -std=c++11
CPPFLAGS += -Werror=return-type -O3 -pthread
CPPFLAGS += -I./include
CPPFLAGS += -I/usr/local/include
CPPFLAGS += -L/usr/local/lib
LDFLAGS += -Wl,-rpath ./lib
LIB := -lopencv_core -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_calib3d -lopencv_video
BUILD_PATH := build
LIB_NAME ?= test
STATIC_NAME ?= lib$(LIB_NAME).a
SHARE_NAME ?= lib$(LIB_NAME).so
SRC_MAIN_CPP := $(shell find demo -name "*.cpp")
SOURCE := $(shell find src -name "*.cpp")
$(info $(SOURCE))
TARGET_PATH := lib
STATIC_TARGET := $(TARGET_PATH)/$(STATIC_NAME)
SHARE_TARGET := $(TARGET_PATH)/$(SHARE_NAME)
TARGET_NULTI_EXE := $(SRC_MAIN_CPP:%.cpp=$(BUILD_PATH)/%.bin)
OBJS:=$(patsubst %.cpp, $(BUILD_PATH)/%.o, $(SRC_MAIN_CPP))
SOBJS:=$(patsubst %.cpp, $(BUILD_PATH)/%.o, $(SOURCE))
OBJS+=$(patsubst %.cpp, $(BUILD_PATH)/%.o, $(SOURCE))
BUILD_DIR := $(sort $(BUILD_PATH) $(dir $(OBJS)))
DEPS :=$(OBJS:%.o=%.d) #静态模式(变量值替换,OBJS中所有以o结尾的换成以d结尾的)
all:$(BUILD_DIR) $(TARGET_PATH) $(OBJS) $(STATIC_TARGET) $(SHARE_TARGET) $(TARGET_NULTI_EXE)
#
.PHONY:all clean
#生成可执行文件
# #静态模式 (目标集合:目标模式:依赖模式)
$(TARGET_NULTI_EXE):%.bin:%.o $(SOBJS) | $(BUILD_DIR)
@echo $(CXX) $< $(SOBJS) $@
$(CXX) -g $(CPPFLAGS) -o $@ $< $(SOBJS) $(LIB)
#依赖生成的so生成可执行文件
# $(TARGET_NULTI_EXE):%.bin:%.o | $(TARGET_PATH) $(BUILD_DIR)
# @echo $(CXX) $< $@
# $(CXX) -g $(CPPFLAGS) -L./$(TARGET_PATH) -o $@ $< -ltest $(LIB) $(LDFLAGS)
#生成静态库
#动态库的调用仍是动态调用,而不是把动态库的相关函数copy到自己身上
$(STATIC_TARGET):$(OBJS) | $(TARGET_PATH) $(BUILD_DIR)
ar rcs $@ $<
ranlib $@
#生成动态库 (.so添加链接库,生成库的依赖关系,若不加就没有依赖关系 ldd ./lib/libtest.so)
$(SHARE_TARGET):$(OBJS) | $(TARGET_PATH) $(BUILD_DIR)
@echo $(CXX) $< $@
$(CXX) -shared -fPIC $(CPPFLAGS) -o $@ $< $(LIB)
#生成二进制文件
$(BUILD_PATH)/%.o: %.cpp $(SRC_MAIN_CPP) | $(TARGET_PATH) $(BUILD_DIR)
@echo $(CXX) $< $@
$(CXX) $(CPPFLAGS) -fPIC -MMD -MP -c $< -o $@
$(BUILD_DIR):
@echo mkdir $@
mkdir -p $(BUILD_DIR)
$(TARGET_PATH):
@echo mkdir $@
mkdir -p $(TARGET_PATH)
clean:
rm -rf $(TARGET_PATH) $(BUILD_DIR)
-include $(DEPS)
github
git clone https://github.com/guoqingMeng/makefile.git