Reputation:
In this partial Makefile when I execute make with no argument and .PHONY disabled it returns:
make: Nothing to be done for 'debug'.
With .PHONY enabled (or make -r) it go to 'build' without make any object file, so GCC don't can open any object file because there is no object files in target directories yet.
arm-none-eabi-gcc: error: obj/debug/ThirdParty/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.o: No such file or directory
This makefile separate objs into folders obj/debug or obj/release.
File structure:
bin
inc
Src
ThirdParty // thirdparty source files
obj // mkdir -p should create this directories tree
debug
Src
ThirdParty
release
...
Makefile
.PHONY: build debug release clean $(COBJ) $(SOBJ)
# Main target
debug: CC_FLAGS += $(DEBUG)
debug: ELF = debug.elf
debug: OBJPATH = obj/debug
debug: COBJ = $(patsubst ./%,$(OBJPATH)/%,$(C:.c=.o)) # C contains c code
debug: SOBJ = $(patsubst ./%,$(OBJPATH)/%,$(S:.s=.o)) # S contains asm code
debug: build
release: CC_FLAGS += $(RELEASE)
release: OBJPATH = obj/release
release: COBJ = $(patsubst ./%,$(OBJPATH)/%,$(C:.c=.o))
release: SOBJ = $(patsubst ./%,$(OBJPATH)/%,$(S:.s=.o))
release: ELF = release.elf
release: build
build: $(COBJ) $(SOBJ)
$(CC) $(COBJ) $(SOBJ) $(LIBS) $(LD_FLAGS) -o bin/$(ELF)
%.o: %.c
echo $@
@mkdir -p $(OBJPATH)/$(dir $@)
$(CC) $(CC_FLAGS) -c $< -o $(OBJPATH)/$@
%.o: %.s
@mkdi -p $(OBJPATH)/$(dir $@)
$(CC) $(CC_FLAGS) -c $< -o $(OBJPATH)/$@
One sample of $(COBJ):
obj/debug/ThirdParty/FreeRTOS/queue.o
Linux x86-64
GNU Make 4.2.1
Arm-none-eabi-gcc - I think this don't matter
Upvotes: 0
Views: 702
Reputation:
As MadScientist mentioned the limited scope of target-specific variables I put out of makefile a selector and run make with TARGET = 'target' argument like this:
make TARGET = debug
make TARGET = release
No elegant but functional!
Makefile:
O = $(C:%.c=%.o)
O += $(S:%.s=%.o)
ifeq ($(TARGET), release)
ELF = bin/release.elf
CC_FLAGS += -O3
OBJPATH = obj/release
else
ELF = bin/debug.elf
CC_FLAGS += -g3
OBJPATH = obj/debug
endif
OBJ = $(addprefix $(OBJPATH)/, $(O))
all: makepath build
build: $(OBJ)
@echo ---- LINKING ----
$(CC) $(OBJ) $(LIBS) $(LD_FLAGS) -o $(ELF)
makepath:
@mkdir -p $(dir $(OBJ))
$(OBJPATH)/%.o:%.c
@echo ---- C ----
$(CC) $(CC_FLAGS) -c $< -o $@
$(OBJPATH)/%.o:%.s
@echo ---- S ----
$(CC) $(CC_FLAGS) -c $< -o $@
clean:
find -name *.o -delete
find -name *.elf -delete
Upvotes: 0
Reputation: 101081
You are missing a critical note from the GNU make manual regarding target-specific variables:
As with automatic variables, these values are only available within the context of a target’s recipe (and in other target-specific assignments).
So, in your makefile:
debug: COBJ = $(patsubst ./%,$(OBJPATH)/%,$(C:.c=.o)) # C contains c code
debug: SOBJ = $(patsubst ./%,$(OBJPATH)/%,$(S:.s=.o)) # S contains asm code
build: $(COBJ) $(SOBJ)
...
At this point $(COBJ)
and $(SOBJ)
refer to the globally-set values of the COBJ
and SOBJ
variables (because as above, target-specific values are available only within the recipe, NOT in the prerequisites list). These variables have no global values, so they expand to the empty string, and your makefile essentially has just:
build:
...
with no prerequisites, which is why you're seeing the behavior you are.
There are multiple ways you could manage this. One is to use recursive make: remove the release: build
and debug: build
lines and add this:
debug release:
@$(MAKE) COBJ='$(COBJ)' SOBJ='$(SOBJ)' build
Another way is to use secondary expansion (you can't do it the way I originally suggested but you can do it with constructed variable names:
OBJPREFIX := obj
COBJ = $(patsubst ./%,$(OBJPREFIX)/$@/%,$(C:.c=.o))
SOBJ = $(patsubst ./%,$(OBJPREFIX)/$@/%,$(S:.s=.o))
# Main target
debug: CC_FLAGS += $(DEBUG)
debug: ELF = debug.elf
release: CC_FLAGS += $(RELEASE)
release: ELF = release.elf
.SECONDEXPANSION:
release debug: $$(COBJ) $$(SOBJ)
$(CC) $(COBJ) $(SOBJ) $(LIBS) $(LD_FLAGS) -o bin/$(ELF)
This uses the name of the target in the output object name.
Another way is to use generated makefiles.
You might consider reading the series of posts here: http://make.mad-scientist.net/category/metaprogramming/ (starting with the oldest one first).
Upvotes: 2