下面是我添加到文檔的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