In my makefile, I have the following sources
src/commonModule.c src/freeRtos/freeRtosIntegration.c
which shall result in objectfiles like this
build/commonModule.o build/freeRtos/freeRtosIntegration.o
The folders build/ and build/freeRtos/ are created correctly.
Before linking, I am calling build
which is supposed to result in the commands
gcc -g -x c -c src/freeRtos/freeRtosIntegration.c -o build/freeRtos/freeRtosIntegration.o
gcc -g -x c -c src/freeRtos/freeRtosIntegration.c -o build/freeRtos/freeRtosIntegration.o
.PHONY: build
SRC_PREFIX = src
BUILD_PREFIX = build
SRCDIRS = ${SRC_PREFIX} ${SRC_PREFIX}/freeRtos
SEARCHC = $(addsuffix /*.c ,$(SRCDIRS))
SOURCEFILES := $(wildcard ${SEARCHC})
OBJECTFILES := $(patsubst %.c,%.o,$(SOURCEFILES))
OBJECTFILES := $(subst ${SRC_PREFIX},${BUILD_PREFIX},$(OBJECTFILES))
MP_CC = gcc
CFLAGS = -g -x c -c
build: ${OBJECTFILES}
${OBJECTFILES}: %.o: $(subst ${BUILD_PREFIX},${SRC_PREFIX},$@)
${MP_CC} ${CFLAGS} $< -o $@
This generates the output
gcc -g -x c -c -o build/commonModule.o
gcc -g -x c -c -o build/freeRtos/freeRtosIntegration.o
What do I need to change in my subst command to receive the expected result?
This works, but it recompiles every time when calling make
.PHONY: build
.PHONY: echoFiles
SRC_PREFIX = src
BUILD_PREFIX = buildTest
SRCDIRS = ${SRC_PREFIX} ${SRC_PREFIX}/freeRtos
SEARCHC = $(addsuffix /*.c ,$(SRCDIRS))
SOURCEFILES := $(wildcard ${SEARCHC})
OBJECTFILES := $(patsubst %.c,%.o,$(SOURCEFILES))
MP_CC = gcc
CFLAGS = -g -x c -c
echoFiles:
@echo ${SOURCEFILES}
@echo ${OBJECTFILES}
build: ${OBJECTFILES}
${OBJECTFILES}: %.o: %.c
${MP_CC} ${CFLAGS} $< -o ${BUILD_PREFIX}$(subst ${SRC_PREFIX},,$@)
Your problem comes from the fact that make expands the prerequisites of rules when it parses the Makefile, but at that time the $@
automatic variable expands as the empty string because it has not been assigned yet; it is defined at a later stage.
Unless you use GNU make's secondary expansion you cannot use automatic variables in prerequisites, only in recipes.
Your second attempt is also wrong because you are lying to make: you tell it that the recipe builds src/foo.o
while it builds build/foo.o
. As a consequence make never finds the object files and always decides that they must be rebuilt. Never lie to make.
Anyway, there is no need for complex text string manipulations or automatic variables in prerequisites, static pattern rules can perfectly handle your case. You can try:
.PHONY: build
SRC_PREFIX := src
BUILD_PREFIX := build
SOURCEFILES := $(wildcard $(SRC_PREFIX)/*.c $(SRC_PREFIX)/freeRtos/*.c)
OBJECTFILES := $(patsubst $(SRC_PREFIX)/%.c,$(BUILD_PREFIX)/%.o,$(SOURCEFILES))
CC := gcc
CFLAGS := -g -x c
build: ${OBJECTFILES}
${OBJECTFILES}: $(BUILD_PREFIX)/%.o: $(SRC_PREFIX)/%.c
$(CC) $(CFLAGS) -c $< -o $@
Note the use of patsubst
to do the whole substitution at once. Your use of subst
was also wrong because it substitutes all occurrences, not just the first. If one of your source files is src/foosrcbar.c
, your patsubst
+ subst
combination transforms it to build/foobuildbar.o
.