Library update and Makefile - makefile

It is a long time since I haven't done Makefiles. My actual Makefile works except that if a lib in $(LIB) changes, I get a message that make has nothing to do. The dependency on libs in $(LIB) isn't taken into account. Note that in $(LIB) I have libraries with their full path.
all: $(OBJ_LIST) $(TEST_LOAD) $(TEST_CPP_UNIT) $(LIB)
%.o: %.cpp
g++ -c $(CPPFLAGS) -o $# $<

You haven't really expressed any useful dependencies. If you want something specific to be rebuilt when something in $(LIB) changes, you'll need to specify that explicitly. For instance:
all: my_app
# my_app will be rebuilt if something in $(LIB) changes
my_app: $(OBJ_LIST) $(LIB)
g++ -o $# $<
%.o: %.cpp
g++ -c $(CPPFLAGS) -o $# $<

Related

How to use a makefile with gprof to recompile dependencies?

I have a makefile which compiles and links together objects to create an executable. In order to profile, I need to use an additional flag -pg before compiling. Here is my current makefile:
# objects required
OBJS = obj1.o obj2.o
# flags
FC = gfortran
FLAGS = -O3
PROFILEFLAG = -pg
# executable
EXE = program.exe
PROFEXE = program_prof.exe
# suffixes
.SUFFIXES: .o .f90
# rules
%.o: %.f90
$(FC) $(FLAGS) -c $<
default: $(OBJS)
$(FC) $(FLAGS) $(OBJS) -o $(EXE)
profile: $(OBJS)
$(FC) $(FLAGS) $(OBJS) -o $(PROFEXE) $(PROFILEFLAG)
clean:
rm *.o *.mod
Running make profile runs the rule associated with profile, which creates the executable program_prof.exe which can be profiled. However, since the individual dependencies obj1 and obj2 are not compiled with the -pg flag, I cannot profile the code running in those files.
Is there a way I can add a rule such that the individual objects are also recompiled with the -pg flag when I need to profile?
Currently I am editing the individual object dependencies manually to:
%.o: %.f90
$(FC) $(FLAGS) -c $< -pg
which works as expected, but is time consuming (my actual makefile has multiple dependencies in subfolders, all of which need to be edited). Ideally, I am looking for a rule which should recompile individual objects with the `-pg' flag.
You can do exactly what you want, with target-specific variables:
PROFILE :=
%.o : %.f90
$(FC) $(FLAGS) $(PROFILE) -c -o $# $<
default: $(OBJS)
....
profile: PROFILE := -pg
profile: $(OBJS)
....
However, this is not usually the preferred way. Unless you're really diligent about always doing a full clean when switching back and forth between profile and non-profile builds it's very easy to get confused and have some objects compiled with profiling and others compiled without.
As mentioned in the comments, it's better to build them into separate directories:
$(PDIR)/%.o : %.f90
#mkdir -p $(#D)
$(FC) $(FLAGS) -pg -c -o $# $<
$(ODIR)/%.o : %.f90
#mkdir -p $(#D)
$(FC) $(FLAGS) -c -o $# $<
default: $(addprefix $(ODIR)/,$(OBJS))
$(FC) $(FLAGS) $^ -o $#
profile: $(addprefix $(PDIR)/,$(OBJS))
$(FC) $(FLAGS) -pg $^ -o $#

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

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 can I put .o files to different folder and how should I improve this overall?

I've never really wrote any makefiles before and I have little knowledge of its syntax.
I'd like to put .o files into separate folder, obj/ for example. But I'm a bit lost how this should be done since there seem to be lot's of different ways to write makefile.
This is what I have currently and I would like to improve it.
PROGRAM=Project
CC=g++
CFLAGS=-c -g -std=c++0x -Wall -Wextra -pedantic -I $(SFML)/include -I src
LDFLAGS=-lsfml-graphics -lsfml-window -lsfml-system -lsfml-audio -L $(SFML)/lib -Wl,-rpath=$(SFML)/lib -Wl,-rpath-link=$(SFML)/lib
SOURCES=$(wildcard src/*.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=bin/project
all: build $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) $(LDFLAGS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
build:
#mkdir -p bin
clean:
rm -rf $(EXECUTABLE) $(OBJECTS)
I've tried some different approaches but haven't yet figured out how to put .o files in their own folder.
Replace your OBJECTS line with something like:
OBJECTS=$(patsubst src/%.cpp,obj/%.o,$(SOURCES))
Remove the .ccp.o rule and replace it with something like:
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) $< -o $#
You can probably also remove $(SOURCES) from the prerequisite list of the all target unless you expect make to try to create those files somehow.

Resources