首页 文章

当mkdir -p不可用时,如何在makefile中创建目录?

提问于
浏览
8

我有一个makefile,它通常创建目录:

$(Release_target_OBJDIR)/%.o: %.cpp
     mkdir -p $(dir $@)
     $(COMPILE.cpp) $< $(CFLAGS) $(INCLUDES) -o $@

不幸的是,当我在scratchbox2下运行它时,mkdir -p命令总是无声地失败 .

我尝试了以下无效的kludge:

$(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在scratchbox2下不起作用?

EDIT

根据bobbogo的建议,我把它放在一起 . 它看起来相当复杂,但似乎工作,即使在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 $@

3 回答

  • 4

    您可以用以下内容替换 mkdir 的森林:

    $(Release_target_OBJDIR)/%.o: %.cpp
        $(foreach d,$(subst /, ,${@D}),mkdir $d && cd $d && ):
        ∶
    

    这将创建一个shell命令somethng,如下所示:

    mkdir projects && cd projects && mkdir htc && cd htc && mkdir arm && cd arm && :
    

    这适用于每个编译 . 不是很优雅 . 您可以使用某种sentinel文件来优化它 . 例如:

    $(Release_target_OBJDIR)/%.o: %.cpp ${Release_target_OBJDIR}/.sentinel
        ∶
    
    %/.sentinel:
        $(foreach d,$(subst /, ,$*),mkdir $d && cd $d && ):
        touch $@
    

    .sentinel 在所有对象之前创建一次,并且 make -j 友好 . 事实上你应该这样做,即使 mkdir -p 适合你(在这种情况下你会使用 mkdir -p 而不是 $(foreach) hacksolution) .

  • -2

    您可以使用 - 告诉 make 忽略命令中的任何失败返回码:

    $(Release_target_OBJDIR)/%.o: %.cpp
        -mkdir $(dir $(dir $(dir $@)))
        -mkdir $(dir $(dir $@))
        -mkdir $(dir $@)
        $(COMPILE.cpp) $< $(CFLAGS) $(INCLUDES) -o $@
    

    (请注意,这不会解决尾部斜杠问题 . )

  • 2

    有一种更简单的方法 . 你可以在shell函数中调用mkdir,如下所示:

    foobar:
            $(shell mkdir -p mydirectoryname)
    

    gnu中的 shell 函数在单词 shell 作为shell命令后执行命令 .

相关问题