基于目录存在的 Makefile 变量赋值

Makefile variable assignment based on an existence of a directory

寻找根据目录的存在在 Makefile 中分配变量的方法。

例如:(伪代码)

if dir "src/$(project)" exists
SOURCE_DIR := src/$(project)
else
SOURCE_DIR := src/default

test.o: $SOURCE_DIR/test.c
    gcc -c -o $@ $<

实现上述目标的最佳方法是什么

试试这个。

SOURCE_DIR := src/$(shell test -d src/"$(project)" && echo "$(project)" || echo default)

由于您的源目录将包含文件而一个不存在的目录不会,您可以使用 GNU make 内部函数 $(wildcard):

project := test

# returns all entries under src/$(project) directory or empty string
ifneq ($(wildcard src/$(project)/*),)
SOURCE_DIR := src/$(project)
else
SOURCE_DIR := src/default
endif

.PHONY: all
all:
    @echo $(SOURCE_DIR)

测试运行

$ ls src/test/
a.c
$ make
src/test

$ rm -rf src/test
$ make
src/default

奖励:重写条件语句可能更具可读性:

SOURCE_DIR := src/$(project)
ifeq ($(wildcard $(SOURCE_DIR)/*),)
  # fall back to default directory
  SOURCE_DIR := src/default
endif

更新2:如果你不想依赖目录中任何文件的存在,你也可以直接测试目录名。一个目录总是有一个条目 .,因为它指向它自己:

SOURCE_DIR := src/$(project)
ifeq ($(wildcard $(SOURCE_DIR)/.),)
  # fall back to default directory
  SOURCE_DIR := src/default
endif

更新 3: 添加检查 $(project) 是否已设置:

SOURCE_DIR := src/$(project)
ifeq ($(strip $(project)),)
  # fall back to default directory
  SOURCE_DIR := src/default
else ifeq ($(wildcard $(SOURCE_DIR)/.),)
  # fall back to default directory
  SOURCE_DIR := src/default
endif

或者如果你更喜欢 makefile Golfing(感谢@MadScientist 的建议)

SOURCE_DIR := $(or $(and $(project),$(wildcard src/$(project)/.)),src/default)
  • $(and) 结果
    • 如果$(project)是一个空字符串:空字符串
    • if src/$(project) 不是目录:空字符串
    • 否则:src/$(project)/.,相当于src/$(project)
  • $(or) 结果
    • if $(and) returns 空字符串:src/default
    • 否则:$(and)
    • 返回的字符串

警告: 如果 $(project) 包含白色 space.

,上面列出的测试将失败