我需要基于父目录创建目录
例如:
如果我有以下项目
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
答案 0 :(得分:2)
我认为:
my favorite make file
”,则随后的操作将无效。首先,您需要获取包含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时才起作用。即使从其他地方调用了make,获取Makefile绝对路径的正确方法是$(abspath $(lastword $(MAKEFILE_LIST)))
。请记住将其放在任何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