Make-File:将多个 SRC 文件夹编译为单个 OBJ 文件夹

Make-File: compile multiple SRC-Folders to single OBJ-Folder

我的项目层次结构如下所示:

+Makefile
+---src
|   main.c
|   ...
|   +---block
|   |       air.c
|   |       ...
|   |       
|   +---entity
|   |       esc.c
|   |       esc.h
|   |       ...
|   |       
|   \---world
|           \---gen
|                noise.c
|                ...
|           xyz.c
|           ...
\---obj
    main.o
    air.o
    esc.o
    noise.o
    xyz.o
    ...

我想用make将层次结构中的所有.c文件编译到一个obj文件夹中。 到目前为止我得到了:

UNAME_S = $(shell uname -s)

CC = clang
CFLAGS = -std=c11 -O3 -g -Wall -Wextra -Wpedantic -Wstrict-aliasing
CFLAGS += -Wno-pointer-arith -Wno-newline-eof -Wno-unused-parameter -Wno-gnu-statement-expression
CFLAGS += -Wno-gnu-compound-literal-initializer -Wno-gnu-zero-variadic-macro-arguments
CFLAGS += -Ilib/cglm/include -Ilib/glad/include -Ilib/glfw/include -Ilib/stb -Ilib/noise -fbracket-depth=1024
LDFLAGS = lib/glad/src/glad.o lib/cglm/libcglm.a lib/glfw/src/libglfw3.a lib/noise/libnoise.a -lm

# GLFW required frameworks on OSX
ifeq ($(UNAME_S), Darwin)
    LDFLAGS += -framework OpenGL -framework IOKit -framework CoreVideo -framework Cocoa
endif

ifeq ($(UNAME_S), Linux)
    LDFLAGS += -ldl -lpthread
endif

OBJ_DIR = obj

SRC = $(wildcard src/**/*.c) $(wildcard src/*.c) $(wildcard src/**/**/*.c) $(wildcard src/**/**/**/*.c)
OBJ = $(addprefix $(OBJ_DIR)/,$(addsuffix .o,$(notdir $(basename $(SRC)))))

SRC_DIRS = $(sort $(dir $(SRC)))
BIN = bin

.PHONY: all clean

all: dirs libs game

libs:
    cd lib/cglm && cmake . -DCGLM_STATIC=ON && make
    cd lib/glad && $(CC) -o src/glad.o -Iinclude -c src/glad.c
    cd lib/glfw && cmake . && make
    cd lib/noise && make

dirs:
    mkdir -p ./$(BIN) ./$(OBJ_DIR)

run: all
    $(BIN)/game

game: $(OBJ)
    $(CC) -o $(BIN)/game $^ $(LDFLAGS)

$(OBJ_DIR)/%.o: src/%.c
    $(CC) -o $@ -c $< $(CFLAGS)

$(OBJ_DIR)/%.o: src/block/%.c
    $(CC) -o $@ -c $< $(CFLAGS)

$(OBJ_DIR)/%.o: src/entity/%.c
    $(CC) -o $@ -c $< $(CFLAGS)

$(OBJ_DIR)/%.o: src/gfx/%.c
    $(CC) -o $@ -c $< $(CFLAGS)

$(OBJ_DIR)/%.o: src/ui/%.c
    $(CC) -o $@ -c $< $(CFLAGS)

$(OBJ_DIR)/%.o: src/util/%.c
    $(CC) -o $@ -c $< $(CFLAGS)

$(OBJ_DIR)/%.o: src/world/%.c
    $(CC) -o $@ -c $< $(CFLAGS)

$(OBJ_DIR)/%.o: src/world/gen/%.c
    $(CC) -o $@ -c $< $(CFLAGS)

clean:
    rm -rf $(BIN) $(OBJ_DIR)

有什么方法可以更有效地完成这项工作吗?特别是 $(OBJ_DIR)/%.o 案例?

最好的方法是 using VPATH

例如:

SRC := $(wildcard src/*/*.c) $(wildcard src/*.c) $(wildcard src/*/*/*.c) $(wildcard src/*/*/*/*.c)
OBJ := $(addprefix $(OBJ_DIR)/,$(addsuffix .o,$(notdir $(basename $(SRC)))))

SRC_DIRS := $(sort $(dir $(SRC)))

VPATH := $(SRC_DIRS)

  ...

$(OBJ_DIR)/%.o: %.c
        $(CC) -o $@ -c $< $(CFLAGS)

你只需要一个模式规则。