您可以使用我为简单项目制作的这个模板。我不知道您使用的是哪个编译器,但您可以使用第一部分中的变量以及其他有用的配置对其进行配置:
#=============================================================================
# Project related variables
EXENAME = test
FILEIDENTIFIER = .c
COMPFLAGS = -pedantic -Wall
COMPSTANDARD = -std=c11
EXELINKS = -lm
DBARGS = -g
BUILDDIR = build/
BINARY_OUTPUT_DIR = $(BUILDDIR)bin/
OBJDIR = obj/
SOURCEDIRS = src/
INCLUDEDIRS = include/
LIBSDIRS = /usr/lib/
#=============================================================================
# Commands variables
COMPILER = gcc
LINKER = ld -r
DISPLAY = printf
MKDIR = mkdir -p
RMDIR = rmdir
RM = rm -f
#=============================================================================
# Other
VOIDECHO = > /dev/null 2>&1
#=============================================================================
# Semi-automatic variables
EXEFINALOBJ = $(OBJDIR)$(EXENAME).o
EXEFINAL = $(BINARY_OUTPUT_DIR)$(EXENAME)
INCLUDEARGS = $(addprefix -I,$(INCLUDEDIRS))
#=============================================================================
# Automatic variables
SOURCES = $(foreach sourcedir,$(SOURCEDIRS),$(wildcard $(sourcedir)**/*$(FILEIDENTIFIER)) $(wildcard $(sourcedir)*$(FILEIDENTIFIER)))
OBJECTS = $(patsubst %$(FILEIDENTIFIER),%.o,$(foreach sourcedir,$(SOURCEDIRS),$(subst $(sourcedir),$(OBJDIR),$(wildcard $(sourcedir)**/*$( FILEIDENTIFIER)) $(wildcard $(sourcedir)*$(FILEIDENTIFIER)))))
GENERATED_FILES = $(OBJECTS) $(EXEFINALOBJ) $(EXEFINAL)
GENERATED_FOLDERS = $(OBJDIR) $(BINARY_OUTPUT_DIR) $(BUILDDIR)
#=============================================================================
# Special GNU make variables
VPATH = $(SOURCEDIRS)
#=============================================================================
# Rules: Phony Targets
.PHONY: silent
silent:
@make --silent $(EXEFINAL)
.PHONY: all
all: $(EXEFINAL)
.PHONY: debug
debug: COMPFLAGS += $(DBARGS)
debug: all
.PHONY: clean
clean:
@$(DISPLAY) "\n-> Cleaning files...\n"
@$(DISPLAY) " $(foreach file,$(GENERATED_FILES),$(if $(wildcard $(file)),- Removing file $(file)\n,\b))"
@$(RM) $(GENERATED_FILES)
@$(DISPLAY) "\n-> Cleaning folders...\n"
@$(DISPLAY) " $(foreach folder,$(GENERATED_FOLDERS),$(if $(wildcard $(folder)),- Removing folder $(folder)\n,\b))"
@$(RMDIR) $(GENERATED_FOLDERS) $(VOIDECHO) || true
@$(DISPLAY) "\n"
#=============================================================================
# Rules: File Targets
$(EXEFINAL): $(EXEFINALOBJ)
@$(DISPLAY) "\n - Building $@ from $^... "
@$(MKDIR) $(BINARY_OUTPUT_DIR)
$(COMPILER) $(EXEFINALOBJ) -o $@ $(LIBARGS) $(EXELINKS)
@$(DISPLAY) "Done"
@$(DISPLAY) "\n\n"
$(EXEFINALOBJ): $(OBJECTS)
@$(DISPLAY) "\n - Merging objects files into $@... "
$(LINKER) $(OBJECTS) -o $@
@$(DISPLAY) "Done"
$(OBJDIR)%.o: %$(FILEIDENTIFIER)
@$(DISPLAY) "\n - Building $@ from $^... "
@$(MKDIR) $(OBJDIR)
$(COMPILER) $(COMPFLAGS) $(COMPSTANDARD) $(INCLUDEARGS) -c $^ -o $@
@$(DISPLAY) "Done"
实际配置是针对 Linux 的,使用 gcc 和 ld。它支持源的子文件夹,并定义了 4 个目标:
- 静默(默认):静默构建
- 全部:详细构建
- 调试:调试构建
- clean:删除 makefile 生成的文件和文件夹
如果您想确切了解 Makefile 的工作原理,正如 MadScientist 所写,请查看位于 https://www.gnu.org/software/make/manual/html_node/Introduction.html 的 GNU make 手册