我想用指定目标制作特定的可执行文件。 我创建了一个示例项目,如下所示
./main_a.cpp
./main_b.cpp
./include
./include/fun.h
./src
./src/fun.cpp
./Makefile
main_a.cpp
#include "fun.h"
#include <stdio.h>
int main(int argc, char **argv)
{
fun();
printf("AAA\n");
}
main_b.cpp
#include "fun.h"
#include <stdio.h>
int main(int argc, char **argv)
{
fun();
printf("BBB\n");
}
fun.h
#include <stdio.h>
extern void fun();
fun.cpp
#include "fun.h"
void fun()
{
printf("test ");
}
Makefile的内容列为打击
OBJDIR := obj/
SRCDIR := obj/src
CXX_INCLUDE = -I. -I ./include
CXX_SRCS := $(shell find src/ -name "*.cpp")
CXX_OBJS = $(addprefix $(OBJDIR), ${CXX_SRCS:.cpp=.o})
EXE_AA = main_a
EXE_BB = main_b
aa: $(OBJDIR)
aa: $(SRCDIR)
aa: CXX_SRCS += main_a.cpp # take main_a.cpp as main
aa: $(EXE_AA)
bb: $(OBJDIR)
bb: $(SRCDIR)
bb: CXX_SRCS += main_b.cpp # take main_b.cpp as main
bb: $(EXE_BB)
$(EXE_AA): $(CXX_OBJS)
@echo "Building AAA :"
$(CXX) $(CXX_OBJS) -o $@
@echo "Building Finished:"
$(EXE_BB): $(CXX_OBJS)
@echo "Building BBB :"
$(CXX) $(CXX_OBJS) -o $@
@echo "Building Finished:"
$(OBJDIR)%.o: %.cpp $(DEPS)
$(CXX) $(CXX_INCLUDE) -c $^ -o $@
$(SRCDIR):
mkdir -p $(SRCDIR)
$(OBJDIR):
mkdir -p $(OBJDIR)
.PHONY: clean
clean:
rm -rf $(OBJDIR) $(EXE_AA) $(EXE_BB)
我想要的是如果我运行 make aa ,然后生成 make_a 但发生的错误如下所示:
mkdir -p obj/
mkdir -p obj/src
g++ -I. -I ./include -c src/fun.cpp -o obj/src/fun.o
Building AAA :
g++ obj/src/fun.o obj/main_a.o -o main_a
g++: error: obj/main_a.o: No such file or directory
Makefile:24: recipe for target 'main_a' failed
make: *** [main_a] Error 1
当我运行 make bb
时,也会出现相同的错误我应该如何修改我的Makefile,以便我可以使用指定目标生成特定的可执行文件,谢谢
答案 0 :(得分:1)
您的问题是,正如the GNU make manual中明确指出的那样,特定于目标的变量仅在规则的配方中可用。它们在规则的先决条件列表中不可用。
所以在这种情况下:
$(EXE_AA): $(CXX_OBJS)
@echo "Building AAA :"
$(CXX) $(CXX_OBJS) -o $@
@echo "Building Finished:"
先决条件列表中的CXX_OBJS
版本未看到特定于目标的变量添加的新值:
aa: CXX_SRCS += main_a.cpp
因此make不知道它需要构建该目标文件。但是,配方中的CXX_OBJS
值会从特定于目标的变量中查看新值,并尝试链接该不存在的目标文件。如果您将链接器规则更改为“更正”,请执行以下操作:
$(EXE_AA): $(CXX_OBJS)
@echo "Building AAA :"
$(CXX) $^ -o $@
@echo "Building Finished:"
然后你会看到问题,因为链接行也不包含额外的对象。
ETA
有很多可能的方法可以做到这一点。一种是直接列出目标文件,而不是完全使用目标特定的变量:
$(EXE_AA): $(OBJ_DIR)main_a.o $(CXX_OBJS)
@echo "Building AAA :"
$(CXX) $^ -o $@
@echo "Building Finished:"
另一种方法是使用secondary expansion:
.SECONDEXPANSION:
$(EXE_AA): $$(CXX_OBJS)
@echo "Building AAA :"
$(CXX) $^ -o $@
@echo "Building Finished:"
(请注意先决条件清单中的双美元符号)。您还可以使用生成的包含文件,递归makefile或eval
。