Makefile PHONY/ALL target: only builds the first - makefile

FC=gfortran
perf.c.bin: perf.c
$(CC) -std=c99 -O3 $< -o $#
perf.f90.bin: perf.f90
$(FC) $(FFLAGS) -O3 $< -o $#
all: perf.c.bin perf.f90.bin
.PHONY: all
If I run just make, it just builds the perf.c.bin. If I run make all, it builds both perf.*.bin. Why?

The default target is the first target, not the one named "all". If you want your "all" to be the default (so that make is equivalent to make all) then just put it first.

Related

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

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.

Compiling for Multiple Targets

I want to compile my program both to linux and windows using g++ and mingw respectively. The only difference between the compilations is the compiler to use and output file name.
A single make command should produce both output files. What is the best way to achieve this with as little duplications in the makefile as possible?
How about this:
linux-name: CC:=g++
windows-name: CC:=mingw
linux-name windows-name:
$(CC) whatever -o $#
EDIT:
What I wrote above is only the new part of the makefile; I assumed that the rest of the makefile was implied. To be more explicit:
all: linux-name windows-name
linux-name: CC:=g++
windows-name: CC:=mingw
linux-name windows-name: foo.o bar.o baz.o SomethingElse
$(CC) $(CCFLAGS) whatever $^ -o $#
%.o: %.cc
$(CC) $(CFLAGS) -I$(INC_DIR) whatever -c $< -o $#
SomethingElse:
build somehow

Could someone explain this make file?

I found this makefile on this site. They don't explain this example, so I was wondering if anybody new what was going on.
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
sets four variables to be constant strings. For the rest of the makefile, wherever $(CC) appears (for example), it will be replaced by g++
OBJECTS=$(SOURCES:.cpp=.o)
sets the variable OBJECTS to be the same as SOURCES, except wherever the pattern .cpp appears in a words of SOURCES, its replaced by .o
EXECUTABLE=hello
sets another constant string var
all: $(SOURCES) $(EXECUTABLE)
The first actual rule in the makefile, This tells make that to build all it must first build everything in $(SOURCES) and $(EXECUTABLE), and then do nothing. Since this is first, it becomes the default target, so running make is equivalent to make all
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
Another rule: to create $(EXECUTABLE) (which expands to hello) it must first build everything in $(OBJECTS) (equivalent to main.o hello.o factorial.o) and then run the command $(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) -o $# $<
A pattern rule: in order to build a file ending in .o, first rebuild/create/find the corresponding file ending in .cpp, and then run the command $(CC) $(CFLAGS) -o $# $<.
These last two rules contain the special variables $# and $< which are only valid in rule actions and expand to the target and first dependency respectively
So when you run make, it reads all this and then tries to build the default target (all).
Since it doesn't exist, it tries to build the files main.cpp, hello.cpp, factorial.cpp, and hello. Since the first 3 (presumably) exist, it looks for rules/dependencies for them, but doesn't find any, so decides there's nothing to do for them. If they didn't exist, make would give an error saying "no rule to make target 'main.cpp'"
In the case of "hello" it depends on main.o, hello.o and factorial.o, so it looks into them. For main.o, the pattern rule says it depends on main.cpp, so if main.o doesn't exist or if main.cpp is newer, it will run the command g++ -c -Wall -o main.o main.cpp. The same happens for hello.o and factorial.o.
Once those are done, if hello doesn't exist or is older than any of those .o files (which may have just changed, so are possibly pretty new), it will run that command to relink it. Finally, it will run the empty command (doing nothing) to 'rebuild' all.

How to define rules in the Makefile to compile only that *.cpp files which was modified (and their dependencies), not all *.cpp files

Lets say I have files:
Libs:
one.cpp, one.h
two.cpp, two.h
three.cpp, three.h
Program:
program.cpp
Is there way, to create Makefile which will compile only that *.cpp which were modified from last compilation?
Currently I have something like that:
SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)
all: $(OBJS) program
.cpp.o:
g++ -Wall -c $<
program:
g++ -Wall $(OBJS) program.cpp -o program
clean:
rm -f $(OBJS) program
I works fine, but when I compile my program and then change two.cpp or two.h I need to run "make clean" first, because when I secondly run "make" I get:
Nothing to be done for 'all'.
I would like to change my Makefile in that way, it would recognize my changes and recompile that file and its dependencies (if one.cpp uses code from two.cpp which was modified, both files should be recompiled).
So if I modify two.cpp, make should do:
g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program
But if one.cpp uses code from two.cpp which was modified, make shold do:
g++ -Wall -c one.cpp
g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program
First we make the object files prerequisites of the executable. Once this is done, Make will rebuild program whenever one of the SRCS changes, so we don't need OBJS as an explicit target:
all: program
program: $(OBJS)
g++ -Wall $(OBJS) program.cpp -o program
Then we make the header files prerequisites of the objects, so that if we change three.h, Make will rebuild three.o:
$(OBJS): %.o : %.h
And finally since one.cpp uses code from two.cpp by means of two.h (I hope), we make two.h a prerequisite of one.o:
one.o: two.h
And to make things cleaner and easier to maintain we use automatic variables:
program: $(OBJS)
g++ -Wall $^ program.cpp -o $#
Put it all together and we get:
SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)
all: program
$(OBJS): %.o : %.h
one.o: two.h
.cpp.o:
g++ -Wall -c $<
program: $(OBJS)
g++ -Wall $^ program.cpp -o $#
clean:
rm -f $(OBJS) program
There are a few more things we could do (like adding program.o to OBJS), but this is enough for today.
Add the files a command depends upon to run to the right of the target name.
Example:
default: hello.c
gcc -o hello.bin hello.c
install: hello.bin
cp hello.bin ../
All you need to do is tell make that the .o file depends on the .cpp file:
%.cpp.o: %.cpp
g++ -Wall -c -o $# $<

Resources