以前也写过一点 Makefile ,但是基本上都是有一个文件就写条编译命令,于是 Makefile 里面往往会弄得很乱。 双休日看了点 Makefile 的文档,直接上手用在一个小项目里了,但是会出现一点问题,实在搞不定。
先看下目录结构:
# tree
.
├── bin
├── Makefile
├── objs
└── src
├── Httpkit.cpp
├── Httpkit.h
└── main.cpp
然后是 Makefile 。其中我重新定义了 %.o:%.cpp 的规则,这样可以把生成的动态链接库文件放到 objs 目录下。
CXX = g++
CXXFLAGS = -std=c++11 -Wall -Werror
CFLAGS = -lcurl -lcurlpp
SRC_DIR = ./src
OBJS_DIR = ./objs
BIN_DIR = ./bin
vpath %.cpp $(SRC_DIR)
vpath %.h $(SRC_DIR)
vpath %.o $(OBJS_DIR)
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $(OBJS_DIR)/$@ $^
.PHONY: default clean
default: HttpKit
main.o: main.cpp
Httpkit.o: Httpkit.cpp
HttpKit: main.o Httpkit.o
$(CXX) $(CXXFLAGS) $(CFLAGS) -o $(BIN_DIR)/$@ $^
clean:
-rm -rf $(OBJS_DIR)/*
-rm -rf $(BIN_DIR)/*
执行 make 的结果:
g++ -std=c++11 -Wall -Werror -c -o ./objs/main.o ./src/main.cpp
g++ -std=c++11 -Wall -Werror -c -o ./objs/Httpkit.o ./src/Httpkit.cpp
g++ -std=c++11 -Wall -Werror -lcurl -lcurlpp -o ./bin/HttpKit main.o Httpkit.o #注意这行
g++: error: main.o: No such file or directory
g++: error: Httpkit.o: No such file or directory
Makefile:21: recipe for target 'HttpKit' failed
make: *** [HttpKit] Error 1
上面我标注释的这行输出,虽然自动推导展开了依赖参数,但是依赖的路径完全没有按照 vpath 进行补全。但是奇怪的是,上面两个生成动态链接库的规则也是这样的写法,却完全正确地补全了!
但是,此时 objs 目录下已经有了两个 .o 文件,再执行 make ,直接只有一行输出:
g++ -std=c++11 -Wall -Werror -lcurl -lcurlpp -o ./bin/HttpKit ./objs/main.o ./objs/Httpkit.o
WTF ?!?!?!
现在我有两个问题: 1 ,究竟为什么第一次 make 无法按照 vpath 变量的值自动展开路径,第二次直接就可以了? 2 ,生成最终二进制文件的命令能否也定义成隐含规则自动推导(确实这个意义不大,但是主要还是学习下 Makefile ,并且最终二进制文件并没有后缀名)?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.