GNU Makefile Questions - makefile

I'm trying to figure out some differences in makefiles and what some of the code does. Below are some of the different items that I'm trying to address.
CC vs $(CC)
CP vs $(CP)
LD vs $(LD)
-Wl
This line of code. Is it setting a target of .o files to .c files in the first line? I understand the second line sets flags for compiling, but I don't quite understand the notation at -c $< -o *.o. -c is a flag to generate the object file, $< is the name of the prerequisite(don't really understand this), and -o I'm not certain of.
$(libSup)/%.o : %.c
$(MINGW_CC) $(ADDED_CFLAGS) $(EXTRA_INCLUDE) -c $< -o $(libSup)/$*.o

Related

Create object files in one folder from different source folders

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

What is the syntax for copying in makefile [duplicate]

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 $#
What do the $# and $< do exactly?
$# is the name of the target being generated, and $< the first prerequisite (usually a source file). You can find a list of all these special variables in the GNU Make manual.
For example, consider the following declaration:
all: library.cpp main.cpp
In this case:
$# evaluates to all
$< evaluates to library.cpp
$^ evaluates to library.cpp main.cpp
From Managing Projects with GNU Make, 3rd Edition, p. 16 (it's under GNU Free Documentation License):
Automatic variables are set by make after a rule is matched. They
provide access to elements from the target and prerequisite lists so
you don’t have to explicitly specify any filenames. They are very
useful for avoiding code duplication, but are critical when defining
more general pattern rules.
There are seven “core” automatic variables:
$#: The filename representing the target.
$%: The filename element of an archive member specification.
$<: The filename of the first prerequisite.
$?: The names of all prerequisites that are newer than the target,
separated by spaces.
$^: The filenames of all the prerequisites, separated by spaces. This
list has duplicate filenames removed since for most uses, such as
compiling, copying, etc., duplicates are not wanted.
$+: Similar to $^, this is the names of all the prerequisites separated
by spaces, except that $+ includes duplicates. This variable was
created for specific situations such as arguments to linkers where
duplicate values have meaning.
$*: The stem of the target filename. A stem is typically a filename
without its suffix. Its use outside of pattern rules is
discouraged.
In addition, each of the above variables has two variants for
compatibility with other makes. One variant returns only the directory
portion of the value. This is indicated by appending a “D” to the
symbol, $(#D), $(<D), etc. The other variant returns only the file
portion of the value. This is indicated by appending an “F” to the
symbol, $(#F), $(<F), etc. Note that these variant names are more than
one character long and so must be enclosed in parentheses. GNU make
provides a more readable alternative with the dir and notdir
functions.
The $# and $< are called automatic variables. The variable $# represents the name of the target and $< represents the first prerequisite required to create the output file.
For example:
hello.o: hello.c hello.h
gcc -c $< -o $#
Here, hello.o is the output file. This is what $# expands to. The first dependency is hello.c. That's what $< expands to.
The -c flag generates the .o file; see man gcc for a more detailed explanation. The -o specifies the output file to create.
For further details, you can read this article on linoxide about Linux Makefiles.
Also, you can check the GNU make manuals. It will make it easier to make Makefiles and to debug them.
If you run this command, it will output the makefile database:
make -p
The $# and $< are special macros.
Where:
$# is the file name of the target.
$< is the name of the first dependency.
The Makefile builds the hello executable if any one of main.cpp, hello.cpp, factorial.cpp changed. The smallest possible Makefile to achieve that specification could have been:
hello: main.cpp hello.cpp factorial.cpp
g++ -o hello main.cpp hello.cpp factorial.cpp
pro: very easy to read
con: maintenance nightmare, duplication of the C++ dependencies
con: efficiency problem, we recompile all C++ even if only one was changed
To improve on the above, we only compile those C++ files that were edited. Then, we just link the resultant object files together.
OBJECTS=main.o hello.o factorial.o
hello: $(OBJECTS)
g++ -o hello $(OBJECTS)
main.o: main.cpp
g++ -c main.cpp
hello.o: hello.cpp
g++ -c hello.cpp
factorial.o: factorial.cpp
g++ -c factorial.cpp
pro: fixes efficiency issue
con: new maintenance nightmare, potential typo on object files rules
To improve on this, we can replace all object file rules with a single .cpp.o rule:
OBJECTS=main.o hello.o factorial.o
hello: $(OBJECTS)
g++ -o hello $(OBJECTS)
.cpp.o:
g++ -c $< -o $#
pro: back to having a short makefile, somewhat easy to read
Here the .cpp.o rule defines how to build anyfile.o from anyfile.cpp.
$< matches to first dependency, in this case, anyfile.cpp
$# matches the target, in this case, anyfile.o.
The other changes present in the Makefile are:
Making it easier to changes compilers from g++ to any C++ compiler.
Making it easier to change the compiler options.
Making it easier to change the linker options.
Making it easier to change the C++ source files and output.
Added a default rule 'all' which acts as a quick check to ensure all your source files are present before an attempt to build your application is made.
in exemple if you want to compile sources but have objects in an different directory :
You need to do :
gcc -c -o <obj/1.o> <srcs/1.c> <obj/2.o> <srcs/2.c> ...
but with most of macros the result will be all objects followed by all sources, like :
gcc -c -o <all OBJ path> <all SRC path>
so this will not compile anything ^^ and you will not be able to put your objects files in a different dir :(
the solution is to use these special macros
$# $<
this will generate a .o file (obj/file.o) for each .c file in SRC (src/file.c)
$(OBJ):$(SRC)
gcc -c -o $# $< $(HEADERS) $(FLAGS)
it means :
$# = $(OBJ)
$< = $(SRC)
but lines by lines INSTEAD of all lines of OBJ followed by all lines of SRC

How can I have a step in a makefile to generate preprocess files and compile from those files?

I took a makefile from a previous project that compiles programs for an avr microcontroller. I ran into some problems with what IO ports/data directional addresses I was setting which was causing the microcontroller to fault and reset. Because of this I wanted to add a step in my makefile to have it generate the pre-proccessed files and then compile from these preprocessed files. I'm not too familiar with how rules/dependencies work in makefiles so I've made, what I believe is, a simple mistake in my understanding of how makefiles work. My rules to make the preprocessed files/object files and eventually the .elf file must be wrong. Up until I added the steps which attempted to create the preprocessed files creating the .elf file work fine. What is my simple mistake/understanding in how rules/dependencies work in make?
How I view this working is when I ask to make all it sees that it has a dependency of led.elf. To create this it has the dependency of the preprocessed files based on the line of $(OUTPUT).elf: $(PROCESS_FILES) so it starts with this line. When I try to make all however I get the error make: *** No rule to make target 'main.c', needed by 'main.e'. Stop. and I don't understand why. Can anyone help my understanding in make files?
SRC_FILES=\
main.c led.c comm.c
#Object files
PROCESS_FILES=$(SRC_FILES:.c=.e)
OBJ_FILES=$(PROCESS_FILES:.e=.o)
#Directories where to look for include files
INC_DIRS=\
-I. \
#Output file name
OUTPUT=led
#Programmer and port
PROG=dragon_isp
PORT=usb
#Debugging host and port
DHOST=localhost
DPORT=6423
#Compiler related params
MCU=atmega2560
CC=avr-gcc
OBJCOPY=avr-objcopy
CFLAGS= -mcall-prologues -std=gnu99 -funsigned-char -funsigned bitfields \
-fpack-struct -fshort-enums -mmcu=$(MCU) -Wall -Wstrict-prototypes \
$(INC_DIRS)
#Optimization level
CFLAGS+=-Os
#Debug info
CFLAGS+=-gdwarf-2
#Generate hex file ready to upload
all: $(OUTPUT).elf
$(OBJCOPY) -R .eeprom -O ihex $(OUTPUT).elf $(OUTPUT).hex
#Link output files
$(OUTPUT).elf: $(PROCESS_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $(OUTPUT).elf -Wl,-Map,$(OUTPUT).map
#Create object files
$(PROCESS_FILES): %.e : %.c
$(CC) -E $(CFLAGS) $< -o $#
$(OBJ_FILES): %.o : %.e
$(CC) -x $(CFLAGS) $< -o $#
#Create assembler file of a C source
%.s: %.c
$(CC) -S $(CFLAGS) $< -o $#
#Cleans all generated files
clean:
rm -f $(OBJ_FILES)
rm -f $(OUTPUT).elf
rm -f $(OUTPUT).hex
rm -f $(OUTPUT).map
Edit: I'm away from my computer now so I can't check this but thinking about my issue I'm starting to think I don't have a file named main.c in that directory. Even if I did I still think the makefile would not work correctly because I don't fully understand rules in makefiles.
My error was coming from the fact that I did not have a main.c file in my directory. Make sure you backup files when you're messing with the OBJ_FILES or similar variable and have a line that will delete whatever is in that variable upon a make clean.
As for the rules, I had to make one small fix to achieve what I wanted. I changed
$(OUTPUT).elf: $(PROCESS_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $(OUTPUT).elf -Wl,-Map,$(OUTPUT).map
to
$(OUTPUT).elf: $(OBJ_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $(OUTPUT).elf -Wl,-Map,$(OUTPUT).map
This then sees it needs the object files which in turn needs the preprocessed files.
Edit: I also changed OBJ_FILES=$(PROCESS_FILES:.e=.o) to OBJ_FILES=$(SRC_FILES:.c=.o). I also added $(PROCESS_FILES) to $(OUTPUT).elf: $(OBJ_FILES) so the rule would generate both the preprocessed files and object files independently. I had to change $(OBJ_FILES): %.o : %.e to $(OBJ_FILES): %.o : %.c to make this work.

Makefile include file for same targets

I have a large project using recursive Make. Almost all the Makefiles are the same though. I'm basically building all the object files into the same directory like this:
$(OBJ)/%.o: %.c
$(COMPILE) ${INCLUDES} -c $< -o $#
$(OBJ)/%.o: %.cpp
${CXX} ${INCLUDES} ${FLAGS} -c -fPIC $< -o $#
Is it possible to put these targets in an include file so I don't have to put the same lines in every Makefile?
include I've only used for shared variables and when I tested this using include it did not work.

What do the makefile symbols $# and $< mean?

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 $#
What do the $# and $< do exactly?
$# is the name of the target being generated, and $< the first prerequisite (usually a source file). You can find a list of all these special variables in the GNU Make manual.
For example, consider the following declaration:
all: library.cpp main.cpp
In this case:
$# evaluates to all
$< evaluates to library.cpp
$^ evaluates to library.cpp main.cpp
From Managing Projects with GNU Make, 3rd Edition, p. 16 (it's under GNU Free Documentation License):
Automatic variables are set by make after a rule is matched. They
provide access to elements from the target and prerequisite lists so
you don’t have to explicitly specify any filenames. They are very
useful for avoiding code duplication, but are critical when defining
more general pattern rules.
There are seven “core” automatic variables:
$#: The filename representing the target.
$%: The filename element of an archive member specification.
$<: The filename of the first prerequisite.
$?: The names of all prerequisites that are newer than the target,
separated by spaces.
$^: The filenames of all the prerequisites, separated by spaces. This
list has duplicate filenames removed since for most uses, such as
compiling, copying, etc., duplicates are not wanted.
$+: Similar to $^, this is the names of all the prerequisites separated
by spaces, except that $+ includes duplicates. This variable was
created for specific situations such as arguments to linkers where
duplicate values have meaning.
$*: The stem of the target filename. A stem is typically a filename
without its suffix. Its use outside of pattern rules is
discouraged.
In addition, each of the above variables has two variants for
compatibility with other makes. One variant returns only the directory
portion of the value. This is indicated by appending a “D” to the
symbol, $(#D), $(<D), etc. The other variant returns only the file
portion of the value. This is indicated by appending an “F” to the
symbol, $(#F), $(<F), etc. Note that these variant names are more than
one character long and so must be enclosed in parentheses. GNU make
provides a more readable alternative with the dir and notdir
functions.
The $# and $< are called automatic variables. The variable $# represents the name of the target and $< represents the first prerequisite required to create the output file.
For example:
hello.o: hello.c hello.h
gcc -c $< -o $#
Here, hello.o is the output file. This is what $# expands to. The first dependency is hello.c. That's what $< expands to.
The -c flag generates the .o file; see man gcc for a more detailed explanation. The -o specifies the output file to create.
For further details, you can read this article on linoxide about Linux Makefiles.
Also, you can check the GNU make manuals. It will make it easier to make Makefiles and to debug them.
If you run this command, it will output the makefile database:
make -p
The $# and $< are special macros.
Where:
$# is the file name of the target.
$< is the name of the first dependency.
The Makefile builds the hello executable if any one of main.cpp, hello.cpp, factorial.cpp changed. The smallest possible Makefile to achieve that specification could have been:
hello: main.cpp hello.cpp factorial.cpp
g++ -o hello main.cpp hello.cpp factorial.cpp
pro: very easy to read
con: maintenance nightmare, duplication of the C++ dependencies
con: efficiency problem, we recompile all C++ even if only one was changed
To improve on the above, we only compile those C++ files that were edited. Then, we just link the resultant object files together.
OBJECTS=main.o hello.o factorial.o
hello: $(OBJECTS)
g++ -o hello $(OBJECTS)
main.o: main.cpp
g++ -c main.cpp
hello.o: hello.cpp
g++ -c hello.cpp
factorial.o: factorial.cpp
g++ -c factorial.cpp
pro: fixes efficiency issue
con: new maintenance nightmare, potential typo on object files rules
To improve on this, we can replace all object file rules with a single .cpp.o rule:
OBJECTS=main.o hello.o factorial.o
hello: $(OBJECTS)
g++ -o hello $(OBJECTS)
.cpp.o:
g++ -c $< -o $#
pro: back to having a short makefile, somewhat easy to read
Here the .cpp.o rule defines how to build anyfile.o from anyfile.cpp.
$< matches to first dependency, in this case, anyfile.cpp
$# matches the target, in this case, anyfile.o.
The other changes present in the Makefile are:
Making it easier to changes compilers from g++ to any C++ compiler.
Making it easier to change the compiler options.
Making it easier to change the linker options.
Making it easier to change the C++ source files and output.
Added a default rule 'all' which acts as a quick check to ensure all your source files are present before an attempt to build your application is made.
in exemple if you want to compile sources but have objects in an different directory :
You need to do :
gcc -c -o <obj/1.o> <srcs/1.c> <obj/2.o> <srcs/2.c> ...
but with most of macros the result will be all objects followed by all sources, like :
gcc -c -o <all OBJ path> <all SRC path>
so this will not compile anything ^^ and you will not be able to put your objects files in a different dir :(
the solution is to use these special macros
$# $<
this will generate a .o file (obj/file.o) for each .c file in SRC (src/file.c)
$(OBJ):$(SRC)
gcc -c -o $# $< $(HEADERS) $(FLAGS)
it means :
$# = $(OBJ)
$< = $(SRC)
but lines by lines INSTEAD of all lines of OBJ followed by all lines of SRC

Resources