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

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 $# $^

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 $#

reduce the amount of duplicated rules in makefile

The goal is to specify a build directory where .o and the executable will reside after building the project
currently I've written this Makefile that does this but I have to specify for each object file its directory manually.
PROGNAME = parkingLotApp
CXX = g++
SRC = main.cpp \
parking_car.cpp \
parking_lot.cpp \
shader.cpp \
shader_manager.cpp
OBJS = main.o \
parking_car.o \
parking_lot.o \
shader.o \
shader_manager.o \
BUILDIR = build
CXXFLAGS = -Wall -c -std=c++11
LDFLAGS = -Wall
LIBS = -lGL -lGLEW -lglfw
$(PROGNAME): $(OBJS)
$(CXX) $(BUILDIR)/*.o $(LDFLAGS) $(LIBS) -o $(BUILDIR)/$(PROGNAME)
main.o:
$(CXX) $(CXXFLAGS) $(INCDIR) main.cpp -o $(BUILDIR)/main.o
parking_car.o:
$(CXX) $(CXXFLAGS) $(INCDIR) parking_car.cpp -o $(BUILDIR)/parking_car.o
parking_lot.o:
$(CXX) $(CXXFLAGS) $(INCDIR) parking_lot.cpp -o $(BUILDIR)/parking_lot.o
shader.o:
$(CXX) $(CXXFLAGS) $(INCDIR) shader.cpp -o $(BUILDIR)/shader.o
shader_manager.o:
$(CXX) $(CXXFLAGS) $(INCDIR) shader_manager.cpp -o $(BUILDIR)/shader_manager.o
.PHONY: clean
clean:
rm $(BUILDIR)/*.o $(BUILDIR)/$(PROGNAME)
Again, this works as I expected but I want to get rid of manually specifying directory ($(BUILDIR)/someobject.o) for each .o file
I tried this instead of duplicated lines above
$(OBJS):
$(CXX) $(CXXFLAGS) $(INCDIR) $(SRC) -o $(patsubst %, $(BUILDIR)/%, $(OBJS))
but it gave an error for all build/*.o
saying that
no such file or directory
Why it does not work ?
Your attempt to combine all of the object file rules failed because the compiler did not know that you wanted to compile all of the source files separately.
We start with the object file rules:
main.o:
$(CXX) $(CXXFLAGS) $(INCDIR) main.cpp -o $(BUILDIR)/main.o
...
Then we realize that these rules don't build what they claim to build; this rule claims to build main.o, but it actually builds build/main.o. This will cause trouble later, so we fix it:
$(BUILDIR)/main.o:
$(CXX) $(CXXFLAGS) $(INCDIR) main.cpp -o $(BUILDIR)/main.o
...
Then we notice that we forgot to tell Make about the prerequisite source files-- Make does not know that it should rebuild this target if main.cpp has changed. So we correct that:
$(BUILDIR)/main.o: main.cpp
$(CXX) $(CXXFLAGS) $(INCDIR) main.cpp -o $(BUILDIR)/main.o
...
Then we use automatic variables to reduce the redundancy:
$(BUILDIR)/main.o: main.cpp
$(CXX) $(CXXFLAGS) $(INCDIR) $# -o $#
...
Then we notice that all of these object-file-building rules have exactly the same command, so we combine them into a pattern rule:
$(BUILDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) $(INCDIR) $# -o $#
(You could make them into a static pattern rule, but this is enough for one day.)
EDIT:
We must also change the PROGNAME rule to give it the correct name and prerequisites, and use automatic variables:
$(BUILDIR)/$(PROGNAME): $(addprefix $(BUILDIR)/, $(OBJS))
$(CXX) $^ $(LDFLAGS) $(LIBS) -o $#

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.

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.

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