Is default goal is first rule in makefile - makefile

I have simple makefile:
CC=gcc
CFLAGS=-I.
DEPS = hellomake.h
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
hellomake: hellomake.o hellofunc.o
gcc -o hellomake hellomake.o hellofunc.o -I.
According to makefile description "first rule in makefile is default goal". According to my understanding the first rule is:
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
But I suppose this is not "default goal" since goal is to create hellomake executable? Where is my mistake?

According to the gnu make manual, By default, make starts with the first target (not targets whose names start with ‘.’).
%.o : ... does not count as an actual target, but rather is a pattern, which is resolved to actual goals when needed.

Related

How to write a general pattern in makefile

I have multiple programs which share the same structure of compilation.
test_variance : test_variance.o
$(CPP) -o test_variance.exe $(CFLAGS) test_variance.o $(LIBDIR) $(LIBS)
test_variance_incremental: test_variance_incremental.o
$(CPP) -o test_variance_incremental.exe $(CFLAGS) test_variance_incremental.o $(LIBDIR) $(LIBS)
test_hyper: test_hyper.o
$(CPP) -o test_hyper.exe $(CFLAGS) test_hyper.o $(LIBDIR) $(LIBS)
test_hyper.o: test_hyper.cpp
$(CPP) $(CFLAGS) $(INCLUDES) -c test_hyper.cpp
test_variance_incremental.o: test_variance_incremental.cpp
$(CPP) $(CFLAGS) $(INCLUDES) -c test_variance_incremental.cpp
test_variance.o : test_variance.cpp
$(CPP) $(CFLAGS) $(INCLUDES) -c test_variance.cpp
So for compling .o, I can use the pattern
%.o: %.cpp
$(CPP) $(CFLAGS) $(INCLUDES) -c $<
I wonder if there is a general pattern for compling the executive. I've tried
TARGETS = test_variance test_variance_incremental test_hyper
$(TARGETS): $#.o
$(CPP) -o $#.exe $^ $(CFLAGS) $(LIBDIR) $(LIBS)
But Make tells me there is no input files and I think my usage of $# is wrong. Any advice?
You should use CC and CFLAGS for compiling C code, and CXX and CXXFLAGS for compiling C++ code. CPP (in make) is used for running the C preprocessor (only). The standard variable to hold libraries is LDLIBS.
If you use these variables then you don't even need to define your own rules at all: there are built-in rules in make that already know how to compile and link C++ programs. All you need is this:
TARGETS = test_variance test_variance_incremental test_hyper
all: $(TARGETS)
Anyway, if you want to write it explicitly you can write:
TARGETS = test_variance test_variance_incremental test_hyper
all: $(TARGETS)
% : %.o
$(CXX) -o $# $^ $(CXXFLAGS) $(LDFLAGS) $(LDLIBS)
(you should definitely not name the target test_variance, but then have your link line build test_variance.exe: the target name and the file that the recipe builds must always be the same).

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

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.

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.

Simple Makefile not taking include path

following is my makefile. but It is not taking include path during build.
SHELL = /bin/sh
CC = g++
FLAGS =
CFLAGS = -fPIC
TARGET = my_bridge.so
INC=-I/my_custom_path/include/ -I/my_custom_path/include/linux
SOURCES = $(shell echo *.cpp)
HEADERS = $(shell echo *.h)
OBJECTS = $(SOURCES:.cpp=.o)
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(FLAGS) $(INC) $(CFLAGS) -o $(TARGET) $(OBJECTS)
When I build i get following line
g++ -c -o my_bridge.o my_bridge.cpp
Your $(TARGET): $(OBJECTS) rule tells make how to generate my_bridge.so out of my_bridge.o, but you haven't given a rule that explains how to make my_bridge.o in the first place. make relies thus on its implicit rules for that, which gives you the command that you see. You can either define your own rule to compile .cpp files, e.g.
%.o: %.cpp
$(CC) $(FLAGS) $(INC) $(CFLAGS) -o $# $<
or put your include directive in $(CXXFLAGS), which is used by make's default rule (see https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html#Catalogue-of-Rules)

Resources