当 mkdir -p 不可用时如何在 makefile 中创建目录?
我有一个 makefile,它执行通常的目录创建:
$(Release_target_OBJDIR)/%.o: %.cpp
mkdir -p $(dir $@)
$(COMPILE.cpp) $< $(CFLAGS) $(INCLUDES) -o $@
不幸的是,当我在 scrapbox2 下运行它时, mkdir -p 命令总是默默地失败。
我尝试了以下不起作用的组装:
$(Release_target_OBJDIR)/%.o: %.cpp
mkdir $(dir $(dir $(dir $@)))
mkdir $(dir $(dir $@))
mkdir $(dir $@)
$(COMPILE.cpp) $< $(CFLAGS) $(INCLUDES) -o $@
此输出:
mkdir -p /home/foo/projects/htc/arm/obj/cbar/release/
mkdir -p /home/foo/projects/htc/arm/obj/cbar/release/
mkdir -p /home/foo/projects/htc/arm/obj/cbar/release/
...尾部斜杠阻止 dir 函数以我想要的方式剥离最后一个目录。
如果没有编写脚本或小型 C 应用程序来复制“-p”功能,是否有人有任何在 makefile 中创建子目录的想法?
如果没有 -p 选项,当 makefile 尝试创建已存在的目录时,mkdir 将给出错误。我可以做 mkdir blah 2> /dev/null 但我可能会丢失其他错误消息。
有谁知道为什么 mkdir -p 在 scrapbox2 下不起作用?
编辑
根据bobbogo的建议,我将其放在一起。它看起来相当复杂,但即使在 scrapbox2 下似乎也能工作。
# Generic variables for use in functions
comma:= ,
empty:=
space:= $(empty) $(empty)
# Make directory function
forlooprange = $(wordlist 1,$(words $1),1 2 3 4 5 6 7 8 9 10)
forloop = $(foreach n,$(call forlooprange,$1),$(call $2,$n,$3))
mkdirfunc0 = test -d $1 || mkdir $1;
mkdirfunc1 = $(call mkdirfunc0,/$(subst $(space),/,$(foreach n,$(wordlist 1,$1,$2),$n)))
mkdirfunc2 = $(call forloop,$1,mkdirfunc1,$1)
mkdirmain = $(call mkdirfunc2,$(subst /, ,$1))
.PRECIOUS: %/.sentinel
%/.sentinel:
$(call mkdirmain,$*)
touch $@
I have a makefile which does the usual directory creation:
$(Release_target_OBJDIR)/%.o: %.cpp
mkdir -p $(dir $@)
$(COMPILE.cpp) lt; $(CFLAGS) $(INCLUDES) -o $@
Unfortunately when I run this under scratchbox2 the mkdir -p command always fails silently.
I attempted the following kludge which doesn't work:
$(Release_target_OBJDIR)/%.o: %.cpp
mkdir $(dir $(dir $(dir $@)))
mkdir $(dir $(dir $@))
mkdir $(dir $@)
$(COMPILE.cpp) lt; $(CFLAGS) $(INCLUDES) -o $@
This outputs:
mkdir -p /home/foo/projects/htc/arm/obj/cbar/release/
mkdir -p /home/foo/projects/htc/arm/obj/cbar/release/
mkdir -p /home/foo/projects/htc/arm/obj/cbar/release/
... the trailing slash prevents the dir function from stripping the last directory in the way I wanted.
Short of writing a script or small C app to replicate the "-p" functionality, does anyone have any ideas for creating the subdirectories within the makefile?
Without the -p option mkdir will give an error when the makefile tries to create a directory which already exists. I can do mkdir blah 2> /dev/null but then I risk losing other error messages.
Does anyone have any thoughts as to why mkdir -p doesn't work under scratchbox2?
EDIT
Based on suggestions by bobbogo I put this together. It looks fairly convoluted, but seems to work, even under scratchbox2.
# Generic variables for use in functions
comma:= ,
empty:=
space:= $(empty) $(empty)
# Make directory function
forlooprange = $(wordlist 1,$(words $1),1 2 3 4 5 6 7 8 9 10)
forloop = $(foreach n,$(call forlooprange,$1),$(call $2,$n,$3))
mkdirfunc0 = test -d $1 || mkdir $1;
mkdirfunc1 = $(call mkdirfunc0,/$(subst $(space),/,$(foreach n,$(wordlist 1,$1,$2),$n)))
mkdirfunc2 = $(call forloop,$1,mkdirfunc1,$1)
mkdirmain = $(call mkdirfunc2,$(subst /, ,$1))
.PRECIOUS: %/.sentinel
%/.sentinel:
$(call mkdirmain,$*)
touch $@
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以用以下内容替换您的
mkdir
森林:这将创建一个类似这样的 shell 命令:
这会在每次编译时运行。不是很优雅。您可以通过使用某种哨兵文件来优化它。例如:
.sentinel
在所有对象之前创建一次,并且是make -j
友好的。事实上,即使mkdir -p
适合您,您也应该这样做(在这种情况下,您将使用mkdir -p
而不是$(foreach)
破解解决方案)。You can replace your forest of
mkdir
s with this:This will create a shell command somethng like this:
This runs for every compile. Not very elegant. You could optimise this by using some sort of sentinel file. For instance:
.sentinel
gets created once before all objects, and ismake -j
friendly. In fact you should do it this way even ifmkdir -p
works for you (in which case you would usemkdir -p
rather than the$(foreach)
hacksolution).您可以使用
-
告诉make
忽略命令中的任何失败返回代码:(请注意,这并不能解决尾部斜杠问题。)
You can tell
make
to ignore any failure return code from a command using-
:(Note that this doesn't address the trailing slash problem.)