help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: how to make dirs without races


From: Mark Galeck
Subject: Re: how to make dirs without races
Date: Mon, 4 Mar 2013 19:35:37 -0800 (PST)

Well,  implicit chain does not work because of what Paul says in the manual:

"No single implicit rule can appear more than once in a chain. This means 
that make will not even consider such a ridiculous thing as 
making foo from foo.o.o by running the linker twice. This constraint has the 
added benefit of preventing any infinite loop in the search for an implicit 
rule 


chain"

I think I disagree with this.  I would want a convenient implicit rule that 
would make a directory (recognized by trailing /.) depend on the parent, 
knowing 


that the chain will eventually have to end with an existing directory.  

I need to depend on the parent, because if I don't, mkdir -p has a side effect, 
which violates Paul's rules of makefiles, and for a good reason - that creates 
a 


race condition.


In the absence of that, I have to go explicit.  It is probably faster, OK, but 
I 

better hide this from the developers, for they will scream in horror.  The user 
calls the function 


$(call MAKE_DIR,<directory>)


If anybody knows how to do this (make any directory, without race conditions, 
possibly with irregular strings such as foo/../bar, and without any make 
warnings about duplicate rules) easier than the below, please show me.  



########################################
# make dir $(1) without race conditions
#
# you can just 
# $(call MAKE_DIR,<directory>)
#
# for convenience, this is redirected to MAKE_DIR_F
########################################
MAKE_DIR = $(eval $(call MAKE_DIR_F,$(1)))
 
define MAKE_DIR_F
 
# get rid of irregularities in $(1) such as ..
MAKE_DIR_CANON := $(abspath $(1))
 
# depend on that canonical version
$(1): $$(filter-out $(1),$$(MAKE_DIR_CANON))
 
# iterate from root to $1 in the function MAKE_DIR_I
# depend each directory in turn on the parent
MAKE_DIR_I_PARENT := /
$$(foreach dir,$$(subst /, ,$$(MAKE_DIR_CANON)),$$(eval $$(call 
MAKE_DIR_I,$$(dir))))
 
endef
 
 
########################################
# collect make directory targets for sorting later
########################################
MAKE_DIRS :=
 
 
########################################
# one itaration in MAKE_DIR_F
#
# add one level directory name $(1) to make the current dir global
# $(MAKE_DIR_I_CURR)
# depend that on the global parent $(MAKE_DIR_I_PARENT)
# and add that to make directory targets
########################################
define MAKE_DIR_I
 
MAKE_DIR_I_CURR := $$(MAKE_DIR_I_PARENT)$(1)
$$(MAKE_DIR_I_CURR): $$(MAKE_DIR_I_PARENT)
 
MAKE_DIRS += $$(MAKE_DIR_I_CURR)
 
# make global parent for the next iteration
MAKE_DIR_I_PARENT := $$(MAKE_DIR_I_CURR)/
 
endef
 
 
########################################
# make dirs without dup rules
########################################
$(sort $(MAKE_DIRS)):
            mkdir $@





----- Original Message ----
From: Mark Galeck (CW) <address@hidden>
To: "address@hidden" <address@hidden>


Well, OK, I tried this, but does not work deeper than 1 level of directories, I 
guess because the chain of implicit rules does not apply (or something of that 
sort)

.PRECIOUS: %/.
.SECONDEXPANSION:
%/.: $$(dir $$*).
    mkdir $* 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]