Create object files in one folder from different source folders - makefile

I am creating a Makefile of a Keil based project. I have a working Makefile now, but I have manually written rules for all the source files, something like this:
out/abc.o: ../../../src/modules/abc.c
ARMCC -o $# $(FLAGS) $^
out/def.o: ../../../src/utilities/def.c
ARMCC -o $# $(FLAGS) $^
out/xyz.o: src/xyz.c
ARMCC -o $# $(FLAGS) $^
which has become kinda long. The object files need to be in one directory(/out), but the source files are in different levels and in various folders like utilities, modules etc. Is there a way to shorten my Makefile so that it scans these different levels of source files and creates the object files?
EDIT:
A follow-up question to the answer. My linker rule is something like this, along with the VPATH addition. I added one directory to VPATH and others are still explicitly compiled.
OBJECT_FILES=out/abc.o out/def.o out/xyz.o
out/binary.axf: $(OBJECT_FILES)
ARMLINK $(MANY_FLAGS) $^ -o $#
VPATH=../a/b/c/module
out/%.o : %.c
$(CC) $(C_FLAGS) $(INCLUDE_PATH) -o $# --depend out/%.d $<
I now get an error that there is no rule for abc.o. abc.c which is present in the directory specified in VPATH under module
*** No rule to make target `out/abc.o', needed by `out/binary.axf'. Stop.

You can use VPATH for this. It can search a list of directories for source files. Assuming you can come up with the list of directories:
VPATH = ../../../src src
CC = ARMCC
out/%.o : %.c
$(CC) -o $# $(CFLAGS) -c $<

Related

Makefile - recompile

My makefile always recompiles everything in directory if one header is changed. It's not a problem now but since I'm adding more to my program this is becoming and issue. I don't want to wait for a whole recompile if I add a new variable to a header of a separate class object.
Here is my makefile:
CXX = g++
CPPFLAGS = -I -lm -lsfml-graphics -lsfml-audio -lsfml-window -lsfml-system
OBJ = CR_Main.o CarRental.o CR_Button.o CR_LoginMenu.o CR_TextBox.o CR_UserCreation.o CR_CheckBox.o
DEPS = CarRental.hpp CR_Button.hpp CR_LoginMenu.hpp CR_TextBox.hpp CR_UserCreation.hpp CR_CheckBox.hpp
%.o: %.cpp $(DEPS)
$(CXX) -c -o $# $< $(CPPFLAGS)
CRC.exe: $(OBJ)
$(CXX) -o $# $^ $(CPPFLAGS)
.PHONY: clean
clean:
del *.o *.exe
Thanks in advance!
EDIT:
I was wondering why is it compiling everything in my directory if only 1 out 6 .hpp files are modified on one line? Is something wrong with my makefile or is that how it is?
why is it compiling everything in my directory if only 1 out 6 .hpp files are modified on one line? Is something wrong with my makefile or is that how it is?
"Wrong" might be too strong a word, but yes, the behavior you describe is a consequence of how your makefile is written.
This rule ...
%.o: %.cpp $(DEPS)
$(CXX) -c -o $# $< $(CPPFLAGS)
... says, roughly, that you can build .o files from corresponding .cpp files plus all the files named in variable DEPS. This implies that if that's the rule make selects for building a given .o file, and any of those prerequisites is newer than the target, then the target is out of date and needs to be rebuilt. You have named all your headers in DEPS and you have not provided any other rules for building .o files, so yes, if any of your headers changes, all of the .o files will be rebuilt.
The most simple-minded alternative would be to write a separate rule for each .o, naming the prerequisites of that file only. That is, the corresponding .cpp file and whichever headers it #includes, directly or indirectly.
But you can save yourself a little typing by instead removing the $(DEPS) part from your existing rule, and adding an additional rule for each .o that does not have a recipe but names all the header prerequisites for that file.
Or if, as it appears, you have consistent relationships between source file names and header names, you might do something like this:
CXX = g++
CPPFLAGS = -I.
LIBS = -lsfml-graphics -lsfml-audio -lsfml-window -lsfml-system -lm
MAIN_OBJ = CR_Main.o
MODULE_OBJS = CarRental.o CR_Button.o CR_LoginMenu.o CR_TextBox.o CR_UserCreation.o CR_CheckBox.o
$(MAIN_OBJ): CR_Main.cpp $(MODULE_OBJS:.o=.h)
$(CXX) $(CPPFLAGS) -c -o $# $<
%.o: %.cpp %.h
$(CXX) $(CPPFLAGS) -c -o $# $<
CRC.exe: $(MAIN_OBJ) $(MODULE_OBJS)
$(CXX) -o $# $^ $(LIBS)
# Extra dependencies (guesses for the sake of example):
CarRental.o CR_LoginMenu.o CR_UserCreation.o: CR_TextBox.h CR_CheckBox.h
# No recipe here
.PHONY: clean
clean:
del $(MAIN_OBJ) $(MODULE_OBJS) CRC.exe
Ultimately, though, what you would really like to do is generate all the header dependencies automatically. That makes the project much easier to maintain once you get it initially set up. You can find lots of information about that on the web, some of it in the GNU make manual.

Rename .o files using Makefile and gcc

I have several lines in Makefile that are compiling and producing .o and .d files. I want two sets of .o .d to be produced, something like:
name.d
name_hello.d
name.o
name_hello.o
Already found how to change names of .d using "$(#:.o=_hello.d)" but have no success changing .o Perhaps i need to play with $# but have no idea how to do it.
Here is Make file code:
$(OBJECT_DIRECTORY)/%.o: %.c
# Build header dependencies
$(CC) $(CFLAGS) $(INCLUDEPATHS) -M $< -MF "$(#:.o=.d)" -MT $#
$(CC) $(CFLAGS) $(INCLUDEPATHS) -M $< -MF "$(#:.o=_hello.d)" -MT $#
# Do the actual compilation
$(CC) $(CFLAGS) $(INCLUDEPATHS) -c -o $# $<
$(CC) $(CFLAGS) $(INCLUDEPATHS) -c -o $# $< - this line i want to change
I use arm-none-eabi-gcc.exe for ARMs and make.exe
Update
Seems that using separate target is preffered solution than changing names. So, i did separate target for it. But it is never used. In other place of the Makefile there is next line of code that tells compiler what .o files to use:
C_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(C_SOURCE_FILENAMES:.c=.o) )
I suppose that i need to change it to something like:
C_OBJECTS_hello = $(addprefix $(OBJECT_DIRECTORY)/, $(C_SOURCE_FILENAMES:.c=*_hello.o) )
Please tell how to modify C_OBJECTS in order to make compiler use *_hello.o files
Update 2
This is how C_OBJECTS used, i suppose some kind of a filter in C_OBJECTS tells CC ( arm-none-eabi-gcc.exe ) to use certain .o files. And since *_hello.o files are not used in the filter they are also not produced in their target.
## Link C and assembler objects to an .out file
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out: $(BUILD_DIRECTORIES) $(C_OBJECTS) $(ASSEMBLER_OBJECTS) $(LIBRARIES)
$(CC) $(LDFLAGS) $(C_OBJECTS) $(ASSEMBLER_OBJECTS) $(LIBRARIES) -o $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
I know that this is written in make help and i am reading it, but still not able to find an answer
Update 3
Here is how i modified 'C_OBJECTS' , and seems this works:
C_OBJECTS_hello = $(addprefix $(OBJECT_DIRECTORY)/, $(C_SOURCE_FILENAMES:.c=_hello.o) )
You indeed would use a replacement. The $# variable expands all the %.o matches. That's why you had a $(#:.o=.d) replacement; you needed a .d file for each %.o match.
In this case, you can indeed use a $(#:.o=_hello.o) replacement. Note that this is NOT a dependency of the %.c input; it is a secondary output.
The alternative is to add a second output $(OBJECT_DIRECTORY)/%.o $(OBJECT_DIRECTORY)/%_hello.o: %.c. In this case, you wouldn't use $# but use $* which is the matched %. So your two dependency files would be $(OBJECT_DIRECTORY)/$*.d and $(OBJECT_DIRECTORY)/$*_hello.d
Your makefile rule produces more files than make is aware of. $(OBJECT_DIRECTORY)/%.o: %.c says it builds one .o from .c, whereas you would like it to build 4 files.
You need to make make aware what files its rules produces, so that it can build a complete dependency graph:
$(OBJECT_DIRECTORY)/%.o $(OBJECT_DIRECTORY)/%.d: %.c # Compile and build dependencies.
$(CC) -c -o $# $(CFLAGS) $(INCLUDEPATHS) -MD -MP $<
$(OBJECT_DIRECTORY)/%_hello.o $(OBJECT_DIRECTORY)/%_hello.d: %.c # Compile and build dependencies.
$(CC) -c -o $# $(CFLAGS) $(INCLUDEPATHS) -MD -MP $<
Note that these rules do not explicitly name the .d output file, letting the compiler determine it by replacing .o with .d.
Now that you have two rules instead of one make can parallelize their execution when -j flag is used.
Note that you should not need explicit rules for auto-generated dependencies for the reasons stated in https://stackoverflow.com/a/7358961/412080.

make 'vpath' directive, why isn't it sufficient for this prerequisite?

The following example makefile works as expected, using vpath to find object files and source files. But in the last line, where i tell make about the dependency of one object file on the other, I need to specify the directory $(objd)/ of the prerequisite file, otherwise i get an error (see error message below the code). How come the vpath directive isn't sufficient in the last line?
# Program Name
prog = avpar
#dirs
objd=obj
modd=mod
# extra places to search for prerequisites
vpath %.f90 ../modules
vpath %.o obj/
# etc
FC = gfortran
flags = -I$(modd) -J$(modd) #-fopenmp
obj_files = $(prog).o rw_mod.o
# compile
p$(prog): $(obj_files)
$(FC) $(flags) $^ -o $#
$(objd)/%.o: %.f90
$(FC) $(flags) -c $< -o $#
$(objd)/$(prog).o: $(objd)/rw_mod.o
That is, changing the last line to:
$(objd)/$(prog).o: rw_mod.o
gives the error:
make: *** No rule to make target 'rw_mod.o', needed by 'obj/avpar.o'. Stop.
EDIT
with this form of the last lines it does also work, without the directory specification:
#compile
p$(prog): $(obj_files)
$(FC) $(flags) $^ -o $#
$(objd)/rw_mod.o: rw_mod.f90
$(FC) $(flags) -c $< -o $#
$(objd)/$(prog).o: $(prog).f90 rw_mod.o
$(FC) $(flags) -c $< -o $#
vpath can only be used to find prerequisites that exist.
Makefiles rule 3
Use VPATH to locate the sources from the objects directory, not to locate the objects from the sources directory.
There's no rule that matches rw_mod.o so the rule for obj/avpar.o fails, vpath won't prepend stuff during prerequisite rule lookup, the only way it would work here would be if obj/rw_mod.o already existed.
It's unlikely that rule is correct anyway, why would one object file depend on another?

Makefile decoupled dependencies

With the following makefile snippet:
main: main.o f1.o f2.o
$(CC) $(CFLAGS) -o program main.o f1.o f2.o
main.o: main.cc
$(CC) $(CFLAGS) -c main.cc
f1.o: f1.cc
$(CC) $(CFLAGS) -c f1.cc
f2.o: f2.cc
$(CC) $(CFLAGS) -c f2.cc
If I just change one file, only that file get recompiled when I rerun make, as desired. However, I'm having a hard time generalizing this without having to list each file individually. When I try something like:
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -o $# -c $(patsubst %.o,%.cc,$#)
It builds each object file individually, but each object file depends on ALL my sources, so a change in any one file causing a full recompile. What's a good way to accomplish this?
Basically,
you do have to list each .o file's dependencies individually.
For example, each .o is likely to depend on a different bunch of headers.
Taking your f1.o, you need something like:
f1.o: include/i.h
f1.o: another.h dir/and-another.h
f1.o: f1.cc
$(CC) $(CFLAGS) -c f1.cc
(you can have as many dependency lines for a target as you like).
Maintaining that list is a nightmare.
Broken dependency lists render your Makefile worse than useless—you might as well use a batch file.
All is not lost!
If you are tidy,
you can get the compiler to do it automatically,
and pretty much for free.
Makes your Makefile tidier to boot.
Win Win.
As Ismail Badawi commented, pattern rules provide a nice solution. They are a type of implicit rule for make. Basically, implicit rules are automatic recipes based off the file extension. For example, make knows how to convert .c files into .o files implicitly. By default make will run the following recipe for .c files (see the rule catalogue):
$(CC) $(CPPFLAGS) $(CFLAGS) -c
You can modify the process either by setting the variables CC, CPPFLAGS, and CFLAGS, or by defining a pattern rule:
%.o: %.c
$(CC) $(CFLAGS) -c $<
The "$<" above matches the name of the first prerequisite, which will be the .c file in this example. See Beta's comment and automatic variables.

Passing target name to a dependency in makefile

If I have the following rule in a makefile:
$(OBJ)/%.o: $(SRC)/%.c
$(CC) -c -o $# $< $(CFLAGS)
Every file matching the prefix ./obj/ and sufix .o will have its stem passed to %, so I can provide some dependencies based on its name.
But, suppose I have this kind of rule, which I specify one by one the targets I want:
OBJECTS=abc.o bca.o cba.o
$(OBJECTS): $(SRC)/%.c
$(CC) -c -o $# $< $(CFLAGS)
How do I make the % stem actually work for the current target name make is executing? Just using % doesn't work, neither $#.
Note that I'm trying to write the actual target name to its own dependency. For example, when make is executing the rule for abc.o, it would include $(SRC)/abc.c and just it (something like $(patsubst %.o, $(SRC)/%.c, MAGIC_TARGET_NAME_VARIABLE)).
You can just replace this rule:
$(OBJECTS): $(SRC)/%.c
with:
$(OBJECTS) : %.o : $(SRC)/%.c
You will need to add the $(OBJ) to the -o part of the recipe if you still want them built there:
$(OBJECTS) : %.o : $(SRC)/%.c
$(CC) -c -o $(OBJ)/$# $< $(CFLAGS)
I’m not completely clear on what you’re asking, but I think this accomplishes what you’re trying to do:
OBJECTS=abc.o bca.o cba.o
.PHONY: all
all: $(OBJECTS:%=obj/%)
$(OBJ)/%.o: $(SRC)/%.c
echo $(CC) -c -o $# $< $(CFLAGS)
All .o files are built; each .o file is built using only the .c file corresponding to it; and if you want to refer to the list of all object files or source files in the command for compiling a .o file, then you can reference ${OBJECTS} directly.
If this isn’t what you’re trying to do, you’ll be able to get a better answer by listing the input files you have, the output files you want to make, the input dependencies of each output file, and what compilation command you want to execute for each output file.

Resources