multiple targets build in makefile - makefile

Any idea why something like this wouldnt work in makefile ?
all : $(GOAL_DB) $(GOAL)
%.d: %.cpp
$(CC) $(CPPFLAGS_DB) $< > $#
%.o : %.cpp
$(CC) $(FLAGS_DB) $< -o $#
$(GOAL_DB) : $(OFILES)
$(CC) $(LFLAGS_DB) -o $# $^ $(LIBS_DB)
strip $(GOAL_DB)
rm -f *.o *.d
%.d: %.cpp
$(CC) $(CPPFLAGS) $< > $#
%.o : %.cpp
$(CC) $(FLAGS) $< -o $#
$(GOAL) : $(OFILES)
$(CC) $(LFLAGS) -o $# $^ $(LIBS)
strip $(GOAL)
rm -f *.o *.d
I'm just trying to build two different targets using make all , GNU make.
The first target builds fine , but it not creating new objects files for another target.

A makefile is not like a standard program that is executed sequentially. It seems you've made the assumption that new rules appearing before a new target will apply to that target. This is not the case. The makefile is fully evaluated for variables, targets, dependencies, and more, before it starts applying rules.
Make is going to match those $(OFILES) against only one of those %.d: targets, probably the first target pattern it finds.
The reason you are not getting new objects for the other target is that to make it looks like you are building the same set of files twice, thus skipping the second build because it's already complete.
A solution is to use 'target specific variables':
all : $(GOAL_DB) $(GOAL)
$(GOAL): BUILD_FLAGS=$(FLAGS)
$(GOAL): BUILD_CPPFLAGS=$(CPPFLAGS)
$(GOAL): BUILD_OUTDIR=./outdir
$(GOAL): $(OFILES)
$(GOAL_DB): BUILD_FLAGS=$(FLAGS_DB)
$(GOAL_DB): BUILD_CPPFLAGS=$(CPPFLAGS_DB)
$(GOAL_DB): BUILD_OUTDIR=./outdir_db
$(GOAL_DB): $(OFILES)
%.d: %.cpp
mkdir -p $(BUILD_OUTDIR)
$(CC) $(BUILD_CPPFLAGS) $< > $(BUILD_OUTDIR)/$#
%.o : %.cpp
mkdir -p $(BUILD_OUTDIR)
$(CC) $(BUILD_FLAGS) $< -o $(BUILD_OUTDIR)/$#

Related

Understanding deeply using a specific case how makefiles are interpreted

I'm trying to understand deeply how makefiles work.
For example, I've the following one:
CC = gcc
CFLAGS = -I.
DEPS = int_array.h
OBJS = int_array.o test_int_array.o
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
test_int_array: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
clean:
rm -rf *.o test_int_array *.dSYM
The part that I really don't understand fully is :
...
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
test_int_array: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
...
I know that the option -c basically indicates just to run the preprocessor, compiling and assembling steps (i.e. without producing executables, I guess).
-o means to write the output to the specified file. Which file in this case?
I understood that $# (and $^ for right) is apparently referring to a "left" side, but which one? Is it referring, in the first case, to the left side of :, that is %.o?
What does $< mean?
Could you please explain step by step how the make tool would interpret those two statements?
I think I understood this part more or less:
...
test_int_array: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
...
which should mean produce an executable called "test_int_array" (which basically is indicated by these options -o $# from the $(OBJS) files on the right (stated using the option $^).
Is $(CFLAGS) needed in both cases? Does the order matter?
In the example:
test_int_array: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
$# is the filename of the target for this rule: test_int_array.
$^ is the names of all prerequisites.
This would be whatever is contained in OBJS, so: int_array.o test_int_array.o
In the example:
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
$< is the name of the first prerequisite: %.c
$# is the filename of the target for this rule: %.o
$(CFLAGS) is not needed for linking, since it only includes the flag -I. Also the CFLAGS indicates that the flags are used for compiling only, hence C FLAGS.
In a Makefile, each rule follows this format:
resulting_file : source_files
steps to get resulting_file from source_files
What is called respectively lefthand and righthand in a rule is the resulting_file and the source_files.
%.ext : %.ext2
is a pattern rule. It allows your Makefile to automatically create any .ext file it needs if it can find a file at the same path with .ext2.
%.c : %.o
is a pattern rule to obtain your .o files (int_array.o test_int_array.o) from their equivalent .c files (int_array.c test_int_array.c)
This is invoked when you specify that $(OBJS) is needed to build the test_int_array file.
Pattern rules automatically use certain variables, such as $(CFLAGS) so you do not need to manually add it in that rule. You can find a full list of implicitly used variables in pattern rules here: https://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_10.html#SEC96
You can find out about $#, $< and $^ and similar here: https://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_10.html#SEC101
$#: the entire lefthand
$<: the first file in the righthand
$^: the entire righthand list of files, space separated.

makefile - define dependency using variable with objects when building many executables

I'm following great tutorial about ffmpeg (http://dranger.com/ffmpeg) and I'm trying to build a generic makefile for it.
My problem is that I cannot define a generic rule for executables to be depenent on an object of the same name but with ".o" suffix.
Example: when invoked make all I want to build 2 executables tutorial01 and tutorial02 out of 2 files tutorial01.cpp and tutorial02.cpp, but first I want to compile them into *.o and then link them.
My whole Makefile is like so:
CC=g++
CXXFLAGS="-std=c++11"
CXXFLAGS+=`sdl-config --cflags`
LDFLAGS=-L/usr/lib/x86_64-linux-gnu/
LDFLAGS+=-L/lib/x86_64-linux-gnu/
LDFLAGS+=-lavutil-ffmpeg -lavcodec-ffmpeg -lavformat-ffmpeg -lswscale-ffmpeg
LDFLAGS+=`sdl-config --libs`
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLES=$(SOURCES:.cpp=)
all : $(EXECUTABLES)
# Not working:
#%$(EXECUTABLES) : $(OBJECTS)
# $(CC) $< -o $# $(LDFLAGS) $(LD_LIBS)
#
# Not working (always substitutes the first found):
#$(EXECUTABLES) : $(OBJECTS)
# $(CC) $< -o $# $(LDFLAGS) $(LD_LIBS)
#
# Not working:
#for exec in $(EXECUTABLES) ; do \
#$(exec) : $(exec).o ; \
#done
#
# Working:
#tutorial01:tutorial01.o
#tutorial02:tutorial02.o
#tutorial03:tutorial03.o
%: %.o
$(CC) $< -o $# $(LDFLAGS) $(LD_LIBS)
%.o : %.cpp
$(CC) $(CXXFLAGS) -c $< -o $#
clean:
rm -rf $(OBJECTS) $(EXECUTABLES)
I tried what is stated above as "not working" and also gave an example of what is working but not generic.
# Not working (always substitutes the first found):
$(EXECUTABLES) : $(OBJECTS)
$(CC) $< -o $# $(LDFLAGS) $(LD_LIBS)
This fails because $(OBJECTS) expands to something like tutorial01.o tutorial02.o tutorial03.o for all targets, and $< expands to the first prerequisite, which is the same (tutorial01.o) for all targets.
# Not working:
for exec in $(EXECUTABLES) ; do \
$(exec) : $(exec).o ; \
done
This fails because it is for-loop written in shell syntax. You can write a for-loop in Make syntax, but it is not needed here.
I would use a pattern rule:
tutorial%: tutorial%.o
$(CC) $< -o $# $(LDFLAGS) $(LD_LIBS)
or a static pattern rule:
$(EXECUTABLES): %: %.o
$(CC) $< -o $# $(LDFLAGS) $(LD_LIBS)

How to move .o on project folder?

I wrote this Makefile to move all .o of the project inside a directory 'obj' in the main folder.
Directories
.:
actor/ lib/ Controller.cpp Controller.h Controller.o doc.txt main.cpp main.o Makefile uno VRP*
./actor:
Customer.cpp Customer.h Customer.o Depot.cpp Depot.h Depot.o Route.cpp Route.h Route.o Vehicle.cpp Vehicle.h Vehicle.o
./lib:
Search.cpp Search.h Search.o Utils.cpp Utils.h Utils.o VRP.cpp VRP.h VRP.o
Makefile
CXX=g++
RM=rm -rf
BIN_NAME=VRP
CPPFLAGS=-s -O2 -std=gnu++11 -Wall
SRCS=$(wildcard *.cpp actor/*.cpp lib/*.cpp)
OBJS=$(subst .cpp,.o,$(SRCS))
all: $(OBJS_DIR) $(BIN_NAME)
$(OBJS_DIR):
mkdir $(OBJS_DIR)
$OBJS_DIR)/%.o : $(SRCS)
$(CXX) $(CPPFLAGS) -c $< -o $#
$(BIN_NAME) : $(OBJS)
$(CXX) -o $# $^
debug:
$(CXX) -g $(CPPFLAGS) -o $(BIN_NAME) $(OBJS)
.PHONY : all clean
clean:
$(RM) $(OBJS) $(OBJS_DIR)
dist-clean: clean
$(RM) $(BIN_NAME)
How can I make it works?
This line $OBJS_DIR)/%.o : $(SRCS) sets the prerequisites of every file that matches $OBJS_DIR)/%.o to all the files in $(SRCS) that's not even close to what you want. (It is also a typo. You are missing the opening ().
You can't write a single rule for what you are trying to do here you need three pattern rules (or one with a vpath/VPATH setup).
$(OBJS_DIR)/%.o: %.cpp
$(CXX) $(CPPFLAGS) -c $< -o $#
$(OBJS_DIR)/%.o: actor/%.cpp
$(CXX) $(CPPFLAGS) -c $< -o $#
$(OBJS_DIR)/%.o: lib/%.cpp
$(CXX) $(CPPFLAGS) -c $< -o $#
That being said you don't actually have any targets that match $(OBJS_DIR)/%.o since the value of $(OBJS) is Controller.o ... actor/Customer.o ... lib/Search.o. To fix that you also need:
OBJS=$(addprefix $(OBJS_DIR)/,$(patsubst %.cpp,%.o,$(notdir $(SRCS))))
$(notdir) to get just the filename from the source files.
$(patsubst) instead of $(subst) just for correctness (subst would have modified a Bar.cpp.cpp file to Bar.o.o).
$(addprefix) to add the $(OBJS_DIR) prefix to the bare object file names.

Want to place all .o files into a directory, but make stops after compilng fist one

I want to have a neat makefile containing explicit dependencies but placing all .o objects in a separate directory to link it altogether later (in an another file).
The problem is that my make stops after compiling the first source and then stops with no error whatsoever.
CC=gcc
CFLAGS=-c -Wall -pedantic -std=c99
DIR=../obj
$(DIR)/CList.o : CList.c CList.h CList_aux.h Observation.h CList_View_aux.h
$(CC) $(CFLAGS) CList.c -o $#
$(DIR)/CList_aux.o : CList_aux.c CList.h CNode.h
$(CC) $(CFLAGS) CList_aux.c -o $#
$(DIR)/CList_View_aux.o : CList_View_aux.c CNode.h Observation.h
$(CC) $(CFLAGS) CList_View_aux.c -o $#
$(DIR)/CNode.o : CNode.c CNode.h CNode_aux.h Observation.h CList.h
$(CC) $(CFLAGS) CNode.c -o $#
$(DIR)/CNode_aux.o : CNode_aux.c CNode.h Observation.h
$(CC) $(CFLAGS) CNode_aux.c -o $#
$(DIR)/Observation.o : Observation.c Observation.h Observation_aux.h CNode.h
$(CC) $(CFLAGS) Observation.c -o $#
$(DIR)/Observation_aux.o : Observation.c Observation.h
$(CC) $(CFLAGS) Observation_aux.c -o $#
$(DIR)/Record.o : Record.c Record.h Observation.h
$(CC) $(CFLAGS) Record.c -o $#
By default, make builds the first target in the makefile. In this case, that is ${DIR}/CList.o.
You need a different first target, conventionally called all:
OBJECTS = \
$(DIR)/CList.o \
$(DIR)/CList_aux.o \
$(DIR)/CList_View_aux.o \
$(DIR)/CNode.o \
$(DIR)/CNode_aux.o \
$(DIR)/Observation.o \
$(DIR)/Observation_aux.o
all: ${OBJECTS}
Note that this works whether there are any object files in the ${DIR} or not; a wildcard looking for object files in the directory makes sure that those that have already been compiled once are up to date, but doesn't try building those which failed to compile previously, or simply aren't there.
If the Makefile is really just as much as you posted, then you're missing the all: rule. Without having an explicit all rule, make assumes that the first present rule is to be made, so it stops after that. In order to achieve what you want, add (append) this to the Makefile (change the final executable name respectively):
OBJECTS = $(wildcard $(DIR)/*.o)
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(LD) $(LDFLAGS) -o $# $^

Makefile : No rule to make target (automatic variables)

I am having trouble with my makefile, i have been reading somme tutoriels on how to make a more re-usable makefile but i am facing this error, and i have been searching for a while now, especially on the GNU make manual and here.
Here is my makefile :
SRC_DIR=./src
BUILD_DIR=./build
OBJS= $(BUILD_DIR)/main.o $(BUILD_DIR)/hamming.o
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h
$(CC) -c $< $(CFLAGS) -o $#
$(BUILD_DIR)/main: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
I am having the error :
make: No rule to make target build/main.o', needed bybuild/main'. Stop.
It seems to me that the objects in the variable OBJS are not associated with the %.o pattern rule, but i don't know why.
In my working directory there is : my makefile and the two directories 'src' and 'build'.
Thank you.
I'll go out on a limb and guess that there is no src/main.h. If that's the case, you could fix things this way:
$(BUILD_DIR)/hamming.o: $(BUILD_DIR)/%.o : $(SRC_DIR)/%.h
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) -c $< $(CFLAGS) -o $#
EDIT:
Now I'm puzzled. Please try this (it is crude, but if it works we can refine it):
SRC_DIR=./src
BUILD_DIR=./build
OBJS= $(BUILD_DIR)/main.o $(BUILD_DIR)/hamming.o
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h
$(CC) -c $< $(CFLAGS) -o $#
$(BUILD_DIR)/main.o: $(SRC_DIR)/main.c
$(CC) -c $< $(CFLAGS) -o $#
$(BUILD_DIR)/main: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
Here is a little documentation I put together for NMake a while back I hope it helps. Are you sure there are only tabs before the commands. You can't have spaces that is the number one error I have seen in the past.

Resources