0

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?

errolflynn
  • 641
  • 2
  • 11
  • 24

1 Answers1

2

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

Beta
  • 96,650
  • 16
  • 149
  • 150
  • simple to understand, thanks. this is an old makefile for a series of test programs, but i don't tend to write makefiles much anyways. If u have time, how would u edit this to use `pattern rules` and `automatic variables`? – errolflynn May 12 '17 at 15:12
  • @errolflynn: Look at the manual section I cited, and play around with the tools. And decide where and why to insert "_test" in file names; it's not clear to me. If you need more help, my freelance rates are quite reasonable, all things considered. – Beta May 12 '17 at 22:52