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

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?

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

Related

Makefile - Compile Single Objects in different directory

I have been combing the web and I can't figure out the right way to get this to work. Just trying to create a simple Makefile which takes my source and only builds the changed files. I need all the .o files to be put in the same output folder. I currently have everything working except that if I change one file the whole thing rebuilds. For example, if I change main.c it will compile EOL.c as well. However if nothing changes it says nothing needs to be done.
NAME=Program
CC=arm-none-eabi-gcc
CFLAGS=-c -Wall -O0 -std=c99 \
-nostartfiles --specs=nano.specs \
-mthumb -fmessage-length=0 \
-fsigned-char -ffunction-sections \
-fdata-sections -mcpu=cortex-m0
BID?=_DEV
DEFINES= -DPROD -DBLD_ID=\"$(BID)\"
LDFLAGS= -nostartfiles
INCLUDES= -ISrc/App/Include -ISrc/Device/CMSIS/Include
SOURCES= Src/main.c Src/App/Source/Application.c Src/App/Source/EOL.c Src/Svc/Source/TimerManager.c
OBJECTS=$(OBJECTS1:.c=.o)
OBJECTS1=$(SOURCES:.S=.o)
OFILES1=$(notdir ${OBJECTS})
OFILES=$(addprefix $(OBJDIR)/,$(OFILES1))
OBJDIR=Output
.PHONY: all rebuild clean
all: $(OBJDIR) $(SOURCES) $(OBJDIR)/$(NAME).hex
%.hex: %.elf
arm-none-eabi-objcopy -O ihex $< $#
%elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(OFILES) -o $#
rebuild: clean all
.SECONDARY:
.c.o:
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $(OBJDIR)/$(notdir $#)
.S.o:
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $(OBJDIR)/$(notdir $#)
$(OBJDIR):
mkdir $(OBJDIR)
clean:
rm -f $(OBJDIR)/*.o $(OBJDIR)/*.elf $(OBJDIR)/*.hex $(OBJDIR)/*.bin
There are several problems with this makefile. Basically you have rules whose targets are not the files they actually produce, and a rule whose prerequisites are not the files it actually needs.
Suppose you have modified Src/main.c and try to rebuild Output/Program.elf using this rule:
%elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(OFILES) -o $#
The prerequisites ($(OBJECTS)) are actually Src/main.o Src/App/Source/EOL.o and so on. These files do not exist -- they never exist -- but there is a rule for them:
.c.o:
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $(OBJDIR)/$(notdir $#)
Make sees that Src/main.o depends on Src/main.c and must therefore be rebuilt, as must Output/Program.elf. So it invokes this rule -- which actually builds Output/main.o. But the elf rule demands all of the (imaginary) object files, so all of the sources must be recompiled-- into object files that already exist and are not out of date, but which Make wasn't paying attention to.
The first thing to do is fix the object rules, but there's a problem: although the rules are flawed, they have the advantage of helping Make to find the corresponding source files (before misusing them), like this:
Src/App/Source/EOL.o: Src/App/Source/EOL.c
...
How can we tell Make where to find the source file corresponding to Output/EOL.o? There's more than one way, but a good way is by using vpath:
vpath %.c Src/App/Source
Output/EOL.o: EOL.c
...
All we have to do is create a list of source directories, pass it to vpath, and modify the pattern rule:
SRCDIRS := $(dir $(SOURCES))
vpath %.c $(SRCDIRS)
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $#
(The .S.o rule can be fixed the same way.)
Then modify the elf rule to name -- and use -- its real prerequisites:
%elf: $(OFILES)
$(CC) $(LDFLAGS) $^ -o $#

Makefile executable not generated

CC=g++
CFLAGS=-c -o
PROG=craps
LIBSRCS=craps.cpp craps_game.cpp craps_helper.cpp craps_io.cpp
LIBOBJS=$(patsubst %.cpp, %.o, $(LIBSRCS))
LIBCRAPS=craps
CXXFLAGS=-I./ -fpic
LDFLAGS=-L./
all: $(PROG)
$(PROG): $(LIBSRCS)
$(CC) $(LDFLAGS) -l$(PROG) -o $(PROG) $(PROG).o
$(LIBCRAPS): $(LIBOBJS)
$(CC) -shared -o lib$(LIBCRAPS).so $(LIBOBJS)
%.o: %.cpp
$(CC) $(CXXFLAGS) -c -o $# $
depend:
${CC} -MM ${PROG}.cpp ${LIBSCRS} > depends.mak
include depends.mak
Why executable file not compiled and generated?
All o files generated with no error.
Why this line $(CC) $(LDFLAGS) -l$(PROG) -o $(PROG) $(PROG).o does not run ? what is wrong ?
You misunderstood my comment. I'm saying this this:
PROG=craps LIBSRCS=craps.cpp craps_game.cpp craps_helper.cpp craps_io.cpp
is wrong. You can't assign two variables on the same line, in a makefile. These variables must look like this:
PROG=craps
LIBSRCS=craps.cpp craps_game.cpp craps_helper.cpp craps_io.cpp
I'm asking, is the latter how your actual makefile looks, or is the example you provided here just inaccurate.
Also these rules both have incorrect newlines:
$(PROG):
$(LIBSRCS) $(CC) $(LDFLAGS) -l$(PROG) -o $(PROG) $(PROG).o
$(LIBCRAPS):
$(LIBOBJS) $(CC) -shared -o lib$(LIBCRAPS).so $(LIBOBJS)
You are adding the prerequisite lists $(LIBSRCS) and $(LIBOBJS) into the recipe (shell commands) used to build the target. Prerequisites must be on the same line as the target. These should look like this:
$(PROG): $(LIBSRCS)
$(CC) $(LDFLAGS) -l$(PROG) -o $(PROG) $(PROG).o
$(LIBCRAPS): $(LIBOBJS)
$(CC) -shared -o lib$(LIBCRAPS).so $(LIBOBJS)
This is your problem, below
Finally, you can't have both the program and the target have the same name:
PROG=craps
LIBCRAPS=craps
You can only create one target with a given name so the value of both these variables cannot be craps. Maybe you wanted:
PROG = craps
LIBCRAPS = libcraps.so
Assuming the makefile you've quoted here is identical to what you're running, you must be getting warnings like this from make when you run this makefile:
Makefile:15: warning: overriding recipe for target 'craps'
Makefile:12: warning: ignoring old recipe for target 'craps'
These warnings are why you are not seeing the compile rule invoked: the library rule is overriding it just as the warning says.
Also, you should have the program depend on the library (since it links it) and the object file $(PROG).o because currently make doesn't know it needs to be built. And you don't need to have it depend on all the source files. You want something like:
$(PROG): $(LIBCRAPS) $(PROG).o
$(CC) $(LDFLAGS) -l$(PROG) -o $(PROG) $(PROG).o

the correct usage of `LDFLAGS` in makefile

First, the makefile in question roughly looks like this (I'm writing off my memory):
CXX=g++
CXXFLAGS=-c -Wall -std=c++11 -O3
LDFLAGS=-Wall -std=c++11 -O3
all: clean car.out
clean:
rm -f *.o *.out
car.out: a.o b.o
$(CXX) -o $# $(LDFLAGS) $^
a.o: a.cpp
$(CXX) $(CXXFLAGS) $<
b.o: b.cpp
$(CXX) $(CXXFLAGS) $<
Basically this will make some object files first and then link them together. I think this is semantically unreasonable because:
As its name suggests, LDFLAGS is for ld, but there is no flags for it here. If we need some external library like OpenGL, then a flag like -LGL is passed to g++, and then g++ would pass it to the linker. In that case, it would be reasonable to put -LGL in LDFLAGS.
Even if it's the case where we put flags such as -Wall into LDFLAGS, it doesn't make much sense. This kind of flags are intuitively for the compilation process, not linking (unless I understand this process wrong).
In https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html, there is a piece of code $(CC) -c $(CFLAGS) $(CPPFLAGS), which passes -c explicitly. I think this is the better way to do this--putting all compilation flags (e.g. -Wall) into CXXFLAGS, and pass in -c explicitly for object file compilation. Of course, the web page does not say that this piece of code is definitely better or the only way to do it.
So the only reason I can think of to use LDFLAGS there is because "there's a linking step," which doesn't make much sense to me. In my opinion, the makefile above should look like:
CXX=g++
CXXFLAGS=-Wall -std=c++11 -O3
all: clean car.out
clean:
rm -f *.o *.out
car.out: a.o b.o
$(CXX) -o $# $(LDFLAGS) $^
a.o: a.cpp
$(CXX) -c $(CXXFLAGS) $<
b.o: b.cpp
$(CXX) -c $(CXXFLAGS) $<
LDFLAGS defaults to an empty string, so we can still have it there for the linking step.
However I'm not sure if I'm right.
You are right that compilation flags have nothing to do in LDFLAGS. Just define LDFLAGS explicitly so that another editor -or yourself, when some time has passed- can figure out at a glance that 1. it is empty and 2. where to modify it (like adding -s to it, which is quite common).

How to write a makefile for llvm IR

If I have 3 files, function.h, function.c and my_program.c which calls a method in function.h all in the same directory, what would be the best way to write a makefile so that I end up with a my_program.bc that would actually run when I type in lli my_program.bc? (I need to run a user defined pass that would insert stuff into the functions - should I run the pass on function.bc and test.bc, or should I link before running the pass?)
I've tried llvm-link function.bc my_program.bc with no luck. I feel I'm either missing something simple or going about the whole thing wrong.
Current terrible none-working makefile:
.PHONY: all clean
CC = clang
CFLAGS = -std=gnu99 -D_POSIX_C_SOURCE=200809L -g -Wall
IRFLAGS = -O3 -emit-llvm
TARGET = test
DEPS = functions.h
all: $(TARGET)
bc: test2
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
%.bc: %.c $(DEPS)
$(CC) $(IRFLAGS) -c -o $# $<
test2: test.bc functions.bc
llvm-link -o test2.bc $< functions.bc
test: test.o functions.o
$(CC) $(CFLAGS) -o $# $^
clean:
$(RM) $(TARGET) *.o *.bc
Why not just write a normal Makefile to produce the desired executable,
then use wllvm?
Shameless plug for wllvm:
https://github.com/SRI-CSL/whole-program-llvm
I do not use lli, so I would be interested to hear about how it resolved
any reliance on stdlibc that your program may have.

Makefile with generic intermediate rules

I have a makefile that works that looks like this:
TARGET:=prog
SOURCES:=a.c b.c
CFLAGS:=-Wall -g -O2
OBJECTS:=$(SOURCES:%.c=%.o)
$(TARGET): $(OBJECTS)
gcc -o $# $^
%.o: %.c
gcc $(CFLAGS) -c -o $# $<
clean:
rm -f $(TARGET) $(OBJECTS)
The only variables that the user needs to change are the target name and the sources required to build it. The objects that need to be generated are automatically determined from the sources. I would like to extend this to support multiple targets, each with its own list of sources. I'm having trouble getting the syntax right, though. This is the general idea:
TARGETS:=prog1 prog2
SOURCES_prog1:=a.c b.c
SOURCES_prog2:=a.c c.c
CFLAGS:=-Wall -g -O2
OBJECTS_$#=$(SOURCES_$#:%.c=%.o)
$(TARGETS): $(OBJECTS_$#)
gcc -o $# $^
%.o: %.c
gcc $(CFLAGS) -c -o $# $<
clean:
rm -f $(TARGET) $(OBJECTS)
But I can't get the object list to be generated correctly. I'm also unsure how to write the clean rule to clean all of the objects. Is this possible?
There are two primary ways that I see to do this.
The first involves dynamically creating the target/prerequisite mappings using the $(eval) function.
TARGETS:=prog1 prog2
SOURCES_prog1:=a.c b.c
SOURCES_prog2:=a.c c.c
CFLAGS:=-Wall -g -O2
$(TARGETS):
gcc -o $# $^
$(foreach t,$(TARGETS),$(eval OBJECTS_$t := $(SOURCES_$t:.c=.o))$(eval $t: $(OBJECTS_$t)))
The second involves using Secondary Expansion.
TARGETS:=prog1 prog2
SOURCES_prog1:=a.c b.c
SOURCES_prog2:=a.c c.c
CFLAGS:=-Wall -g -O2
.SECONDEXPANSION:
$(TARGETS): $$(OBJECTS_$$#)
gcc -o $# $^
$(foreach t,$(TARGETS),$(eval OBJECTS_$t := $(SOURCES_$t:.c=.o)))
In either case the clean target becomes:
clean:
rm -f $(TARGETS) $(foreach t,$(TARGETS),$(OBJECTS_$t))

Resources