C ++制定特定目标

时间:2017-04-07 04:50:24

标签: c++ makefile

我想用指定目标制作特定的可执行文件。 我创建了一个示例项目,如下所示

./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,以便我可以使用指定目标生成特定的可执行文件,谢谢

1 个答案:

答案 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