测试makefile中是否存在目录

时间:2013-12-24 16:02:11

标签: bash makefile

在他的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中是否存在目录?

7 个答案:

答案 0 :(得分:54)

如果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

答案 1 :(得分:38)

这种方法以最小的回声起作用:

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

答案 2 :(得分:15)

在缺少目录的情况下采取行动

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

directory = ~/Dropbox

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

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

.PHONY: all

说明:

  • |表示make不应该关心时间戳(它是order-only-prerequisite)。
  • 您可以编写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语句慢。但是,第三种情况可能非常罕见,只是为了完整性而添加。

答案 3 :(得分:10)

试试这个:

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

仅当something存在时,才会执行Documents下的命令。

为了解决评论中提到的problem,你可以制作一个这样的变量:

PATH_TEST = ~/SomeDirectory

test -d $(PATH_TEST) && something

答案 4 :(得分:8)

我有一个案例,我希望根据测试来定义一个变量是否存在目录是否存在于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 :(得分:1)

有一个非常不同的答案,允许您在一个shell中设想它们时使用if语句:

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

请注意,唯一的区别是ONESHELL special target

答案 6 :(得分:0)

我使用以下命令检测文件或目录是否存在并对其进行操作:

$(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)