2011-03-04 29 views
8

Her zamanki dizin oluşturma işlemini yapan bir makefile sahibim:gnu make: mkdir -p kullanılamadığında makefile içinde bir dizin nasıl oluşturulur?

$(Release_target_OBJDIR)/%.o: %.cpp 
    mkdir -p $(dir [email protected]) 
    $(COMPILE.cpp) $< $(CFLAGS) $(INCLUDES) -o [email protected] 

Ne yazık ki bunu scratchbox2 altında çalıştırdığımda mkdir -p komutu her zaman sessizce başarısız olur.

Çalışmıyorken aşağıdaki kludayı denedim:

$(Release_target_OBJDIR)/%.o: %.cpp 
    mkdir $(dir $(dir $(dir [email protected]))) 
    mkdir $(dir $(dir [email protected])) 
    mkdir $(dir [email protected]) 
    $(COMPILE.cpp) $< $(CFLAGS) $(INCLUDES) -o [email protected] 

Bu çıktılar:

mkdir -p/home/foo/projeler/htc/arm/obj/cbar/release/
mkdir -p/home/foo/projeler/htc/arm/obj/cbar/release/
mkdir -p/home/foo/projeler/htc/arm/obj/cbar/release/

... Sondaki eğik çizgi, dir işlevinin istediğim şekilde son dizini çıkarmasını engeller.

"-p" işlevini çoğaltmak için bir komut dosyası veya küçük bir C uygulaması yazmaktan kısa bir süre, makefile içindeki alt dizinleri oluşturmak için herhangi bir fikri olan var mı?

-p seçeneği olmadan mkdir, makefile zaten var olan bir dizin oluşturmaya çalıştığında bir hata verecektir. Ben mkdir blah 2>/dev/null yapabilirim ama sonra diğer hata mesajlarını kaybetme riski.

Herkes mkdir -p'nin neden scratchbox2 altında çalışmadığı konusunda herhangi bir fikriniz var mı?

bobbogo adlı kullanıcının önerilerine dayanarak bu konuyu bir araya getirdim. Oldukça kıvrımlı görünüyor, ancak kazı-kazan2 altında bile çalışıyor gibi görünüyor.

# 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 [email protected] 

cevap

4

yapabilirsiniz mkdir s ormanınızın yerine aşağıdakileri ekleyin:

Bu böyle bir kabuk komut somethng oluşturur:

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

Bu, her derleme için çalışır. Çok zarif değil. Bir çeşit sentinel dosyası kullanarak bunu optimize edebilirsiniz.

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

%/.sentinel: 
    $(foreach d,$(subst /, ,$*),mkdir $d && cd $d &&): 
    touch [email protected] 

.sentinel tüm nesneler önce bir kez oluşturulur ve make -j dostudur alır: Örneğin. Aslında, mkdir -p sizin için çalışsa bile, bu şekilde yapmanız gerekir (bu durumda $(foreach) hack çözümünü kullanmak yerine mkdir -p kullanırsınız).

+0

Bunun için teşekkürler. Bir garip şey: Çıkış dizinini oluşturmak için, bağlantı aşamasında ve derleme aşamasında bir sentinel ekledim. Bu, (her nasılsa) make dosyası, bu sentinel'ler için bir rm komutu oluşturmak için tetiklemiştir, ancak derleme zamanı olanları değil. Göndereni oluşturmak için gönderilen kurala "dokunma" özelliğini ekledim. Kabuk komutu tam olarak doğru değil ama bir şeyler almak için bana yeterince bilgi verdin. –

+0

@Simon: Ah evet, ben 'dokunma' ekledim ben çok aptal görünmüyor. TVM. – bobbogo

+0

@Simon: ".PRECIOUS" ve ".SECONDARY" öğelerinin bazı kombinasyonlarına ihtiyacınız olabilir. Ayrıca, sentinel desen kuralını Statik Desen Kuralı'na çevirebilirsiniz (yay!). – bobbogo

0

Sen - kullanarak bir komutla gelen herhangi bir arıza dönüş kodu görmezden make söyleyebilir:

$(Release_target_OBJDIR)/%.o: %.cpp 
    -mkdir $(dir $(dir $(dir [email protected]))) 
    -mkdir $(dir $(dir [email protected])) 
    -mkdir $(dir [email protected]) 
    $(COMPILE.cpp) $< $(CFLAGS) $(INCLUDES) -o [email protected] 

(bu eğik çizgi sorunu gidermez unutmayın.)

0

Daha basit bir yol var.Böyle bir kabuk işlevi içinde mkdir arayabilirsiniz:

 
foobar: 
     $(shell mkdir -p mydirectoryname) 

gnu marka içinde shell fonksiyon kabuk komutu olarak kelimenin shell sonra komutları yürütür.

+0

Eğer mkdir -p' * mevcut değil *, neden GNU’nun '$ (shell ...)' olması gerekir? – jww