How can I put .o files to different folder and how should I improve this overall? - makefile

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.

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

Make: Compiling only one .c file though i modify the header file which is included in two .c files [duplicate]

This question already has answers here:
'make' does not recompile when source file has been edited
(3 answers)
Closed 4 years ago.
I have two .c files and one .h file which is included in both .c files.
I have make file :
CC=gcc
CFLAGS=-I.
OBJ = hellofunc.o hellomake.o
DEPS := $(OBJ:.o=.d)
-include $(DEPS)
%.o: %.c
$(CC) $(CFLAGS) -MM -MT $# -MF $(patsubst %.o,%.d,$#) $<
$(CC) -c -o $# $< $(CFLAGS)
hellomake: hellomake.o hellofunc.o
$(CC) -o $# $^
I modified hellomake.h header file and then ran above make file. It is compiling only the first file which is assigned to DEPS variable, Which is hellofunc.c
FYI, When i change the order of DEPS variable it is compiling hellomake.o , Seems like make is only picking first file assigned to DEPS variable.
Is there anything wrong in my makefile.. Please help.
As #tripleee noted in the comments, make will by default build the first target it encounters. Since the include files are included directly, as if they were cut-and-pasted in place, the first target in the first .d file (which I'm guessing you'll find to be hellofunc.c) is the first target that make encounters, so that's what make aims to build.
If you move the include line to the end of the file, then the first target in the file will be hellomake, and so that's the target make will attempt to build by default.
Meta remark: if you can, I'd say it's better to avoid this pattern of depending on .d files, and instead aim to express sufficiently many of the dependencies ‘by hand’ directly in the makefile. Doing it this .d way does work (ie, I'm not saying what you're doing is wrong) and appears to be labour-saving, but in my experience it tends to be a little brittle, partly because if you don't have the .d files to hand then you suddenly have zero dependencies. In order to have the .d files to hand, you'll have to check them in to your code repository (you are using a repository, aren't you?), but that will mean they'll frequently be trivially out of date, and... it can turn into a bit of a mess.
EDIT: considered MadScientist's comment and blog post about separate recipe for .d files.
You could tell make how to generate the .d files with a separate rule instead of putting this in another recipe (but see the above mentioned blog post for several reasons for not doing so).
And you should probably tell make that your default goal is hellomake:
.DEFAULT_GOAL := hellomake
CC=gcc
CFLAGS=-I.
OBJ = hellofunc.o hellomake.o
DEPS := $(OBJ:.o=.d)
-include $(DEPS)
%.d: %.c
$(CC) $(CFLAGS) -MM -MT $# -MF $# $<
%.o: %.c
$(CC) -c -o $# $< $(CFLAGS)
hellomake: hellomake.o hellofunc.o
$(CC) -o $# $^
And it would probably be even better if you were letting make find the source files and deduce the rest:
.DEFAULT_GOAL := hellomake
CC := gcc
CFLAGS := -I.
SRCS := $(wildcard *.c)
OBJS := $(patsubst %.c,%.o,$(SRC))
DEPS := $(patsubst %.c,%.d,$(SRC))
-include $(DEPS)
%.d: %.c
$(CC) $(CFLAGS) -MM -MT $# -MF $# $<
%.o: %.c
$(CC) -c -o $# $< $(CFLAGS)
hellomake: $(OBJS)
$(CC) -o $# $^
Finally, following MadScientist's advices, a better, more efficient, less prone to failures solution could be:
.DEFAULT_GOAL := hellomake
CC := gcc
CFLAGS := -I.
SRCS := $(wildcard *.c)
OBJS := $(patsubst %.c,%.o,$(SRC))
DEPS := $(wildcard $(patsubst %.c,%.d,$(SRC)))
include $(DEPS)
%.o: %.c %.d
$(CC) -MT $# -MMD -MP -MF $*.Td $(CFLAGS) -c -o $# $<
mv -f $*.Td $*.d && touch $#
hellomake: $(OBJS)
$(CC) -o $# $^
%.d: ;
.PRECIOUS: %.d

Why I don't need to add prerequisite ".depend" in this make file?

I have a make file I wrote which represents a simple example of auto-detecting if a header file is changed using .depend generated by gcc -MM -MF.
Consider the following makefile: We have main.c and factorial.h
CC=gcc
CFLAGS=-c -Wall
OBJECTS=main.o
SRCS=main.c
EXECUTABLE=program
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) -o $(EXECUTABLE)
.depend: $(SRCS)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ -MF ./.depend;
sinclude .depend
#main.o: main.c factorial.h
clean:
rm -rf *.o $(EXECUTABLE) .depend
This works fine and I want to know why!
The common sense is to write
$(EXECUTABLE): $(OBJECTS) .depend
because we want to make sure the file .depend is there. However, it seems like omitting it works fine, too. Why? Also, I'd like to know what include (or sinclude in this case) actually does. I think: in our example, include .depend would be replaced by
main.o: main.c factorial.h, but again the workflow doesn't make sense. Any experts?
Make will automatically try to remake the target of an include directive
[...]after reading in all makefiles, make will consider each as a goal target and attempt to update it.
The line sinclude .depend tells make "Read in .depend, don't quit if it fails, look for any matching rules, and remake .depend if it's out of date."
In any case you should create dependencies as a side effect of compilation, there's really no need for the extra step
target := program
sources := main.c
objs := $(sources:.c=.o)
deps := $(objs:.o=.d)
CPPFLAGS := -MMD -MP
CFLAGS := -Wall
$(target): $(objs)
$(LINK.o) $^ $(LDLIBS) -o $#
clean: ; $(RM) $(target) $(objs) $(deps)
-include $(deps)

What does the target ".cpp.o:" mean in a Makefile?

I'm learning the GNU makefile. I came across this page: http://mrbook.org/blog/tutorials/make/
At the end of this article, I found this:
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 $#
Could anyone explain what's in OBJECT variable and what target .cpp.o: means (also the $< in it)?
I also found when I use something like:
SRC = $(wildcard $(SRC_DIR)*.c)
SRC_OBJS = $(patsubst %.c, %.o, $(SRC))
and use "$(SRC_OBJS)" as a target, it will compile all objects for each required object. This doesn't happen for the first one. What's the difference?
It's a suffix rule telling make how to turn file.cpp into file.o for an arbitrary file.
$< is an automatic variable referencing the source file, file.cpp in the case of the suffix rule.
$# is an automatic variable referencing the target file, file.o.

In makefiles, how can I compile module files first using automatic variables?

I am new to makefiles. My current makefile looks like this:
FC=ifort
FFLAGS=-c -module mod/
LDFLAGS=
SOURCES=$(wildcard src/*.f90)
OBJECTS=$(addprefix obj/, $(notdir $(SOURCES:.f90=.o)))
EXECUTABLE=RUN
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(FC) $(LDFLAGS) $^ -o $#
obj/%.o: src/%.f90
$(FC) $(FFLAGS) $< -o $#
The problem is my module files have names start with s and p which are usually compiled in the end of the list, and this causes problems when I have some changes in these module files. I am wondering what is the easiest way to compile these module files first? Yes I can change my module file directory to mod/ and set variables:
MODULES=$(wildcard mod/*.f90)
MODULE_OBJECTS=$(addprefix obj/, $(notdir $(MODULES: .f90=o)))
then add
$(MODULE_OBJECTS):$(MODULES)
$(FC) $(FFLAGS) $< -O $#
But, is there other ways to do this?

Resources