Gcc Makefile在没有可用文件的情况下找不到规则

Gcc Makefile在没有可用文件的情况下找不到规则,gcc,makefile,Gcc,Makefile,目前,我正在尝试让我的一个相当大的项目使用Makefile。我以前使用过Make,但方式相当粗糙,没有真正的动态性,这意味着我对好的makefile还很陌生 我的Makefile如下所示: INCLUDE_DIR = /inc SOURCE_DIR = /src BUILD_DIR = /build BUILD_NAME = build CC = arm-none-eabi-gcc CFLAGS = -I$(INCLUDE_DIR) _INCLUDES = main.h pfc.h INC

目前,我正在尝试让我的一个相当大的项目使用Makefile。我以前使用过Make,但方式相当粗糙,没有真正的动态性,这意味着我对好的makefile还很陌生

我的Makefile如下所示:

INCLUDE_DIR = /inc
SOURCE_DIR = /src
BUILD_DIR = /build

BUILD_NAME = build

CC = arm-none-eabi-gcc
CFLAGS = -I$(INCLUDE_DIR)

_INCLUDES = main.h pfc.h
INCLUDES = $(patsubst %, $(INCLUDE_DIR)/%, $(_INCLUDES))

_OBJ = main.o pfc.o
OBJ = $(patsubst %, $(BUILD_DIR)/%, $(_OBJ))

$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c $(INCLUDES)
    $(CC) -c -o $@ $< $(CFLAGS)

$(BUILD_NAME): $(OBJ)
    $(CC) -o $@ $^ $(CFLAGS)

all: $(BUILD_NAME)

.PHONY: clean

clean:
    rm -rf $(BUILD_DIR)/*
我猜这是这个食谱中的一个错误:

$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c $(INCLUDES)
    $(CC) -c -o $@ $< $(CFLAGS)
遗憾的是,我无法独自完成这项工作。
所有文件都在正确的文件夹中可用

我真的很感谢你的帮助


特里斯坦

我可以看到你这里有一些问题。但首先-只要检查一下,以防所有规则都只缩进了制表符而不是空格。。。。。这可能是一个真正的沉默杀手的makefiles,因为他们提供垃圾错误消息

好吧,那么-假设您有: 而不是/src等。。如评论中所述

你真的有inc/main.h和inc/pfc.h吗? 我复制并粘贴了你的makefile,添加了你的src和inc文件夹,但是我使用了gcc而不是arm-none-eabi-gcc。它正确地执行了编译行,但在链接器阶段失败,因为在linux中已经存在一个名为build not allowed的文件夹的情况下,您正在尝试构建一个名为build的输出文件-对于windows可能是可以的,但我不推荐这样做

我回答了另一个问题-但是如果您有嵌套的src/inc目录,并且希望能够清理输出文件夹,那么这可能是一个更好的起点-为了方便起见,我将把它放在这里: 请注意,这只是一个模板,您仍然需要填写gcc/makefile标志-但这是一个不错的起点

调试 $info。。。是你的朋友-例如,你可以:

$info OBJ=$OBJ

$info objrule=$BUILD_DIR/%.o:$SOURCE_DIR/%.c$包括


打印我们的what make已将这些变量/行扩展为-这可以产生有用的调试。

这里是另一个版本的makefile,具有自动依赖项生成功能:

INCLUDE_DIR := inc
SOURCE_DIR := src
BUILD_DIR := build

CC := arm-none-eabi-gcc
CPPFLAGS := -I$(INCLUDE_DIR)

exes := build
build.obj := main.o pfc.o

all : ${exes:%=${BUILD_DIR}/%}

.SECONDEXPANSION:

${BUILD_DIR}:
    mkdir -p $@

# Rule to link all exes.
${exes:%=${BUILD_DIR}/%} : ${BUILD_DIR}/% : $$(addprefix ${BUILD_DIR}/,$${$$*.obj}) | $${@D}
    ${CC} -o $@ ${LDFLAGS} $^ ${LDLIBS}

# Rule to compile C sources. And generate header dependencies.
${BUILD_DIR}/%.o : ${SOURCE_DIR}/%.c | $${@D}
    ${CC} -o $@ -c ${CPPFLAGS} ${CFLAGS} -MD -MP $<

# Include automatically generated header dependencies.
ifneq ($(MAKECMDGOALS),clean)
-include $(foreach exe,${exes},$(patsubst %.o,${BUILD_DIR}/%.d,${${exe}.obj})) 
endif

clean:
    rm -rf $(BUILD_DIR)

.PHONY: all clean

所有文件都在正确的文件夹中可用。您的计算机根文件系统/下是否真的有名为src,inc和build的目录?哦,糟糕,对不起。/在正确的目录下生成。生成文件仍然找不到规则。@MaximeGroshkin我找到了:$OBJ_DIR/%.o:%.c |$DIRS。。。还是我错过了什么?@MaximEgorushkin哦,是的-好地方。在这种情况下,我认为它只会触发一个重新链接,如果一个文件可能发生了更改,无论如何都会发生这种情况,但它的定义更正确,更新:@MaximeGroushkin-是的,我在那行旁边放了一条评论,建议有其他纯make的选项,所以不要太在意。关于对象,不,这会在对象文件夹中保持文件夹结构的完整性,因此任何具有相同名称的文件都是安全的-这就是事实上的要点:
    INCLUDE_DIR = inc
    SOURCE_DIR = src
    BUILD_DIR = build
    # Get your source list (use wildcard or what ever, but just for clarity you should end up with a list of files with full paths to start with):

    # Output folders/targets
    SRC_DIR = src
    OBJ_DIR = obj
    BIN_DIR = bin
    OUTPUT_FILE = output

    # Generate list of source files - this is a linux command - but you can do this in pure make using wildcard and such).
    SOURCES := $(shell find $(SOURCEDIR) -name '*.c')

    # Create your objects list in the obj directory
    OBJECTS = $(addprefix $(OBJ_DIR)/,$(addsuffix .o,$(basename $(SOURCES))))

    # Create list of unique folders to create
    DIRS = $(sort $(dir $(OBJECTS))) $(BIN_DIR)

    # Create list of include paths
    INCS = $(addprefix -I,$(sort $(dir $(SOURCES))))

    # Main target rule
    $(BIN_DIR)/$(OUTPUT_FILE): $(OBJECTS) | $(DIRS)
        @echo linker: gcc $(OBJECTS) -o $@
        @touch $@

    # Rule to build your object file - ensure that the folders are created first (also create a dummy obj file) - note this works for parallel builds too (make -j
    $(OBJ_DIR)/%.o: %.c | $(DIRS)
        @echo compile: gcc $(INCS) -c $? -o $@
        @touch $@

    # Create your directories here
    $(DIRS):
        @echo Creating dir: $@
        @mkdir -p $@

    # Clean if needed
    .PHONY: clean
    clean:
        rm -rf $(OBJ_DIR) $(BIN_DIR)
INCLUDE_DIR := inc
SOURCE_DIR := src
BUILD_DIR := build

CC := arm-none-eabi-gcc
CPPFLAGS := -I$(INCLUDE_DIR)

exes := build
build.obj := main.o pfc.o

all : ${exes:%=${BUILD_DIR}/%}

.SECONDEXPANSION:

${BUILD_DIR}:
    mkdir -p $@

# Rule to link all exes.
${exes:%=${BUILD_DIR}/%} : ${BUILD_DIR}/% : $$(addprefix ${BUILD_DIR}/,$${$$*.obj}) | $${@D}
    ${CC} -o $@ ${LDFLAGS} $^ ${LDLIBS}

# Rule to compile C sources. And generate header dependencies.
${BUILD_DIR}/%.o : ${SOURCE_DIR}/%.c | $${@D}
    ${CC} -o $@ -c ${CPPFLAGS} ${CFLAGS} -MD -MP $<

# Include automatically generated header dependencies.
ifneq ($(MAKECMDGOALS),clean)
-include $(foreach exe,${exes},$(patsubst %.o,${BUILD_DIR}/%.d,${${exe}.obj})) 
endif

clean:
    rm -rf $(BUILD_DIR)

.PHONY: all clean
exes += another
another.obj := another_main.o another_pfc.o