我在使用 Makefile 生成 .o 到“src/build”时遇到了一些困难。下面是我的结构。
Project
├── include
│ └── Solution.hpp
└── src
├── bin
│ └──
├── build
│ └──
├── Makefile
├── Solution.cpp
└── main.cpp
我想要做的是在src/build文件夹下生成main.o和Solution.o,然后在src/bin下生成可执行文件'test'。运行我的 Makefile 后,我在 src/build 中得到了 main.o,但在 src 中得到了 Solution.o。我不知道为什么?变量 OBJDIR 和 BINDIR 应该设置目标在哪里,对吗?如果我删除 $(OBJECTS),一切正常。为什么我不能将所有 .o 文件输出到 src/build 有什么帮助吗?
ROOTDIR ?= ..
BINDIR := bin
OBJDIR := build
INCLUDEDIR := $(ROOTDIR)/src $(ROOTDIR)/include
CXX := g++
CCFLAGS := -c -g -O2 -Wall -std=c++17
LINKFLAGS :=
SOURCES := main.cpp Solution.cpp
OBJECTS := $(SOURCES:.cpp=.o)
EXECUTABLE := test
OBJSUFFIX := .o
all : $(BINDIR)/$(EXECUTABLE)
makedirs :
@if test ! -d $(BINDIR); then mkdir $(BINDIR); fi
@if test ! -d $(OBJDIR); then mkdir $(OBJDIR); fi
## Link ##
$(BINDIR)/$(EXECUTABLE) : $(OBJDIR)/$(OBJECTS)
$(CXX) $(LINKFLAGS) -o $@ $^
## Compile ##
$(OBJDIR)/%.o : %.cpp makedirs
$(CXX) $(CCFLAGS) $< -o $@
clean :
rm -rf $(BINDIR) $(OBJDIR) *.o
答案 0 :(得分:1)
这是错误的:
$(BINDIR)/$(EXECUTABLE) : $(OBJDIR)/$(OBJECTS)
我看到人们一直在 SO 上这样做,我不知道为什么它如此诱人,但仔细想想它显然行不通。
你有这个:
SOURCES := main.cpp Solution.cpp
OBJECTS := $(SOURCES:.cpp=.o)
所以 OBJECTS
是 main.o Solution.o
,OBJDIR
是 build
。
那么 $(OBJDIR)/$(OBJECTS)
扩展成什么?这里有一个提示:make 不会以某种方式发现 $(OBJECTS)
有多个单词并推断出您想将前缀应用于每个单词。它只是按照写入的方式扩展变量。所以这个扩展的结果是build/main.o Solution.o
。这就是为什么你会得到你所做的行为。
你想写这个:
OBJECTS := $(patsubst %.cpp,$(OBJDIR)/%.o,$(SOURCES))
或者这个:
OBJECTS := $(addprefix $(OBJDIR)/,$(SOURCES:.cpp=.o))
确保目录单独应用于每个单词,而不只是粘贴到第一个单词的前面。