在 makefile 中进行模式匹配时获取错误的文件名
Getting wrong file name while pattern matching in makefile
我项目的目录结构是这样的:
|-build
|-src
|-lib
|-libfile1.hpp
|-libfile1.cpp
|-libfile2.hpp
|-libfile2.cpp
|-libfile3.hpp
|-Makefile(lib)
|-examples
|-pingpong
|-main.cpp
|-ping.cpp
|-ping.hpp
|-Makefile(ping)
我的目标是在示例文件夹中有许多示例,它们都使用 libfiles 但彼此独立。因此,我想在每个示例文件夹中使用单独的 makefile 到 link 到 libfiles 的对象。
为了实现这个目标,这里是 makefile(lib):
SRC = .
BLD = ../../build
SOURCE = $(wildcard $(SRC)/*.cpp)
INCLUDE = $(wildcard $(SRC)/*.hpp)
OBJECT = $(patsubst %,$(BLD)/%, $(notdir $(SOURCE:.cpp=.o)))
CC = g++
#flags went here, removed for brevity
all: $(OBJECT)
$(BLD)/%.o: $(SRC)/%.cpp $(SRC)/%.hpp
mkdir -p $(dir $@)
$(CC) -c $< -o $@
.PHONY: clean
clean:
$(RM) -r $(BLD)
这是 makefile(ping),我在其中尝试构建本地对象并将库对象构建模式传递给 makefile(lib):
TARGET = mainpingpong.out
SRC = ../../actorlib
BLD = ../../../build
LIBSOURCE = $(wildcard $(SRC)/*.cpp)
LIBINCLUDE = $(wildcard $(SRC)/*.hpp)
LIBOBJECT = $(patsubst %,$(BLD)/%, $(notdir $(LIBSOURCE:.cpp=.o)))
LOCSOURCE = $(wildcard *.cpp)
LOCINCLUDE = $(wildcard *.hpp)
LOCOBJECT = $(patsubst %,$(BLD)/%, $(notdir $(LOCSOURCE:.cpp=.o)))
CC = g++
$(TARGET) : $(LIBOBJECT) $(LOCOBJECT)
$(CC)-o $@ $^
$(LOCOBJECT): $(LOCSOURCE) $(LOCINCLUDE)
mkdir -p $(dir $@)
$(CC) -c $< -o $@
$(LIBOBJECT): $(LIBSOURCE) $(LIBINCLUDE)
cd $(SRC) && $(MAKE)
.PHONY: clean
clean :
cd $(SRC) && $(MAKE) clean
错误发生在我的本地文件匹配中,它将 main.o 和 ping.o 与 main.cpp 相关联(其他一切正常):
mkdir -p ../../../build/
g++ -c main.cpp -o ../../../build/main.o
mkdir -p ../../../build/
g++ -c main.cpp -o ../../../build/ping.o
我如何正确地做我想做的事?我应该有不同的规则或目标吗?或者是否有从变量中获取文件名的正确方法?
我希望 .o 文件最终位于同一个位置,但可执行文件保留在示例目录中。
问题出在这里:
$(LOCOBJECT): $(LOCSOURCE) $(LOCINCLUDE)
mkdir -p $(dir $@)
$(CC) -c $< -o $@
LOCSOURCE
包含 main.cpp ping.cpp
,因此此规则使 both 个源文件成为 each 目标的先决条件。无论 Make 正在尝试构建 main.o
还是 ping.o
,先决条件列表都是相同的:main.cpp ping.cpp ping.hpp
。所以自动变量 $<
总是扩展为 main.cpp
(因为这是列表中的第一个文件名)。
解决这个问题的一种方法是 static pattern rule:
$(LOCOBJECT): $(BLD)/%.o: %.cpp $(LOCINCLUDE)
mkdir -p $(dir $@)
$(CC) -c $< -o $@
这仍然不完善,因为所有本地头文件都是来自本地源的每个对象的先决条件。如果你有一个 paddle.cpp
并且你修改了 ping.hpp
,Make 将重建 paddle.o
,即使 paddle.cpp 不以任何方式依赖于 ping.hpp
。这不是一个严重的问题,它只是意味着 Make 会做一些额外的工作,在没有理由的时候重建东西。如果你想解决它,你可以手动将依赖项写入makefile,或者使用更复杂的方法,如automatic dependency generation。
我项目的目录结构是这样的:
|-build
|-src
|-lib
|-libfile1.hpp
|-libfile1.cpp
|-libfile2.hpp
|-libfile2.cpp
|-libfile3.hpp
|-Makefile(lib)
|-examples
|-pingpong
|-main.cpp
|-ping.cpp
|-ping.hpp
|-Makefile(ping)
我的目标是在示例文件夹中有许多示例,它们都使用 libfiles 但彼此独立。因此,我想在每个示例文件夹中使用单独的 makefile 到 link 到 libfiles 的对象。
为了实现这个目标,这里是 makefile(lib):
SRC = .
BLD = ../../build
SOURCE = $(wildcard $(SRC)/*.cpp)
INCLUDE = $(wildcard $(SRC)/*.hpp)
OBJECT = $(patsubst %,$(BLD)/%, $(notdir $(SOURCE:.cpp=.o)))
CC = g++
#flags went here, removed for brevity
all: $(OBJECT)
$(BLD)/%.o: $(SRC)/%.cpp $(SRC)/%.hpp
mkdir -p $(dir $@)
$(CC) -c $< -o $@
.PHONY: clean
clean:
$(RM) -r $(BLD)
这是 makefile(ping),我在其中尝试构建本地对象并将库对象构建模式传递给 makefile(lib):
TARGET = mainpingpong.out
SRC = ../../actorlib
BLD = ../../../build
LIBSOURCE = $(wildcard $(SRC)/*.cpp)
LIBINCLUDE = $(wildcard $(SRC)/*.hpp)
LIBOBJECT = $(patsubst %,$(BLD)/%, $(notdir $(LIBSOURCE:.cpp=.o)))
LOCSOURCE = $(wildcard *.cpp)
LOCINCLUDE = $(wildcard *.hpp)
LOCOBJECT = $(patsubst %,$(BLD)/%, $(notdir $(LOCSOURCE:.cpp=.o)))
CC = g++
$(TARGET) : $(LIBOBJECT) $(LOCOBJECT)
$(CC)-o $@ $^
$(LOCOBJECT): $(LOCSOURCE) $(LOCINCLUDE)
mkdir -p $(dir $@)
$(CC) -c $< -o $@
$(LIBOBJECT): $(LIBSOURCE) $(LIBINCLUDE)
cd $(SRC) && $(MAKE)
.PHONY: clean
clean :
cd $(SRC) && $(MAKE) clean
错误发生在我的本地文件匹配中,它将 main.o 和 ping.o 与 main.cpp 相关联(其他一切正常):
mkdir -p ../../../build/
g++ -c main.cpp -o ../../../build/main.o
mkdir -p ../../../build/
g++ -c main.cpp -o ../../../build/ping.o
我如何正确地做我想做的事?我应该有不同的规则或目标吗?或者是否有从变量中获取文件名的正确方法?
我希望 .o 文件最终位于同一个位置,但可执行文件保留在示例目录中。
问题出在这里:
$(LOCOBJECT): $(LOCSOURCE) $(LOCINCLUDE)
mkdir -p $(dir $@)
$(CC) -c $< -o $@
LOCSOURCE
包含 main.cpp ping.cpp
,因此此规则使 both 个源文件成为 each 目标的先决条件。无论 Make 正在尝试构建 main.o
还是 ping.o
,先决条件列表都是相同的:main.cpp ping.cpp ping.hpp
。所以自动变量 $<
总是扩展为 main.cpp
(因为这是列表中的第一个文件名)。
解决这个问题的一种方法是 static pattern rule:
$(LOCOBJECT): $(BLD)/%.o: %.cpp $(LOCINCLUDE)
mkdir -p $(dir $@)
$(CC) -c $< -o $@
这仍然不完善,因为所有本地头文件都是来自本地源的每个对象的先决条件。如果你有一个 paddle.cpp
并且你修改了 ping.hpp
,Make 将重建 paddle.o
,即使 paddle.cpp 不以任何方式依赖于 ping.hpp
。这不是一个严重的问题,它只是意味着 Make 会做一些额外的工作,在没有理由的时候重建东西。如果你想解决它,你可以手动将依赖项写入makefile,或者使用更复杂的方法,如automatic dependency generation。