Makefile找不到规则影响可用文件

时间:2019-02-07 19:35:22

标签: 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
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)/*

制作文件时,我得到以下信息:

make: *** No rule to make target '/build/main.o', needed by 'build'.  Stop.

我想这是一个错误的食谱:

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

很遗憾,我无法独自完成此操作。 所有文件都位于正确的文件夹中。

我非常感谢所有帮助!

特里斯坦

2 个答案:

答案 0 :(得分:1)

您在这里看到一些问题,我可以看到。但是首先-仅检查(以防万一)您的所有规则都仅使用制表符而不是空格缩进.....这可能是makefile的真正“沉默”杀手,因为它们会给出废话错误消息。

  1. 好的-假设您拥有:
    INCLUDE_DIR = inc
    SOURCE_DIR = src
    BUILD_DIR = build

代替评论中提到的/src等。

  1. 您真的有inc / main.h和inc / pfc.h吗?

我复制并粘贴了您的makefile,并添加了src和inc文件夹(但是我使用gcc代替了arm-none-eabi-gcc。它正确地编译了行,但是在链接器阶段失败了,因为您正在尝试构建输出文件当已经有一个名为build的文件夹时,它称为build(在Linux中是不允许的-对于Windows可能还可以,但我不建议这样做)。

  1. 我回答了另一个问题-但是如果您嵌套了src / inc目录并且希望能够清理输出文件夹,那么可能是一个更好的起点,而不是放在这里为了方便:
    # 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)

注意,这只是一个模板,您仍然需要填写gcc / makefile标志-但这是一个不错的起点...

  1. 调试

$(info ...)是您的朋友-例如,您可以这样做:

$(info OBJ = $(OBJ))

$(info objrule = $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c $(INCLUDES))

要打印出我们的品牌将这些变量/行扩展为-这可以产生有用的调试信息。

答案 1 :(得分:0)

这是您的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

要添加另一个可执行目标,请执行以下操作:

exes += another
another.obj := another_main.o another_pfc.o