下面是我添加到文档的Makefile(正在审核,所以我会在这里发布):
# Set project directory one level above the Makefile directory. $(CURDIR) is a GNU make variable containing the path to the current working directory
PROJDIR := $(realpath $(CURDIR)/..)
SOURCEDIR := $(PROJDIR)/Sources
BUILDDIR := $(PROJDIR)/Build
# Name of the final executable
TARGET = myApp.exe
# Decide whether the commands will be shown or not
VERBOSE = TRUE
# Create the list of directories
DIRS = Folder0 Folder1 Folder2
SOURCEDIRS = $(foreach dir, $(DIRS), $(addprefix $(SOURCEDIR)/, $(dir)))
TARGETDIRS = $(foreach dir, $(DIRS), $(addprefix $(BUILDDIR)/, $(dir)))
# Generate the GCC includes parameters by adding -I before each source folder
INCLUDES = $(foreach dir, $(SOURCEDIRS), $(addprefix -I, $(dir)))
# Add this list to VPATH, the place make will look for the source files
VPATH = $(SOURCEDIRS)
# Create a list of *.c sources in DIRS
SOURCES = $(foreach dir,$(SOURCEDIRS),$(wildcard $(dir)/*.c))
# Define objects for all sources
OBJS := $(subst $(SOURCEDIR),$(BUILDDIR),$(SOURCES:.c=.o))
# Define dependencies files for all objects
DEPS = $(OBJS:.o=.d)
# Name the compiler
CC = gcc
# OS specific part
ifeq ($(OS),Windows_NT)
RM = del /F /Q
RMDIR = -RMDIR /S /Q
MKDIR = -mkdir
ERRIGNORE = 2>NUL || true
SEP=\\
else
RM = rm -rf
RMDIR = rm -rf
MKDIR = mkdir -p
ERRIGNORE = 2>/dev/null
SEP=/
endif
# Remove space after separator
PSEP = $(strip $(SEP))
# Hide or not the calls depending of VERBOSE
ifeq ($(VERBOSE),TRUE)
HIDE =
else
HIDE = @
endif
# Define the function that will generate each rule
define generateRules
$(1)/%.o: %.c
@echo Building [email protected]
$(HIDE)$(CC) -c $$(INCLUDES) -o $$(subst /,$$(PSEP),[email protected]) $$(subst /,$$(PSEP),$$<) -MMD
endef
# Indicate to make which targets are not files
.PHONY: all clean directories
all: directories $(TARGET)
$(TARGET): $(OBJS)
$(HIDE)echo Linking [email protected]
$(HIDE)$(CC) $(OBJS) -o $(TARGET)
# Include dependencies
-include $(DEPS)
# Generate rules
$(foreach targetdir, $(TARGETDIRS), $(eval $(call generateRules, $(targetdir))))
directories:
$(HIDE)$(MKDIR) $(subst /,$(PSEP),$(TARGETDIRS)) $(ERRIGNORE)
# Remove all objects, dependencies and executable files generated during the build
clean:
$(HIDE)$(RMDIR) $(subst /,$(PSEP),$(TARGETDIRS)) $(ERRIGNORE)
$(HIDE)$(RM) $(TARGET) $(ERRIGNORE)
@echo Cleaning done !
主要特点
- 在指定的文件夹
- 多个源文件夹
- 多个对应的目标文件夹对象和依赖文件的
C
源自动检测
- 自动生成规则为每个目标文件夹
- 目标文件夹不存在时创建
- 依赖管理与
gcc
:只建什么是必要的
- 文选
Unix
和DOS
系统
- 而立
GNU Make
如何使用这个Makefile
适应这个Makefile对你的项目你必须:
- 更改
TARGET
变量在SOURCEDIR
的Sources
和Build
文件夹的名称相匹配的目标名称
- 变化
BUILDDIR
- 变化
make all VERBOSE=FALSE
Makefile文件在Makefile本身或发出呼叫的详细级别( )
- 更改
DIRS
中文件夹的名称以匹配您的源代码和生成文件夹
- 如果需要,更改编译器和标记
在这个Makefile Folder0
,Folder1
和Folder2
是等同于你的FolderA
,FolderB
和FolderC
。
请注意,我目前还没有机会在Unix系统上测试它,但它在Windows上正常工作。
说明了几个棘手的部分:
忽略的Windows的mkdir错误
ERRIGNORE = 2>NUL || true
这有两种作用: 第一个,2>NUL
是重定向错误输出NUL,所以它不在控制台中。
第二个,|| true
可防止命令上升错误级别。这是与Makefile无关的Windows东西,因为Windows'mkdir
命令会提高错误级别,如果我们尝试创建已存在的文件夹,而我们并不在意它是否存在,那很好。常见的解决方案是使用if not exist
结构,但这不是UNIX兼容的,所以即使它很棘手,我也认为我的解决方案更清晰。含有它们的正确路径中的所有目标文件OBJS的
创作
OBJS := $(subst $(SOURCEDIR),$(BUILDDIR),$(SOURCES:.c=.o))
在这里我们要OBJS包含与他们的系统的全部目标文件,而且我们已经有了源是包含了所有的源文件及其路径。 $(SOURCES:.c=.o)
对所有来源的* .o都进行* .c更改,但路径仍是其中一个来源。 $(subst $(SOURCEDIR),$(BUILDDIR), ...)
将简单地用构建路径减去整个源路径,所以我们最终有一个包含.o文件及其路径的变量。
与Windows和Unix风格路径分隔符
SEP=\\
SEP =/
PSEP = $(strip $(SEP))
本交易的存在只是为了让Makefile文件在Unix和Windows的工作,自Windows路径使用反斜杠,而其他人使用斜线, 。
SEP=\\
此处使用双反斜杠来转义反斜杠字符,make
通常将其视为“忽略换行字符”以允许在多行上书写。
PSEP = $(strip $(SEP))
这将删除已自动添加的SEP
变量的空格字符。
自动生成的规则,每个目标文件夹
define generateRules
$(1)/%.o: %.c
@echo Building [email protected]
$(HIDE)$(CC) -c $$(INCLUDES) -o $$(subst /,$$(PSEP),[email protected]) $$(subst /,$$(PSEP),$$<) -MMD
endef
这也许与您的用例中最相关的伎俩。这是一个可以使用$(eval $(call generateRules, param))
生成的规则模板,其中param
是您在模板中可以找到的$(1)
。 这基本符合这样的规则对每个目标文件夹填满的Makefile:
path/to/target/%.o: %.c
@echo Building [email protected]
$(HIDE)$(CC) -c $(INCLUDES) -o $(subst /,$(PSEP),[email protected]) $(subst /,$(PSEP),$<) -MMD
你在问一个非常简单的makefile,所以如果有人在这里给你的话,我不会感到惊讶。但通常我们提供免费的帮助,而不是免费的代码。 – Beta
是的你是对的。 –
这种简单的Makefile实际上可以很好地匹配新的文档功能,但对于Q/A而言,它有点太宽泛。 – Tim