I'm trying to improve the naive solution (single rules for compiling targets and additional one for linking all the previous targets together) which I used im my makefile. I came up with the following Makefile (clipped):
.PHONY: clean
BASE_DIR = ../
CC = gcc
CROSS_COMPILE = arm-none-eabi-
CFLAGS =-g -I${BASE_DIR}/include
LDFLAGS =-L${BASE_DIR}/lib -Ttarget.ld -nostdlib
SOURCES = first.c second.c third.c fourth.c
OBJECTS = $(SOURCES:.c=.o)
EXECUTABLE = $(OBJECTS:.o=)
all: $(EXECUTABLE)
%:
${CROSS_COMPILE}$(CC) $(CFLAGS) $(LDFLAGS) $*.c -o $*
clean:
rm ${EXECUTABLE}
This works fine but I'd like to separate the compilation and linking processes. Therefore I tried to modify it as follows:
.PHONY: clean
BASE_DIR = ../
CC = gcc
CROSS_COMPILE = arm-none-eabi-
CFLAGS =-c -g -I${BASE_DIR}/include
LDFLAGS =-L${BASE_DIR}/lib -Ttarget.ld -nostdlib
SOURCES = first.c second.c third.c fourth.c
OBJECTS = $(SOURCES:.c=.o)
EXECUTABLE = $(OBJECTS:.o=)
all : $(EXECUTABLE)
%.o : %.c
@echo "Compiling c file into o file"
${CROSS_COMPILE}$(CC) $(CFLAGS) $< -o $@
% : %.o
@echo "Linking o file into executable"
${CROSS_COMPILE}$(CC) $(LDFLAGS) $< -o $@
clean:
rm ${EXECUTABLE}
This works ok then I invoke the Makefile as e.g. make first.o; make first
or if I modify the EXECUTABLE = $(OBJECTS:.o=)
to EXECUTABLE = $(OBJECTS:.o=.out)
and % : %.o
to %.out : %.o
. If, however, I try to invoke compilation as make
or make first
the implicit rules are used.
I tried going through the Makefile manual but there is really a lot of information in there, I got a little confused.
How can I modify the Makefile to be allowed to invoke building separate targets as make <target>
or all the targets as make
as the same time?
A rule appears in the makefile and says when and how to remake certain files, called the rule's targets (most often only one per rule). It lists the other files that are the prerequisites of the target, and the recipe to use to create or update the target.
The file name of the target of the rule. If the target is an archive member, then ' $@ ' is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), ' $@ ' is the name of whichever target caused the rule's recipe to be run.
Multiple Targets in a RuleA rule with multiple targets is equivalent to writing many rules, each with one target, and all identical aside from that. The same commands apply to all the targets, but their effects may vary because you can substitute the actual target name into the command using `$@' .
The paragraph where you describe your problem is very confusing and hard to understand. When asking questions please be sure that the section describing the problem is the most clear: it's helpful if you provide sample output showing exactly what commands you typed and the results you got, and explain what you expected to get instead.
However, my interpretation is that if you run make first
it uses the built-in rule to compile first
directly from first.c
, rather than your pattern rules (note that both the built-in rules and your pattern rules are considered "implicit rules").
That's because make will choose the "shorter" implicit rule chain so the rule building an executable directly from source, in one step, rather than building the object then the executable in two steps, will be preferred. If you don't want to use the built-in implicit rule then you need to either invoke make with the -r
flag, or else delete it by adding:
% : %.c
(just that) to your makefile.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With