在写涉及到子目录的makefile文件时,从上面的博客学习到很多!自己写的也是仿照着写的,主要以此博客的makefile对知识点做一个 更详细的说明 和 对makefile做一个总结!
说明:如有错误,敬请见谅!我编译的是.so库,很多命令用不到,只是网上搜索学习了一下!
一,原博客
(1)目录结构:
(2)主文件加下的makefile
XX = g++ AR = ar ARFLAG = -rcs CFLAGS = -g
CLIBS = -L./lib/ -lSender -lReceiver -lResponser -lpthread
SUBDIRS = ./receiver ./responser ./sender
INCLUDES = $(wildcard ./include/.h ./sender/.h ./receiver/.h ./responser/.h) # INCLUDE = a.h b.h … can’t be defined like "INCLUDE = ./.h"
#SOURCES = $(wildcard ./.cpp ./sender/.cpp ./receiver/.cpp ./responser/*.cpp)
INCLUDE_DIRS = -I./include -I./sender/ -I./receiver/ -I./responser/ #指定头文件目录,代码中就不需要把头文件的完整路径写出来了
TARGET = mainApp
#OBJECTS =
(
p
a
t
s
u
b
s
t
(patsubst %.cpp,%.o,
(patsubst(SOURCES))
OBJECTS = main.o
export XX CFLAGS AR ARFLAG
$(TARGET) : $(OBJECTS) $(SUBDIRS)
$(XX) $< -o $@ $(CLIBS) # $< 表示依赖列表的第一个 也就是 $(OBJECTS)
$(OBJECTS) : %.o : %.cpp
$(XX) -c $(CFLAGS) $< -o $@ $(INCLUDE_DIRS)
(
S
U
B
D
I
R
S
)
:
E
C
H
O
+
(SUBDIRS):ECHO +
(SUBDIRS):ECHO+(MAKE) -C $@
ECHO:
@echo $(SUBDIRS)
@echo begin compile
.PHONY : clean
clean:
for dir in $(SUBDIRS);
do $(MAKE) -C $$dir clean||exit 1;
done
rm -rf $(TARGET) $(OBJECTS) ./lib/*.a
(3)receiver目录下的makefile代码如下:
LIB_DIR = ./…/lib/
TOP_DIR = ./…
SOURCES = KaTeX parse error: Expected 'EOF', got '#' at position 32: … style="color: #̲008000;">/*</sp…(TOP_DIR)/include -I$(TOP_DIR)/responser/ -I./
TARGET = libReceiver.a
OBJECTS =
(
p
a
t
s
u
b
s
t
(patsubst %.cpp,%.o,
(patsubst(SOURCES))
$(TARGET) : $(OBJECTS)
$(AR) $(ARFLAG) $@ $^
cp $@ $(LIB_DIR)
$(OBJECTS) : %.o : %.cpp
$(XX) -c $(CFLAGS) $< -o $@ $(INCLUDE_DIRS)
.PHONY : clean
clean:
rm -rf $(TARGET) $(OBJECTS)
二、对上述的makefile做说明以及总结
XX = g++
定义变量XX,此后当需要用到g++的时候,可以用$(XX)替代
CLIBS = -L./lib/ -lSender -lReceiver -lResponser -lpthread
同样是定义变量,但对几点做一下说明
-L./lib/ 指明库的路径
-lpthread 在默认和指明的库路径中寻找libpthread.so(以lib开头)
INCLUDES = $(wildcard ./include/*.h ./sender/*.h ./receiver/*.h ./responser/*.h)
wildcard 函数获取工作目录下的.h文件列表
*.h *为通配符, 在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效(这还是定义变量)
wildcard 将通配符展开,INCLUDES获取的就是这些目录下的所有.h文件
INCLUDE_DIRS = -I./include -I./sender/ -I./receiver/ -I./responser/
-I.include 头文件路径,在C++代码中可以不指定头文件的完整路径,将在这些目录下寻找
export XX CFLAGS AR ARFLAG
export 后跟随 变量 将其导出,这些变量在子目录中的makefile依旧可以使用
#OBJECTS = $(patsubst %.cpp,%.o,$(SOURCES))
完整命令应该是 $(patsubst %.cpp,%.o,$(wildcard *.cpp))
使用widcard获取到所有cpp文件,在将其文件后缀替换为.o (我个人编译的是.so库不需要这些,但我认为应该并不是实际修改文件,而只是获得一个文件列表,即之后使用g++编译时的目标)
$(OBJECTS) : %.o : %.cpp $(XX) -c $(CFLAGS) $< -o $@ $(INCLUDE_DIRS)
%.o : %.cpp 将所有.cpp文件编译为相应的.o文件 https://blog.csdn.net/voip3261/article/details/10335969
实际应该是 main.o : main.cpp 这种形式(这也就是patsubst的用处了,获取所有的cpp对应.o文件列表)
$@ 目标,即$(OBJECTS)的值
$< 编译时 : 符号后的第一个依赖文件
$(SUBDIRS):ECHO +$(MAKE) -C $@
ECHO 没有特殊用途,只是执行一下命令
+$(MAKE) -C $@ 执行子目录下的makefile
.PHONY : clean clean: for dir in $(SUBDIRS);\ do $(MAKE) -C $$dir clean||exit 1;\ done rm -rf $(TARGET) $(OBJECTS) ./lib/*.a
.PHNOY clean是没有依赖项的,也不会生成clean文件,如果该文件夹下存在clean文件,就无法执行clean:下的操作了,就是为了解决这个的
do $(MAKE) - C $$dir clean || exit 1; 执行子文件夹下的clean命令 (这里我不是特别懂语法,但是大概也是明白的)
执行到了子文件夹下的makefile,下一步操作类似了,就不在说明了!