目前,我正在尝试开发一个与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)
很遗憾,我无法独自完成此操作。 所有文件都位于正确的文件夹中。
我非常感谢所有帮助!
特里斯坦
答案 0 :(得分:1)
您在这里看到一些问题,我可以看到。但是首先-仅检查(以防万一)您的所有规则都仅使用制表符而不是空格缩进.....这可能是makefile的真正“沉默”杀手,因为它们会给出废话错误消息。
INCLUDE_DIR = inc
SOURCE_DIR = src
BUILD_DIR = build
代替评论中提到的/src
等。
我复制并粘贴了您的makefile,并添加了src和inc文件夹(但是我使用gcc代替了arm-none-eabi-gcc
。它正确地编译了行,但是在链接器阶段失败了,因为您正在尝试构建输出文件当已经有一个名为build
的文件夹时,它称为build
(在Linux中是不允许的-对于Windows可能还可以,但我不建议这样做)。
# 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标志-但这是一个不错的起点...
$(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