为父名称动态创建文件夹
Create folder for the parent name dynamically
我需要根据父目录创建目录
例如:
如果我有如下项目
project1
-File1
-Makefile
在 make 文件中我想做如下的事情
mkdir project1
然后它应该看起来像
project1
-File1
-Makefile
-project1
但我想动态地进行,即 mkdir parent folder
,因为假设在 makefile 中我不知道父文件夹的名称是什么。可能吗?它应该是具有父文件夹名称的空文件夹。
作为先决条件,它应该始终有一个父文件夹
我尝试了以下建议:
更新
all: build
build:
mkdir $(basename "$PWD")
这创建了以下内容:
project1
-File1
-Makefile
-WD
这样在根目录下创建了一个文件夹,可以,但是名字是WD
,是错误的,应该是project1
我假设:
- 您正在使用 GNU make。
- 您只有“合理的”文件和目录名称,没有空格、特殊字符甚至更糟。如果您将 makefile 命名为“
my favorite make file
”,下面的内容将不起作用。
- 您想在包含 Makefile 的目录中创建子目录。
首先,您需要获取包含您的 Makefile 的目录的路径和基本名称。而这并不是那么简单。以下应该适用于所有情况,除非您将 Makefile 放在文件系统的根 /
或具有“unreasonable”文件和目录名称。把这个放在你的 Makefile 的开头,在任何 include
指令之前:
DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
BASE := $(notdir $(patsubst %/,%,$(DIR)))
DIRNAME := $(DIR)$(BASE)
抱歉,它看起来过于复杂,但所有部分都在这里是有充分理由的(详见文末)。如果你真的想让它在所有情况下都能工作,你需要它们。
接下来你需要创建没有错误的子目录,即使它已经存在:
$(DIRNAME):
mkdir -p $@
$@
,在配方中,展开为目标,即本例中的$(DIRNAME)
;强烈建议尽可能使用这些自动变量。不要忘记 -p
选项,否则如果子目录存在,配方将失败。
最后,你必须保证在你真正需要子目录之前执行命令。例如,假设您有一个 all
目标,但您希望在构建 all
目标之前存在该子目录。你可以写一个简单的依赖:
all: $(DIRNAME)
<all-recipe>
$(DIRNAME):
mkdir -p $@
但在这种情况下,每次修改子目录的内容时,您都将重建all
目标,可能毫无用处。这是 order-only prerequisites 有用的地方。它们必须存在,但 make 不考虑它们的最后修改日期。
总而言之,下面应该做你想做的:
DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
BASE := $(notdir $(patsubst %/,%,$(DIR)))
DIRNAME := $(DIR)$(BASE)
all: | $(DIRNAME)
<all-recipe>
$(DIRNAME):
mkdir -p $@
请注意 |
引入了仅订单先决条件。
关于建立你要创建的子目录名称的说明:
您可以从不同的目录调用 make:
make -C <path-to-project>
make -f <path-to-project>/Makefile
因此,$(shell basename "$$PWD")
或任何变体(例如 $(notdir $(PWD))
)仅当您从 Makefile 所在的目录调用 make 时才有效。获取 Makefile 绝对路径的正确方法是 $(abspath $(lastword $(MAKEFILE_LIST)))
,即使 make 是从其他地方调用的。请记住将它放在任何 include
指令之前。扩展结果示例:/home/john/project1/Makefile
.
$(dir <some-path>)
只保留目录部分,去掉文件部分。示例:/home/john/project1/
.
$(patsubst %/,%,<some-path>)
删除尾随 /
,如果有的话。示例:/home/john/project1
.
$(notdir <some-path>)
删除直到并包括最后一个 /
的目录部分。示例:project1
.
因此,如果您的 Makefile 是 /home/john/project1/Makefile
,即使您从 /home/john/project1
以外的任何地方使用 make -C
或 make -f
调用 make,DIR
、BASE
和 DIRNAME
变量将扩展为:
DIR: /home/john/project1/
BASE: project1
DIRNAME: /home/john/project1/project1
我需要根据父目录创建目录
例如:
如果我有如下项目
project1
-File1
-Makefile
在 make 文件中我想做如下的事情
mkdir project1
然后它应该看起来像
project1
-File1
-Makefile
-project1
但我想动态地进行,即 mkdir parent folder
,因为假设在 makefile 中我不知道父文件夹的名称是什么。可能吗?它应该是具有父文件夹名称的空文件夹。
作为先决条件,它应该始终有一个父文件夹
我尝试了以下建议:
更新
all: build
build:
mkdir $(basename "$PWD")
这创建了以下内容:
project1
-File1
-Makefile
-WD
这样在根目录下创建了一个文件夹,可以,但是名字是WD
,是错误的,应该是project1
我假设:
- 您正在使用 GNU make。
- 您只有“合理的”文件和目录名称,没有空格、特殊字符甚至更糟。如果您将 makefile 命名为“
my favorite make file
”,下面的内容将不起作用。 - 您想在包含 Makefile 的目录中创建子目录。
首先,您需要获取包含您的 Makefile 的目录的路径和基本名称。而这并不是那么简单。以下应该适用于所有情况,除非您将 Makefile 放在文件系统的根 /
或具有“unreasonable”文件和目录名称。把这个放在你的 Makefile 的开头,在任何 include
指令之前:
DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
BASE := $(notdir $(patsubst %/,%,$(DIR)))
DIRNAME := $(DIR)$(BASE)
抱歉,它看起来过于复杂,但所有部分都在这里是有充分理由的(详见文末)。如果你真的想让它在所有情况下都能工作,你需要它们。
接下来你需要创建没有错误的子目录,即使它已经存在:
$(DIRNAME):
mkdir -p $@
$@
,在配方中,展开为目标,即本例中的$(DIRNAME)
;强烈建议尽可能使用这些自动变量。不要忘记 -p
选项,否则如果子目录存在,配方将失败。
最后,你必须保证在你真正需要子目录之前执行命令。例如,假设您有一个 all
目标,但您希望在构建 all
目标之前存在该子目录。你可以写一个简单的依赖:
all: $(DIRNAME)
<all-recipe>
$(DIRNAME):
mkdir -p $@
但在这种情况下,每次修改子目录的内容时,您都将重建all
目标,可能毫无用处。这是 order-only prerequisites 有用的地方。它们必须存在,但 make 不考虑它们的最后修改日期。
总而言之,下面应该做你想做的:
DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
BASE := $(notdir $(patsubst %/,%,$(DIR)))
DIRNAME := $(DIR)$(BASE)
all: | $(DIRNAME)
<all-recipe>
$(DIRNAME):
mkdir -p $@
请注意 |
引入了仅订单先决条件。
关于建立你要创建的子目录名称的说明:
您可以从不同的目录调用 make:
make -C <path-to-project> make -f <path-to-project>/Makefile
因此,
$(shell basename "$$PWD")
或任何变体(例如$(notdir $(PWD))
)仅当您从 Makefile 所在的目录调用 make 时才有效。获取 Makefile 绝对路径的正确方法是$(abspath $(lastword $(MAKEFILE_LIST)))
,即使 make 是从其他地方调用的。请记住将它放在任何include
指令之前。扩展结果示例:/home/john/project1/Makefile
.$(dir <some-path>)
只保留目录部分,去掉文件部分。示例:/home/john/project1/
.$(patsubst %/,%,<some-path>)
删除尾随/
,如果有的话。示例:/home/john/project1
.$(notdir <some-path>)
删除直到并包括最后一个/
的目录部分。示例:project1
.
因此,如果您的 Makefile 是 /home/john/project1/Makefile
,即使您从 /home/john/project1
以外的任何地方使用 make -C
或 make -f
调用 make,DIR
、BASE
和 DIRNAME
变量将扩展为:
DIR: /home/john/project1/
BASE: project1
DIRNAME: /home/john/project1/project1