C Make忽略隐式规则依赖关系

C Make忽略隐式规则依赖关系,c,makefile,gnu-make,C,Makefile,Gnu Make,在这个部分生成文件中,当我在没有参数的情况下执行make并禁用.PHONY时,它返回: make:对于“调试”不做任何操作 启用.PHONY(或make-r)后,它将转到“build”,而不生成任何对象文件,因此GCC无法打开任何对象文件,因为目标目录中还没有对象文件 arm none eabi gcc:错误: obj/debug/ThirdParty/stm32f1x\u HAL\u Driver/Src/stm32f1x\u HAL\u adc.o:否 这样的文件或目录 此makefile将

在这个部分生成文件中,当我在没有参数的情况下执行make并禁用.PHONY时,它返回:

make:对于“调试”不做任何操作

启用.PHONY(或make-r)后,它将转到“build”,而不生成任何对象文件,因此GCC无法打开任何对象文件,因为目标目录中还没有对象文件

arm none eabi gcc:错误: obj/debug/ThirdParty/stm32f1x\u HAL\u Driver/Src/stm32f1x\u HAL\u adc.o:否 这样的文件或目录

此makefile将obj分离到文件夹obj/debug或obj/release中

文件结构:

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)/$@
.PHONY:build-debug-release-clean$(COBJ)$(SOBJ)
#主要目标
调试:CC_标志+=$(调试)
调试:ELF=debug.ELF
调试:OBJPATH=obj/debug
调试:COBJ=$(patsubst./%,$(OBJPATH)/%,$(C:.C=.o))#C包含C代码
调试:SOBJ=$(patsubst./%,$(OBJPATH)/%,$(S:.S=.o))#S包含asm代码
调试:构建
发布:CC_标志+=$(发布)
发布:OBJPATH=obj/release
发布:COBJ=$(patsubst./%,$(OBJPATH)/%,$(C:.C=.o))
发布:SOBJ=$(patsubst./%,$(OBJPATH)/%,$(S:.S=.o))
release:ELF=release.ELF
发布:构建
构建:$(COBJ)$(SOBJ)
$(CC)$(COBJ)$(SOBJ)$(LIBS)$(LD_标志)-o bin/$(ELF)
%.o:%.c
回音$@
@mkdir-p$(OBJPATH)/$(dir$@)
$(CC)$(CC_标志)-c$<-o$(OBJPATH)/$@
%.o:%.s
@mkdi-p$(OBJPATH)/$(dir$@)
$(CC)$(CC_标志)-c$<-o$(OBJPATH)/$@
$(COBJ)的一个样本:

obj/debug/ThirdParty/FreeRTOS/queue.o

Linux x86-64

GNU Make 4.2.1


Arm none eabi gcc-我认为这无关紧要

关于特定于目标的变量,您缺少了一个关键注意事项:

与自动变量一样,这些值仅在目标配方的上下文中可用(以及在其他特定于目标的分配中)

因此,在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:
        ...
没有先决条件,这就是为什么你会看到自己的行为

您可以通过多种方式来管理它。一种是使用递归生成:删除
release:build
debug:build
行,并添加以下内容:

debug release:
        @$(MAKE) COBJ='$(COBJ)' SOBJ='$(SOBJ)' build
另一种方法是使用(您不能按照我最初建议的方式执行,但可以使用构造的变量名执行:

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


你可以考虑在这里阅读一系列文章:(先从最老的一个开始)。

你忽略了关于目标特定变量的一个批注:

与自动变量一样,这些值仅在目标配方的上下文中可用(以及在其他特定于目标的分配中)

因此,在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:
        ...
没有先决条件,这就是为什么你会看到自己的行为

有多种方法可以管理此问题。一种是使用递归生成:删除
release:build
debug:build
行,然后添加以下内容:

debug release:
        @$(MAKE) COBJ='$(COBJ)' SOBJ='$(SOBJ)' build
另一种方法是使用(您不能按照我最初建议的方式执行,但可以使用构造的变量名执行:

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


你可以考虑在这里阅读一系列文章:(首先从最老的一个开始)。<> > <强>疯狂科学家提到了目标特定变量的有限范围,我从MaFixFor文件中选择了一个选择器,并用目标=“目标”的参数运行如下:

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
O=$(C:%.C=%.O)
O+=$(S:%.S=%.O)
ifeq($(目标),发布)
ELF=bin/release.ELF
CC_标志+=-O3
OBJPATH=obj/释放
其他的
ELF=bin/debug.ELF
CC_标志+=-g3
OBJPATH=obj/debug
恩迪夫
OBJ=$(addprefix$(OBJPATH)/,$(O))
全部:makepath构建
构建:$(OBJ)
@回音链接----
$(CC)$(OBJ)$(LIBS)$(LD_标志)-o$(ELF)
生成路径:
@mkdir-p$(dir$(OBJ))
$(对象路径)/%.o:%.c
@回声——C----
$(CC)$(CC_标志)-c$<-o$@
$(对象路径)/%.o:%.s
@回声----
$(CC)$(CC_标志)-c$<-o$@
清洁:
查找-名称*.o-删除
查找-名称*.elf-删除

正如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
O=$(C:%.C=%.O)
O+=$(S:%.S=%.O)
ifeq($(目标),发布)
ELF=bin/release.ELF
CC_标志+=-O3
OBJPATH=obj/释放
其他的
ELF=bin/debug.ELF
CC_标志+=-g3
OBJPATH=obj/debug
恩迪夫
OBJ=$(addprefix$(OBJPATH)/,$(O))
全部:makepath构建
构建:$(OBJ)
@回音链接----
$(CC)$(OBJ)$(LIBS)$(LD_标志)-o$(ELF)
生成路径:
@mkdir-p$(dir$(OBJ))
$(对象路径)/%.o:%.c
@回声——C----
$(CC)$(CC_标志)-c$<-o$@
$(对象路径)/%.o:%.s
@回声----
$(CC)$(CC_标志)-c$<-o$@
清洁:
查找-名称*.o-删除
查找-名称*.elf-删除

Arm none eabi gcc-我想这不需要