在具有不同结果的不同构建命令上使用变量的相同 Makefile 命名法

Identical Makefile nomenclature for using variable on different build commands with different results

这个Makefile生成了三个程序。它们遵循相同的模式,但在 运行 时生成不同的构建命令。具体来说,我需要使用 c++11 进行编译,但只能通过其中一个构建命令来实现。这是为什么?

生成文件:

CXX=g++
RM=rm -f
CFLAGS=-std=c++11 -g -Wall $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SOURCES=generic_queue.cpp map_compare.cpp vector_search.cpp
OBJS=$(SOURCES:.cpp=.o)

all: $(SOURCES) generic_queue_test list_of_lists map_compare_test vector_search_test

# Note that $(CFLAGS) is used in the $(CXX) ... command
# each time that a .o file is built.

vector_search_test: $(OBJS) vector_search_test.o
    $(CXX) $(LDFLAGS) -o vector_search_test vector_search_test.o $(LDLIBS)

vector_search_test.o: vector_search.cpp vector_search.h
    $(CXX) $(CFLAGS) -c vector_search.cpp -o vector_search_test.o

generic_queue_test: $(OBJS) generic_queue_test.o
    $(CXX) $(LDFLAGS) -o generic_queue_test generic_queue_test.o $(LDLIBS)

generic_queue_test.o: generic_queue.cpp generic_queue.h fixed_priority_queue.h
    $(CXX) $(CFLAGS) -c generic_queue.cpp -o generic_queue_test.o

list_of_lists: $(OBJS) list_of_lists.o
    $(CXX) $(LDFLAGS) -o list_of_lists list_of_lists.o $(LDLIBS)

list_of_lists.o: list_of_lists.cpp list_of_lists.h
    $(CXX) $(CFLAGS) -c list_of_lists.cpp -o list_of_lists.o

map_compare_test: $(OBJS) map_compare.o
    $(CXX) $(LDFLAGS) -o map_compare map_compare.o $(LDLIBS)

map_compare.o: map_compare.cpp map_compare.h
    $(CXX) $(CFLAGS) -c map_compare.cpp -o map_compare.o


clean:
    $(RM) $(OBJS) generic_queue_test.o list_of_lists.o map_compare.o

dist-clean: clean
    $(RM) generic_queue_test list_of_lists map_compare

输出:

g++    -c -o generic_queue.o generic_queue.cpp
g++ -std=c++11 -g -Wall -pthread -m64 -I/usr/include/root -c map_compare.cpp -o map_compare.o
g++    -c -o vector_search.o vector_search.cpp

我们看到只有第二个g++命令充分利用了CFLAGS变量。为什么?它与 CFLAGS 变量的 $(shell ...) 部分有关吗?

编辑: 能够通过将目标文件的名称 vector_search_test.o 更改为 vector_search.o 来解决我的问题 为什么这样做有效?

您的 makefile 中有几个错误,导致了此行为。

首先考虑OBJS,其中包含

generic_queue.o map_compare.o vector_search.o

这些文件是其他目标的先决条件,但您从未真正使用过 generic_queue.ovector_search.o错误 #1:您错误地拥有了额外的先决条件。

这些文件是其他目标的先决条件,因此 Make 必须构建它们。但是怎么办?您已经为三个目标文件提供了规则:

vector_search_test.o: vector_search.cpp vector_search.h
    ...

generic_queue_test.o: generic_queue.cpp generic_queue.h fixed_priority_queue.h
    ...

list_of_lists.o: list_of_lists.cpp list_of_lists.h
    ...

map_compare.o: map_compare.cpp map_compare.h
    ...

最后一个适用于 map_compare.o,但是 你没有给出 generic_queue.ovector_search.o 的规则(实际上没有你应该这样做的原因,因为你从不使用它们)。但是 Make 知道如何执行某些标准构建,例如 foo.cpp => foo.o。如果您不提供规则,Make 将使用其隐式规则,结果如下所示:

generic_queue.o: generic_queue.cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c generic_queue.cpp -o generic_queue.o

这和你写的规则很相似。事实上,您可能不会注意到其中的区别——您可以省略您的规则并让 Make 依赖这个规则,但是 Bug #2,您将标志 -std=c++11 -g -Wall whatever 添加到错误的变量。 Make 使用 CXXFLAGS 来保存 C++ 编译器的标志;你将你的添加到 CFLAGS,这是用于 C 编译器的。

(我省略了 pattern rules and automatic variables,因为你似乎不了解它们——我敦促你学习它们,它们非常有用,但那是以后的事了。)