测试 makefile 中是否存在目录

问题描述 投票:0回答:8

在他的 answer @Grundlefleck 中解释了如何检查目录是否存在。我尝试在

makefile
中使用它,如下所示:

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then
        echo "Dir exists"
    fi

运行

make foo.bak
(假设
foo.bar
存在)会产生以下错误:

echo "foo"
foo
if [ -d "~/Dropbox" ]; then
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [foo.bak] Error 2

我所做的解决方法是使用一个独立的 bash 脚本来实现测试,并且我从

makefile
调用该脚本。然而,这听起来非常麻烦。有没有更好的方法来检查目录是否存在于
makefile
中?

bash makefile
8个回答
114
投票

Make命令,如果是shell命令,必须在一行中,或者使用反斜杠进行行扩展在多行中。所以,这种方法会起作用:

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then echo "Dir exists"; fi

或者

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then \
        echo "Dir exists"; \
    fi

66
投票

这种方法的回声最小:

.PHONY: all
all:
ifneq ($(wildcard ~/Dropbox/.*),)
        @echo "Found ~/Dropbox."
else
        @echo "Did not find ~/Dropbox."
endif

53
投票

在目录不存在时采取行动

如果您只需要知道某个目录是否不存在并希望通过创建目录等方式对其进行操作,则可以使用普通的 Makefile 目标:

directory = ~/Dropbox

all: | $(directory)
    @echo "Continuation regardless of existence of ~/Dropbox"

$(directory):
    @echo "Folder $(directory) does not exist"
    mkdir -p $@

.PHONY: all

备注:

  • |
    表示make不应该关心时间戳(这是一个仅订单先决条件)。
  • 您可以写
    mkdir -p $@
    退出,或者以不同的方式解决您的情况,而不是写
    false

如果您还需要在目录“存在”时运行一系列特定的指令,则不能使用上述内容。换句话说,它相当于: if [ ! -d "~/Dropbox" ]; then echo "The ~/Dropbox folder does not exist" fi

没有
else

声明。


根据目录的存在采取行动

如果您想要相反的 if 语句,这也是可能的:

directory = $(wildcard ~/Dropbox) all: | $(directory) @echo "Continuation regardless of existence of ~/Dropbox" $(directory): @echo "Folder $(directory) exists" .PHONY: all $(directory)

这相当于:

if [ -d "~/Dropbox" ]; then echo "The ~/Dropbox folder does exist" fi

再次强调,没有任何
else

声明。


根据目录存在和不存在采取行动

这变得有点麻烦,但最终为这两种情况提供了很好的目标:

directory = ~/Dropbox dir_target = $(directory)-$(wildcard $(directory)) dir_present = $(directory)-$(directory) dir_absent = $(directory)- all: | $(dir_target) @echo "Continuation regardless of existence of ~/Dropbox" $(dir_present): @echo "Folder $(directory) exists" $(dir_absent): @echo "Folder $(directory) does not exist" .PHONY: all

这相当于:

if [ -d "~/Dropbox" ]; then echo "The ~/Dropbox folder does exist" else echo "The ~/Dropbox folder does not exist" fi

当然,通配符扩展可能比 if-else-语句慢。然而,第三种情况可能相当罕见,只是为了完整性而添加的。


18
投票

.PHONY: all something: echo "hi" all: test -d "Documents" && something

仅当 
something

存在时,才会执行

Documents
下的命令。

为了解决评论中提到的

问题

,你可以创建一个像这样的变量: PATH_TEST = ~/SomeDirectory test -d $(PATH_TEST) && something



16
投票
Makefile

最顶层,其中上述方法不起作用。我发现

here
一个很好的解决方案,可以像这样使用: MY_DIRNAME=../External ifneq "$(wildcard $(MY_DIRNAME) )" "" # if directory MY_DIRNAME exists: INCLUDES += -I../External else # if it doesn't: INCLUDES += -I$(HOME)/Code/External endif

这将根据
INCLUDES

中存储的目录是否存在来修改变量

MY_DIRNAME

(动机:在我的例子中,这个变量将被用在另一个

Makefile

中,稍后由第一个:


include $(SFRAME_DIR)/Makefile.common

我想以简单的方式在两个不同的环境中实现相同的
Makefile

工作。)

    


5
投票
if

语句:


.ONESHELL: foo.bak: foo.bar echo "foo" if [ -d "~/Dropbox" ]; then echo "Dir exists" fi

请注意,唯一的区别是 ONESHELL 
特殊目标


1
投票

$(if $(filter expected,$(wildcard *)), the expected file exists)

根据您的要求:

.PHONY: ~/Dropbox ~/Dropbox: echo "Dir exists" foo.bak: foo.bar | $(if $(filter ~/Dropbox,$(wildcard ~/*)), the expected file exists)

可以进一步简化:

foo.bak: foo.bar | $(wildcard ~/Dropbox)



0
投票

ifeq ($(shell test -d MYDIR && echo 1 || echo 0), 1) ... endif

© www.soinside.com 2019 - 2024. All rights reserved.