如何在 Makefile 中自动创建(和删除)临时目录?

发布于 2024-07-13 19:27:32 字数 167 浏览 4 评论 0原文

是否可以让 make 在执行第一个目标之前创建一个临时目录? 也许使用一些黑客,一些额外的目标等?

Makefile 中的所有命令都可以引用自动创建的目录 $TMPDIR,并且当 make 命令结束时该目录将自动删除。

Is it possible to have make create a temp directory before it executes the first target? Maybe using some hack, some additional target etc.?

All commands in the Makefile would be able to refer to the automatically created directory as $TMPDIR, and the directory would be automatically removed when the make command ends.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

黑白记忆 2024-07-20 19:27:33

我似乎记得能够递归地调用 make ,大致如下:

all:
    -mkdir $(TEMPDIR)
    $(MAKE) $(MFLAGS) old_all
    -rm -rf $(TEMPDIR)

old_all: ... rest of stuff.

我已经完成了在子目录中调用 make 的类似技巧:

all:
    @for i in $(SUBDIRS); do \
        echo "make all in $i..."; \
        (cd $i; $(MAKE) $(MFLAGS) all); \
    done

刚刚检查了一下,效果很好:

$ cat Makefile
all:
    -mkdir tempdir
    -echo hello >tempdir/hello
    -echo goodbye >tempdir/goodbye
    $(MAKE) $(MFLAGS) old_all
    -rm -rf tempdir

old_all:
    ls -al tempdir

$ make all
mkdir tempdir
echo hello >tempdir/hello
echo goodbye >tempdir/goodbye
make  old_all
make[1]: Entering directory '/home/pax'
ls -al tempdir
total 2
drwxr-xr-x+ 2 allachan None 0 Feb 26 15:00 .
drwxrwxrwx+ 4 allachan None 0 Feb 26 15:00 ..
-rw-r--r--  1 allachan None 8 Feb 26 15:00 goodbye
-rw-r--r--  1 allachan None 6 Feb 26 15:00 hello
make[1]: Leaving directory '/home/pax'
rm -rf tempdir

$ ls -al tempdir
ls: cannot access tempdir: No such file or directory

I seem to recall being able to call make recursively, something along the lines of:

all:
    -mkdir $(TEMPDIR)
    $(MAKE) $(MFLAGS) old_all
    -rm -rf $(TEMPDIR)

old_all: ... rest of stuff.

I've done similar tricks for calling make in subdirectories:

all:
    @for i in $(SUBDIRS); do \
        echo "make all in $i..."; \
        (cd $i; $(MAKE) $(MFLAGS) all); \
    done

Just checked it and this works fine:

$ cat Makefile
all:
    -mkdir tempdir
    -echo hello >tempdir/hello
    -echo goodbye >tempdir/goodbye
    $(MAKE) $(MFLAGS) old_all
    -rm -rf tempdir

old_all:
    ls -al tempdir

$ make all
mkdir tempdir
echo hello >tempdir/hello
echo goodbye >tempdir/goodbye
make  old_all
make[1]: Entering directory '/home/pax'
ls -al tempdir
total 2
drwxr-xr-x+ 2 allachan None 0 Feb 26 15:00 .
drwxrwxrwx+ 4 allachan None 0 Feb 26 15:00 ..
-rw-r--r--  1 allachan None 8 Feb 26 15:00 goodbye
-rw-r--r--  1 allachan None 6 Feb 26 15:00 hello
make[1]: Leaving directory '/home/pax'
rm -rf tempdir

$ ls -al tempdir
ls: cannot access tempdir: No such file or directory
懵少女 2024-07-20 19:27:33

将其放在 Makefile 的顶部

SHELL := /bin/bash
export TMPDIR:=$(shell mktemp -d ./.make-tmp_XXXXXXXX)
$(info Launching clean up task for ${TMPDIR})
$(shell { trap 'rm -rf ${TMPDIR};' EXIT; tail --pid=$PPID -f /dev/null; } \
           </dev/null >/dev/null 2>/dev/null &)

make 进程使用 shell 的父 PID ($PPID) 完成时,就会发生清理。 使用trap设置,当make未正确完成或被中断时也会发生清理。

我按以下方式在 ifeq 中使用它:

SHELL := /bin/bash
ifdef MAKELEVEL
    ifeq "${MAKELEVEL}" "0"
        export TD:=$(shell mktemp -d ./.make-tmp_XXXXXXXX)
        $(info Launching clean up task for ${TD})
        $(shell { trap 'rm -rf ${TD};' EXIT; tail --pid=$PPID -f /dev/null; } \
           </dev/null >/dev/null 2>/dev/null &)
    endif
endif

这确保只有顶级 make 才会创建该目录,并且子 make 可以使用同一目录。 因此导出

可能仅适用于以 bash 作为 shell 的 Linux,因此 SHELL := /bin/bash

希望有帮助。

Put this at the top of your Makefile

SHELL := /bin/bash
export TMPDIR:=$(shell mktemp -d ./.make-tmp_XXXXXXXX)
$(info Launching clean up task for ${TMPDIR})
$(shell { trap 'rm -rf ${TMPDIR};' EXIT; tail --pid=$PPID -f /dev/null; } \
           </dev/null >/dev/null 2>/dev/null &)

The cleanup happens when the make-process finishes using the parent PID ($PPID) of the shell. Using the trap-setup the cleanup happens also when make does not finish properly or is interrupted.

I use this inclosed in an ifeq in the following way:

SHELL := /bin/bash
ifdef MAKELEVEL
    ifeq "${MAKELEVEL}" "0"
        export TD:=$(shell mktemp -d ./.make-tmp_XXXXXXXX)
        $(info Launching clean up task for ${TD})
        $(shell { trap 'rm -rf ${TD};' EXIT; tail --pid=$PPID -f /dev/null; } \
           </dev/null >/dev/null 2>/dev/null &)
    endif
endif

This ensures that only the top-level make will create the directory and the sub-makes can then use the same directory. Thus the export.

Likely only works on linux with bash as the shell, thus the SHELL := /bin/bash.

Hope that helps.

2024-07-20 19:27:32

以前的这些答案要么不起作用,要么看起来过于复杂。 这是我能想到的一个更直接的例子:

PACKAGE := "audit"
all:
    $(eval TMP := $(shell mktemp -d))
    @mkdir $(TMP)/$(PACKAGE)
    rm -rf $(TMP)

These previous answers either didn't work or seemed overly complicated. Here is a far more straight forward example I was able to figure out:

PACKAGE := "audit"
all:
    $(eval TMP := $(shell mktemp -d))
    @mkdir $(TMP)/$(PACKAGE)
    rm -rf $(TMP)
以酷 2024-07-20 19:27:32

至少使用 GNU make

TMPDIR := $(shell mktemp -d)

可以获得临时目录。 除了作为 all 目标一部分的明显的 rmdir "$(TMPDIR)" 之外,我想不出一个在最后清理它的好方法。

With GNU make, at least,

TMPDIR := $(shell mktemp -d)

will get you your temporary directory. I can't come up with a good way to clean it up at the end, other than the obvious rmdir "$(TMPDIR)" as part of the all target.

魂牵梦绕锁你心扉 2024-07-20 19:27:32

请参阅 从 makefile 获取 makefile 的名称$(self) 技巧

ifeq ($(tmpdir),)

location = $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
self := $(location)

%:
    @tmpdir=`mktemp --tmpdir -d`; \
    trap 'rm -rf "$tmpdir"' EXIT; \
    $(MAKE) -f $(self) --no-print-directory tmpdir=$tmpdir $@

else
# [your real Makefile]
%:
    @echo Running target $@ with $(tmpdir)
endif

See Getting the name of the makefile from the makefile for the $(self) trick

ifeq ($(tmpdir),)

location = $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
self := $(location)

%:
    @tmpdir=`mktemp --tmpdir -d`; \
    trap 'rm -rf "$tmpdir"' EXIT; \
    $(MAKE) -f $(self) --no-print-directory tmpdir=$tmpdir $@

else
# [your real Makefile]
%:
    @echo Running target $@ with $(tmpdir)
endif
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文