动态创建父名称文件夹

时间:2018-09-06 07:15:45

标签: linux bash unix makefile gnu-make

我需要基于父目录创建目录

例如:

如果我有以下项目

project1
-File1
-Makefile

在make文件中,我想做以下事情

mkdir project1

然后它应该看起来像

project1
-File1
-Makefile
-project1

但是我想动态地进行操作,即mkdir parent folder,因为我们假设在生成文件中我不知道是父文件夹的名称。可能吗?它应该是带有父文件夹名称的空文件夹。

作为前提条件,它应该始终具有一个父文件夹

我尝试了以下建议:

更新

all: build

build:
    mkdir $(basename "$PWD")

这创建了以下内容:

project1
-File1
-Makefile
-WD

此操作在根目录下创建了一个文件夹,可以,但名称为WD,这是错误的,应该为project1

1 个答案:

答案 0 :(得分:2)

我认为:

  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时才起作用。即使从其他地方调用了make,获取Makefile绝对路径的正确方法是$(abspath $(lastword $(MAKEFILE_LIST)))。请记住将其放在任何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/project1make -Cmake -f以外的任何地方调用make,则DIRBASEDIRNAME变量将扩展为:

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