在具有不同结果的不同构建命令上使用变量的相同 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.o
或 vector_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.o
或 vector_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,因为你似乎不了解它们——我敦促你学习它们,它们非常有用,但那是以后的事了。)
这个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.o
或 vector_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.o
或 vector_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,因为你似乎不了解它们——我敦促你学习它们,它们非常有用,但那是以后的事了。)