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

时间:2017-05-11 22:39:01

标签: makefile compiler-flags cflags

这个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变量。为什么?是否与$(shell ...)变量的CFLAGS部分有关?

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

1 个答案:

答案 0 :(得分:2)

你的makefile中有几个bug,加起来就是这种行为。

首先考虑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添加到了错误的变量使用CXXFLAGS来保存C ++编译器的标志;你添加了CFLAGS,这是为C编译器。

(我已经遗漏了pattern rulesautomatic variables,因为你似乎并不了解它们 - 我敦促你们学习它们,它们非常有用,但那是另一天。)