这是我通常在手写 Makefile 中定义
clean
目标的标准方法:
clean:
rm -fr $(BUILD_DIR)/*
如果变量中有拼写错误或者我忘记定义它,它将改为运行
rm -rf /*
,这不是我想要接受的风险。但是在发生了这种情况之后,我一直在尝试找到一种更好的方法以安全的方式引用 Makefile 中的路径,但我找不到它。
有更好的方法吗?
首先,有很多很多方法可以构建
Makefile
,使事情更容易清洁。大多数都是个人喜好,因此没有正确或错误的问题。
在您的情况下,最突出的是尝试在
rm
虚假目标下使用单个 clean:
命令进行清理。使用多个特定的rm
命令比使用一个“包含所有”rm -r
要容易得多。正如您所发现的,当您rm -r $(SOMEVAR)/*
时,错误命名或缺失的变量设置可能会产生可怕的后果。
我通常所做的是将源代码放入
src
子目录中,包含在 include
子目录中,然后将所有目标文件输出到 obj
子目录中。 (如果您愿意,您也可以在 bin
目录中创建二进制文件)。在这种情况下,clean:
变成
clean:
rm -rvf $(OBJ)
rm -rvf $(BIN)
允许您做到这一点的简单设置是:
TARGET = myexe
CC = gcc
BIN = bin
SRC = src
OBJ = obj
SRCS = $(wildcard $(SRC)/*.c)
OBJS = $(patsubst $(SRC)%.c, $(OBJ)/%.o, $(SRCS))
CFLAGS += -Wall -Wextra -pedantic -Wshadow -Werror -std=c11
CFLAGS += -Iinclude
LDFLAGS +=
# clean before build and create directories
all: clean setup $(TARGET)
setup:
@mkdir -p $(BIN)
@mkdir -p $(OBJ)
# build executable
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $(BIN)/$(TARGET) $^
# compile objects
$(OBJ)/%.o: $(SRC)/%.c
$(CC) -c $(CFLAGS) $< -o $@
# clean
clean:
@rm -rvf $(OBJ)
@rm -rvf $(BIN)
这样,当
rm -rf $(SOMEVAR)/*
未定义或为空时,您就永远不可能 SOMEVAR
。祝您编码顺利。