Gnu make How to create a directory in a makefile when mkdir -p is not available

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

I have a makefile which does the usual directory creation:

$(Release_target_OBJDIR)/%.o: %.cpp
     mkdir -p $(dir $@)
     $(COMPILE.cpp) $< $(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) $< $(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   

http://stackoverflow.com/users/470195/bobbogo http://stackoverflow.com/users/470195/bobbogo

# 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 $@

Answers

You can replace your forest of mkdirs with this:

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

This will create a shell command somethng like this:

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

This runs for every compile. Not very elegant. You could optimise this by using some sort of sentinel file. For instance:

$(Release_target_OBJDIR)/%.o: %.cpp ${Release_target_OBJDIR}/.sentinel
    ∶

%/.sentinel:
    $(foreach d,$(subst /, ,$*),mkdir $d && cd $d && ):
    touch $@

.sentinel gets created once before all objects, and is make -j friendly. In fact you should do it this way even if mkdir -p works for you (in which case you would use mkdir -p rather than the $(foreach) hacksolution).

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/5193421/gnu-make-how-to-create-a-directory-in-a-makefile-when-mkdir-p-is-not-available

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils