大多数“制作”教程几乎没有涵盖您的情况:以通用方式处理不同的文件集。
- 有些文件只是提供了一些实现(我们称这些“lib”文件,即使它们不会被编译成静态或动态库文件),
- 其他文件包含
main() 函数,每个文件都必须生成可执行二进制文件,并与前一个文件链接。
我不会在这里给你一个完整的 makefile,但会尝试展示一个如何处理这种情况的全局方法。
首先,定义不同的源文件夹和对象文件夹:
SRC_DIR_LIB=src
SRC_DIR_EXE=Mains
OBJ_DIR_LIB=obj/lib
OBJ_DIR_EXE=obj/exe
BIN_DIR=bin
HEAD_DIR=include
(这非常很有用,因为如果有一天树的组织发生变化,您只需在一个点上编辑更改。)
而且,是的,您应该为目标文件设置单独的文件夹。
然后,定义源文件集:
SRC_FILES_LIB = $(wildcard $(SRC_DIR_LIB)/*.c)
SRC_FILES_EXE = $(wildcard $(SRC_DIR_EXE)/*.c)
HEAD_FILES = $(wildcard $(HEAD_DIR)/*.h)
让make生成一组目标文件:
OBJ_FILES_LIB = $(patsubst $(SRC_DIR_LIB)/%.c,$(OBJ_DIR_LIB)/%.o,$(SRC_FILES_LIB))
OBJ_FILES_EXE = $(patsubst $(SRC_DIR_EXE)/%.c,$(OBJ_DIR_EXE)/%.o,$(SRC_FILES_EXE))
让make生成可执行文件集:
EXEC_FILES = $(patsubst $(SRC_DIR_EXE)/%.c,$(BIN_DIR)/%,$(SRC_FILES_EXE))
这些将是你的最终目标,你告诉它:
all: $(EXEC_FILES)
为确保您拥有所有这些变量,您可以将show 目标添加到您的makefile:
show:
@echo "SRC_FILES_LIB=$(SRC_FILES_LIB)"
@echo "SRC_FILES_EXE=$(SRC_FILES_EXE)"
.. and so on for all the others
尝试make show,并仔细检查。
然后告诉make如何做真正的工作。您需要两个单独的编译目标:
$(OBJ_DIR_EXE)/%.o: $(SRC_DIR_EXE)/%.c $(HEAD_FILES)
$(CC) -o $@ -c $< $(CFLAGS)
$(OBJ_DIR_LIB)/%.o: $(SRC_DIR_LIB)/%.c $(HEAD_FILES)
$(CC) -o $@ -c $< $(CFLAGS)
编辑:C程序使用$(CC),如果是C++,则使用$(CXX)
以及使用subst()函数的程序链接步骤:
$(BIN_DIR)/%: $(OBJ_DIR_EXE)/%.o
$(CC) -o $@ -s $(subst $(BIN_DIR)/,$(OBJ_DIR_EXE)/,$@).o $(OBJ_FILES_LIB) $(LDFLAGS)
决赛:
- 在这里,只进行了基本的依赖关系检查:对 any 头文件的任何编辑都将导致 所有 文件的重建。这对于大型项目是不可接受的,但对于您描述的小型项目来说是可以的。
- 我这里没有考虑需要在这里构建的“测试”程序,但是一旦你了解了这里的内容,处理这些应该不难。
- 我没有对此进行测试(而是从我自己的 makefile 中复制粘贴过来的,那是一个 C++ 项目),因此可能还有一些小的改动。手动编写 makefile 是一门艺术...
编辑:这是针对基于 Linux 的环境,其中程序名称通常没有扩展名。如果是 Windows,您可能需要在多个位置添加 .exe。