Makefile Make:利用VPATH编译和链接具有不同扩展名的文件
我有一个有点奇怪的制造案例,我正在努力弄清楚。我有一个C++项目,我从一些.CPP文件开始,我需要从多个应用程序中使用的多个远程目录编译一些源文件。这并不理想,但这是我的开发组使用的传统目录/编译结构 其他项目利用VPATH来实现这一点。然而,他们最终硬编码了需要链接的对象列表,这种方法在我看来既不优雅也不灵活。我想动态编译和链接中的所有内容。另一个潜在的复杂性是,这些远程VPATH目录中的某些目录的文件扩展名为.c(即使这些目录编译为c++),而不是.cpp 我当前的解决方案:Makefile Make:利用VPATH编译和链接具有不同扩展名的文件,makefile,gnu-make,vpath,Makefile,Gnu Make,Vpath,我有一个有点奇怪的制造案例,我正在努力弄清楚。我有一个C++项目,我从一些.CPP文件开始,我需要从多个应用程序中使用的多个远程目录编译一些源文件。这并不理想,但这是我的开发组使用的传统目录/编译结构 其他项目利用VPATH来实现这一点。然而,他们最终硬编码了需要链接的对象列表,这种方法在我看来既不优雅也不灵活。我想动态编译和链接中的所有内容。另一个潜在的复杂性是,这些远程VPATH目录中的某些目录的文件扩展名为.c(即使这些目录编译为c++),而不是.cpp 我当前的解决方案: # Direc
# Directory for object files
OBJ_DIR = build
CPPSRC := $(wildcard *.cpp)
CSRC := $(wildcard *.c)
OBJ := $(CSRC:%.c=$(OBJ_DIR)/%.o) $(CPPSRC:%.cpp=$(OBJ_DIR)/%.o)
# Directory for output binaries
BIN_DIR = bin
# Name of binary executable
OUTPUT = foo
# VPATH allows you to specify other directories to search for prereqs in
VPATH = /one/remote/dir /another/remote/dir
# 'make all'
all: $(BIN_DIR)/$(OUTPUT)
# 'make clean'
clean:
@rm -rf $(BIN_DIR)
@rm -rf $(OBJ_DIR)
$(OBJ_DIR)/%.o: %.cpp
@mkdir -p $(OBJ_DIR)
$(CXX) -c $< -o $@
$(OBJ_DIR)/%.o: %.c
@mkdir -p $(OBJ_DIR)
$(CXX) -c $< -o $@
$(BIN_DIR)/$(OUTPUT): $(OBJ)
@mkdir -p $(BIN_DIR)
$(CXX) -g -ansi -Wall -Werror -o $@ $(OBJ)
对象文件的目录
OBJ_DIR=构建
CPPSRC:=$(通配符*.cpp)
中国证监会:=$(通配符*.c)
OBJ:=$(证监会:%.c=$(OBJ\U目录)/%.o)$(CPPSRC:%.cpp=$(OBJ\U目录)/%.o)
#输出二进制文件的目录
BIN_DIR=BIN
#二进制可执行文件的名称
输出=foo
#VPATH允许您指定要在中搜索prereq的其他目录
VPATH=/one/remote/dir/other/remote/dir
#“全做”
全部:$(BIN_DIR)/$(输出)
#“打扫干净”
清洁:
@rm-rf$(本部目录)
@rm-rf$(OBJ_DIR)
$(对象目录)/%.o:%.cpp
@mkdir-p$(OBJ_DIR)
$(CXX)-c$<-o$@
$(OBJ_DIR)/%.o:%.c
@mkdir-p$(OBJ_DIR)
$(CXX)-c$<-o$@
$(BIN_DIR)/$(输出):$(OBJ)
@mkdir-p$(BIN_DIR)
$(CXX)-g-ansi-Wall-Werror-o$@$(OBJ)
结果是,除了我的VPATH目录中的文件外,所有内容都被编译和链接。我怀疑这可能是因为一旦计算了我的$(OBJ)prereq,结果对象本身就没有一个位于VPATH中,只有源文件
我可以采取更好的方法吗?我无法轻松更改这些远程VPATH目录的内容,因为它们由不同所有者的许多不同应用程序使用。查看:
CPPSRC := $(wildcard *.cpp)
CSRC := $(wildcard *.c)
OBJ := $(CSRC:%.c=$(OBJ_DIR)/%.o) $(CPPSRC:%.cpp=$(OBJ_DIR)/%.o)
$(BIN_DIR)/$(OUTPUT): $(OBJ)
第一行表示,获取我当前目录中与模式*.cpp
匹配的所有文件。第二行表示,获取我当前目录中与模式*.c
匹配的所有文件。第三行表示,将所有这些源文件转换为$(OBJ_DIR)
目录中的对象文件名
最后一行说,当您想要构建$(BIN_DIR)/$(OUTPUT)
时,请确保首先构建所有这些对象文件
您没有告诉make它应该为其他地方可能找到的源构建任何对象文件(例如,/one/remote/dir
或/other/remote/dir
)。那么,它为什么要尝试建造它们呢
你必须去寻找那些文件,并将它们添加到你的对象列表中
您可以尝试以下方法:
VPATH = /one/remote/dir /another/remote/dir
OBJ += $(patsubst %,$(OBJ_DIR)/%.o,$(notdir $(basename $(wildcard $(addsuffix /*.cpp,$(VPATH)) $(addsuffix /*.c,$(VPATH))))))
这会将/*.cpp
和/*.c
后缀添加到$(VPATH)
中的每个目录中,然后执行通配符以获取所有匹配的文件,然后获取基本名称(删除.cpp
和.c
后缀),然后删除目录路径,然后将每个基本文件名转换为前缀$(OBJ\u DIR)
并在末尾添加.o
当然,如果系统中的任何位置都有两个基名称相同的文件,那么您就倒霉了,您将不得不做一些更复杂的事情,例如保留目录结构。查看:
CPPSRC := $(wildcard *.cpp)
CSRC := $(wildcard *.c)
OBJ := $(CSRC:%.c=$(OBJ_DIR)/%.o) $(CPPSRC:%.cpp=$(OBJ_DIR)/%.o)
$(BIN_DIR)/$(OUTPUT): $(OBJ)
第一行表示,获取我当前目录中与模式*.cpp
匹配的所有文件。第二行表示,获取我当前目录中与模式*.c
匹配的所有文件。第三行表示,将所有这些源文件转换为$(OBJ_DIR)
目录中的对象文件名
最后一行说,当您想要构建$(BIN_DIR)/$(OUTPUT)
时,请确保首先构建所有这些对象文件
您没有告诉make它应该为其他地方可能找到的源构建任何对象文件(例如,/one/remote/dir
或/other/remote/dir
)。那么,它为什么要尝试建造它们呢
你必须去寻找那些文件,并将它们添加到你的对象列表中
您可以尝试以下方法:
VPATH = /one/remote/dir /another/remote/dir
OBJ += $(patsubst %,$(OBJ_DIR)/%.o,$(notdir $(basename $(wildcard $(addsuffix /*.cpp,$(VPATH)) $(addsuffix /*.c,$(VPATH))))))
这会将/*.cpp
和/*.c
后缀添加到$(VPATH)
中的每个目录中,然后执行通配符以获取所有匹配的文件,然后获取基本名称(删除.cpp
和.c
后缀),然后删除目录路径,然后将每个基本文件名转换为前缀$(OBJ\u DIR)
并在末尾添加.o
当然,如果系统中的任何位置都有两个基名称相同的文件,那么你就不走运了,你必须做一些更复杂的事情,例如保留目录结构。MadScientist的解决方案正是我所需要的,但他提到的警告将使我在未来远离这类事情……疯狂科学家的解决方案正是我所需要的,但他提到的警告将使我在未来远离这类事情。。。