Search code examples
makefilecompiler-flagscflags

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


There are three programs build by this Makefile. They follow the same pattern, but produce different build commands when run. Specifically, I require compilation with c++11 but can only achieve this on one of the build commands. Why is this?

Makefile:

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

Output:

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

We see that only the second g++ command fully utilizes CFLAGS variable. Why? Does it have to do with the $(shell ...) portion of the CFLAGS variable?

Edit: Was able to solve my problem by changing the name of the object file vector_search_test.o to vector_search.o Why did that work?


Solution

  • You have a couple of bugs in your makefile, adding up to this behavior.

    First consider OBJS, which contains

    generic_queue.o map_compare.o vector_search.o
    

    These files are prerequisites of other targets, but you never actually use generic_queue.o or vector_search.o. Bug #1: you have extra prerequisites by mistake.

    These files are prerequisites of other targets, so Make must build them. But how? You have provided rules for three object files:

    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
        ...
    

    That last one will do for map_compare.o, but you have given no rules for generic_queue.o or vector_search.o (and there's really no reason you should, since you never use them). But Make knows how to perform certain standard builds, such as foo.cpp => foo.o. If you don't provide a rule, Make will use its implicit rule, which works out to something like this:

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

    This is very similar to the rules you wrote. In fact, you probably wouldn't have noticed the difference -- and you could have omitted your rules and let Make rely on this one, but Bug #2, you added your flags -std=c++11 -g -Wall whatever to the wrong variable. Make uses CXXFLAGS to hold flags for the C++ compiler; you added yours to CFLAGS, which is for the C compiler.

    (I've left out pattern rules and automatic variables since you don't seem to know about them-- I urge you to learn them, they're very useful, but that's for another day.)