测试makefile中是否存在目录

Dro*_*ror 51 bash makefile

在他的回答中, @ Grundlefleck解释了如何检查目录是否存在.我尝试了一些在内部使用这个makefile如下:

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then
        echo "Dir exists"
    fi
Run Code Online (Sandbox Code Playgroud)

运行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
Run Code Online (Sandbox Code Playgroud)

我做的解决方法是有一个独立的bash脚本,其中实现了测试,我从中调用了脚本makefile.然而,这听起来非常麻烦.有没有更好的方法来检查目录是否存在makefile

lur*_*ker 61

如果shell命令必须在一行中,或者在使用反斜杠进行行扩展的多行上,则创建命令.所以,这种方法将起作用:

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then echo "Dir exists"; fi
Run Code Online (Sandbox Code Playgroud)

要么

foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then \
        echo "Dir exists"; \
    fi
Run Code Online (Sandbox Code Playgroud)


cfo*_*ish 40

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

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

  • `$(通配符〜/ Dropbox /.)就够了.在此用例中不需要通配符 (4认同)

Ann*_*sum 23

在没有目录的情况下采取行动

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

directory = ~/Dropbox

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

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

.PHONY: all
Run Code Online (Sandbox Code Playgroud)

备注:

  • |指示,使不应该关心的时间戳(这是一个订单只-的先决条件).
  • mkdir -p $@您可以写入false退出,或以不同方式解决您的案例,而不是写作.

如果您还需要在存在目录时运行特定系列的指令,则不能使用上述指令.换句话说,它相当于:

if [ ! -d "~/Dropbox" ]; then
    echo "The ~/Dropbox folder does not exist"
fi
Run Code Online (Sandbox Code Playgroud)

没有else声明.

根据目录的存在行事

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

directory = $(wildcard ~/Dropbox)

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

$(directory):
    @echo "Folder $(directory) exists"

.PHONY: all $(directory)
Run Code Online (Sandbox Code Playgroud)

这相当于:

if [ -d "~/Dropbox" ]; then
    echo "The ~/Dropbox folder does exist"
fi
Run Code Online (Sandbox Code Playgroud)

同样,没有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
Run Code Online (Sandbox Code Playgroud)

这相当于:

if [ -d "~/Dropbox" ]; then
    echo "The ~/Dropbox folder does exist"
else
    echo "The ~/Dropbox folder does not exist"
fi
Run Code Online (Sandbox Code Playgroud)

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


小智 11

试试这个:

.PHONY: all
something:
    echo "hi"
all:
    test -d "Documents" && something
Run Code Online (Sandbox Code Playgroud)

这将something仅在Documents存在时执行命令.

为了解决注释中提到的问题,您可以创建一个这样的变量:

PATH_TEST = ~/SomeDirectory

test -d $(PATH_TEST) && something
Run Code Online (Sandbox Code Playgroud)


fue*_*zig 10

我有,我想在一个目录是否存在与否来定义基于测试变量的情况下,最顶层Makefile,其中上述方法不起作用.我在这里找到一个很好的解决方案,可以像这样使用:

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
Run Code Online (Sandbox Code Playgroud)

这将INCLUDES根据存储的目录是否MY_DIRNAME存在来修改变量.

(动机:在我的情况下,这个变量将用于Makefile后面的第一个变量:

include $(SFRAME_DIR)/Makefile.common
Run Code Online (Sandbox Code Playgroud)

我希望以Makefile简单的方式在两个不同的环境中完成相同的工作.)


Ann*_*sum 5

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

.ONESHELL:
foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then
        echo "Dir exists"
    fi
Run Code Online (Sandbox Code Playgroud)

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