【发布时间】:2020-09-30 01:21:45
【问题描述】:
最终更新:
感谢@Useless,问题解决了!
将$(EXET): $(OBJS) 更改为$(EXET): $(OSRC)。
更新日期:2020 年 9 月 29 日
按照@MadScientist 的建议,我从 Makefile 中编辑并删除了不必要的部分。但是,OSRC := $(addprefix $(ODIR)/, $(OBJS)) 行似乎没有任何效果,因为 *.o 目标文件现在被编译到工作区文件夹中,而不是专用的 ./obj 文件夹中,这是我的起源问题。
#############################################################
## THIS IS A TEST PROJECT ##
#############################################################
vpath %.cpp src
vpath %.h hdr
#############################################################
## BUILD TASKS ##
#############################################################
HDIR := hdr
#SRCS := src
ODIR := obj
EXET := a
OBJS := main.o mainhdr.o testcode.o
OSRC := $(addprefix $(ODIR)/, $(OBJS))
CXX := g++
CXXFLAGS := -I$(HDIR) -g -Wall -std=c++17
## BUILD DIRECTIVE:
all: $(EXET)
$(EXET): $(OBJS)
$(CXX) $(CXXFLAGS) $^ -o $@
$(ODIR)/%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $^ -o $@
#############################################################
## CLEAN TASK ##
#############################################################
.PHONY: clean
clean:
rm -r $(EXET) *.o
原始问题:
我一直在努力让 Make 链接特定目录中的预构建对象,但无济于事。我让我的 Makefile 将目标文件编译到不同的目录中,但在那之后我基本上被卡住了。
#############################################################
## THIS IS A TEST PROJECT ##
#############################################################
.SUFFIXES:
.SUFFIXES: .o .h .cpp
vpath %.cpp src
vpath %.h hdr
vpath %.o out
%.h : %.cpp
#############################################################
## BUILD TASKS ##
#############################################################
HDIR := hdr
#SRCS := src #UNUSED
ODIR := obj
EXE := a
OBJS := main.o mainhdr.o testcode.o
## This line added in reference to this thread:
## https://stackoverflow.com/questions/9178285/how-can-makefile-use-separate-directories-for-source-code-and-binaries
## But it doesn't seem to work either
OSRC := $(addprefix $(ODIR)/, $(OBJS))
CPP := g++
CPPFLAGS := -I$(HDIR) -c -g -Wall -std=c++17
## BUILD DIRECTIVE:
all: $(EXE)
## PROBLEM: Doesn't seem to work when prefixed with the output dir:
#$(EXE): $(ODIR)/$(OBJS)
$(EXE): $(OBJS)
$(CPP) -o %@ %^
## This compiles the objects into the output dir just fine.
%.o: %.cpp
# $(CPP) $(CPPFLAGS) $< -o $@
$(CPP) $(CPPFLAGS) $< -o $(ODIR)/$@
#############################################################
## CLEAN TASK ##
#############################################################
.PHONY: clean
clean:
rm -r $(EXE) $(ODIR)/*.o
## End of Makefile ##########################################
到目前为止的调试工作:
-
我将
.o文件类型添加到.SUFFIXES:,但我怀疑它是否有任何作用。 Make 似乎只关心头文件和源文件。 -
我做了更多研究,后来添加了这部分:
## This line added in reference to this thread:
## https://stackoverflow.com/questions/9178285/how-can-makefile-use-separate-directories-for-source-code-and-binaries
## But it doesn't seem to work either
OSRC := $(addprefix $(ODIR)/, $(OBJS))
但是,它似乎根本没有任何效果。 Make也找不到对象目录。
- 尽管它有效,但这条线不知何故困扰着我:
$(CPP) $(CPPFLAGS) $< -o $(ODIR)/$@
不应该以某种方式修复它以与$(addprefix) 指令保持一致吗?
GNU Make 的快速参考,以防我遗漏了什么:
$@ target
%< first prerequisite
$^ prerequisites
以下是简单的测试代码:
// cat hdr/mainhdr.h
#ifndef MAINHDR_H
#define MAINHDR_H
#include "testcode.h"
#define BIGCONST 777
void testFunc();
#endif
// cat hdr/testcode.h
#ifndef TESTCODE_H
#define TESTCODE_H
#include <iostream>
#include <string>
#define SMALLCONST 25
class NameTag {
private:
std::string f;
std::string l;
public:
NameTag(std::string first="", std::string last="");
void setFirstN(std::string );
void setLastN(std::string );
std::string getFirstN() const;
std::string getLastN() const;
void operator=(const NameTag &);
};
#endif
// cat src/main.cpp
#include "mainhdr.h"
int main () {
testFunc();
return 0;
}
// cat src/mainhdr.cpp
#include "mainhdr.h"
void testFunc() {
std::cout << "THIS IS A TEST STRING!\n";
std::cout << "BIGCONST = " << BIGCONST << std::endl;
std::cout << "SMALLCONST = " << SMALLCONST << std::endl;
NameTag someDude("Good", "Dude");
std::cout << someDude.getFirstN() << " " << someDude.getLastN() << std::endl;
}
// cat src/testcode.cpp
#include "testcode.h"
NameTag::NameTag(std::string first, std::string last) {
f = first;
l = last;
}
void NameTag::setFirstN(std::string first) {
f = first;
}
void NameTag::setLastN(std::string last) {
l = last;
}
std::string NameTag::getFirstN() const {
return f;
}
std::string NameTag::getLastN() const {
return l;
}
void NameTag::operator=(const NameTag &right) {
f = right.f;
l = right.l;
}
【问题讨论】:
-
您的
EXET仍然依赖于OBJS,而不是依赖于您添加前缀的OSRC。如果没有任何东西依赖于OSRC,它永远不会被使用。 -
@无用 谢谢!那解决了!太美了!