为父名称动态创建文件夹

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

我假设:

  1. 您正在使用 GNU make。
  2. 您只有“合理的”文件和目录名称,没有空格、特殊字符甚至更糟。如果您将 makefile 命名为“my favorite make file”,下面的内容将不起作用。
  3. 您想在包含 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 $@

请注意 | 引入了仅订单先决条件。

关于建立你要创建的子目录名称的说明:

  1. 您可以从不同的目录调用 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.

  2. $(dir <some-path>)只保留目录部分,去掉文件部分。示例:/home/john/project1/.

  3. $(patsubst %/,%,<some-path>) 删除尾随 /,如果有的话。示例:/home/john/project1.

  4. $(notdir <some-path>) 删除直到并包括最后一个 / 的目录部分。示例:project1.

因此,如果您的 Makefile 是 /home/john/project1/Makefile,即使您从 /home/john/project1 以外的任何地方使用 make -Cmake -f 调用 make,DIRBASEDIRNAME 变量将扩展为:

DIR: /home/john/project1/
BASE: project1
DIRNAME: /home/john/project1/project1