fuyinyuezhang 发表于 2016-05-18 09:49

这个 Makefile 下的生成最终二进制文件输出的环节有点问题

本帖最后由 fuyinyuezhang 于 2016-05-18 13:56 编辑

先看下目录结构:
# 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: *** Error 1
上面我标注释的这行输出,虽然自动推导展开了依赖参数,但是依赖的路径完全没有按照 vpath 进行补全。奇怪的是,上面两个生成动态链接库(.o 后缀的文件)的规则也是这样的写法,却完全正确地补全了!

但是,此时 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 ,并且最终二进制文件并没有后缀名)?

sonicling 发表于 2016-05-18 23:59

HttpKit:      main.o Httpkit.o

这个依赖关系有问题,.o文件被你生成到OBJS_DIR里面去了,你就不能依赖本目录下的OBJS_DIR
而且你要把HttpKit放到BIN_DIR,前面也要加上。

$(BIN_DIR)/HttpKit :   $(OBJS_DIR)/main.o $(OBJS_DIR)/Httpkit.o

爻易 发表于 2016-05-19 08:44

用VPATH变量试试:

VPATH = $(SRC_DIR) : $(OBJS_DIR) : $(BIN_DIR)
页: [1]
查看完整版本: 这个 Makefile 下的生成最终二进制文件输出的环节有点问题