0

我有一个有点奇怪的 Make case,我正在努力弄清楚。我有一个 C++ 项目,我从一些 .cpp 文件开始,我需要从多个应用程序使用的多个远程目录编译一些源文件。这并不理想,但这是我的开发组使用的遗留目录/编译结构。

其他项目利用 VPATH 来实现这一点。然而,他们最终硬编码了需要链接的对象列表,这种方法对我来说似乎并不优雅或灵活。我想动态编译和链接所有内容。另一个潜在的复杂情况是,这些远程 VPATH 目录中的一些具有带有 .c 扩展名的文件(即使这些文件编译为 C++)而不是 .cpp。

我目前的解决方案:

# 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)

结果是除了我的 VPATH 目录中的文件之外,所有内容都被编译和链接。我怀疑这可能是因为一旦我的 $(OBJ) prereq 被评估,结果对象本身都不位于 VPATH 中,只有源文件。

我可以采取更好的方法吗?我无法轻易更改这些远程 VPATH 目录的内容,因为它们被具有不同所有者的许多不同应用程序使用。

4

1 回答 1

2

看着:

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/another/remote/dir)构建任何目标文件。那么它为什么要尝试构建它们呢?

你必须去寻找那些文件并将它们添加到你的对象列表中。

你可以尝试这样的事情:

VPATH = /one/remote/dir /another/remote/dir
OBJ += $(patsubst %,$(OBJ_DIR)/%.o,$(notdir $(basename $(wildcard $(addsuffix /*.cpp,$(VPATH)) $(addsuffix /*.c,$(VPATH))))))

这会将/*.cppand/*.c后缀添加到 中的每个目录$(VPATH),然后执行通配符以获取所有匹配的文件,然后获取基本名称(删除.cppand.c后缀),然后删除目录路径,然后将每个基本文件名转换为前缀$(OBJ_DIR)并添加.o到末尾.

当然,如果您在系统中的任何地方都有两个具有相同基本名称的文件,那么您就不走运了,您将不得不做一些更复杂的事情,例如保留目录结构。

于 2017-11-17T22:41:30.560 回答