在这个部分Makefile中,当我执行make而没有参数且.PHONY被禁用时,它返回:
make:'debug'没什么可做的。
启用.PHONY(或make -r)它会转到'build'而不创建任何目标文件,因此GCC不能打开任何目标文件,因为目标中没有目标文件目录呢。
arm-none-eabi-gcc:错误: obj / debug / ThirdParty / STM32F1xx_HAL_Driver / Src / stm32f1xx_hal_adc.o:No 这样的文件或目录
此makefile将objs分隔为文件夹obj / debug或obj / release。
文件结构:
bin
inc
Src
ThirdParty // thirdparty source files
obj // mkdir -p should create this directories tree
debug
Src
ThirdParty
release
...
生成文件
.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)/$@
$(COBJ)的一个示例:
OBJ /调试/第三方/ FreeRTOS的/ queue.o
Linux x86-64
GNU Make 4.2.1
Arm-none-eabi-gcc - 我认为这没关系
答案 0 :(得分:2)
您遗漏了the GNU make manual关于特定目标变量的重要提示:
与自动变量一样,这些值仅在目标配方的上下文中可用(以及在其他特定于目标的分配中)。
所以,在你的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)
...
此时$(COBJ)
和$(SOBJ)
引用COBJ
和SOBJ
变量的全局设置值(因为如上所述,特定于目标的值仅在配方中可用,而不在先决条件列表中。这些变量没有全局值,因此它们扩展为空字符串,而makefile基本上只有:
build:
...
没有任何先决条件,这就是为什么你会看到你的行为。
有多种方法可以解决这个问题。一种是使用递归make:删除release: build
和debug: build
行并添加:
debug release:
@$(MAKE) COBJ='$(COBJ)' SOBJ='$(SOBJ)' build
另一种方法是使用secondary expansion(你不能按照我最初建议的方式去做,但你可以使用构造的变量名来做到这一点:
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)
这使用输出对象名称中的目标名称。
另一种方法是使用生成的makefile。
您可以考虑阅读以下系列帖子:http://make.mad-scientist.net/category/metaprogramming/(从最早的帖子开始)。
答案 1 :(得分:0)
正如 MadScientist 所提到的,特定于目标的变量的范围有限,我将makefile作为一个选择器并使用TARGET ='target'参数运行make,如下所示:
make TARGET = debug
make TARGET = release
没有优雅但功能齐全!
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