mkdir का उपयोग करते समय मेकफाइल में "निर्देशिका पहले से ही मौजूद त्रुटि" को कैसे रोकें


109

मुझे अपने मेकफाइल में एक डायरेक्टरी जेनरेट करनी होगी और मैं चाहूंगा कि "डाइरेक्टरी पहले से ही मौजूद है" और फिर भी मैं इसे आसानी से इग्नोर कर पाऊं।

मैं मुख्य रूप से mingw / msys का उपयोग करता हूं, लेकिन ऐसा कुछ करना चाहता हूं जो अन्य गोले / सिस्टम पर भी काम करता हो।

मैंने यह कोशिश की, लेकिन यह काम नहीं किया, कोई विचार?

ifeq (,$(findstring $(OBJDIR),$(wildcard $(OBJDIR) )))
-mkdir $(OBJDIR)
endif

जवाबों:


106

UNIX पर बस इसका उपयोग करें:

mkdir -p $(OBJDIR)

यदि निर्देशिका मौजूद है, तो mkdir के लिए -p विकल्प त्रुटि संदेश को रोकता है।


39
"आम तौर पर, इन कार्यक्रमों के व्यापक रूप से समर्थित (आमतौर पर पॉज़िक्स-निर्दिष्ट) विकल्पों और सुविधाओं के लिए छड़ी। उदाहरण के लिए, 'mkdir -p' का उपयोग न करें, यह सुविधाजनक हो सकता है, क्योंकि कुछ सिस्टम इसका समर्थन नहीं करते हैं। सभी के साथ और अन्य लोगों के लिए, यह समानांतर निष्पादन के लिए सुरक्षित नहीं है। " gnu.org/s/hello/manual/make/Utilities-in-Makefiles.html
greg.kindel

8
-pविंडोज पर काम नहीं करता है, जो संभवतः वह सवाल है जिसके बारे में पूछ रहा है। यकीन नहीं होता कि यह कभी कैसे स्वीकार हो गया।
एंटीमनी

2
विंडोज के लिए, इसे वोट दें: connect.microsoft.com/PowerShell/feedback/details/1074131/…
vulcan raven

1
यदि आप GNU मेकग मिन के बाहर मेक यूज कर रहे हैं तो @Antimony आपने शायद कुछ गलत किया है। आपकी पसंद, हालांकि।
yyny

"यूनिक्स पर बस यह प्रयोग करें ..." - make -pयूनिक्स या लिनक्स है?
jww

122

आधिकारिक दस्तावेज बनाने को देखते हुए , यह करने का एक अच्छा तरीका है:

OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)

$(OBJDIR)/%.o : %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<

all: $(OBJS)

$(OBJS): | $(OBJDIR)

$(OBJDIR):
    mkdir -p $(OBJDIR)

आपको यहाँ का उपयोग देखना चाहिए | पाइप ऑपरेटर, केवल एक शर्त को परिभाषित करते हुए। मतलब यह है कि वर्तमान लक्ष्य को बनाने के लिए लक्ष्य का $(OBJDIR)अस्तित्व ( हाल के बजाय ) होना चाहिए ।

ध्यान दें कि मैंने इस्तेमाल किया mkdir -p-pझंडा किए गए दस्तावेज़ों की उदाहरण की तुलना में जोड़ा गया है। अन्य विकल्प के लिए अन्य उत्तर देखें।


4
यह निश्चित रूप से इस समस्या का आधिकारिक तरीका है।
20

@ क्रेगमक्यूक्यूएन: मेरा वास्तव में मतलब था " $(OBJDIR)लक्ष्य अस्तित्व में होना चाहिए " । फ़ाइल उपस्थिति (और टाइमस्टैम्प) के लिए जाँच करें कि क्या उसे लक्ष्य बनाने की आवश्यकता है। इसलिए यहाँ, यदि $(OBJDIR)अनुपस्थित है तो इसे बनाएगा, ताकि यह मौजूदा लक्ष्य के निर्माण के लिए विद्यमान हो $(OBJS), जो अंदर बनाया जाएगा।
इवेरे

मुझे लगता है कि मैंने इसे खोजने से पहले इस समस्या को हल करने के हर दूसरे संयोजन की कोशिश की है (मैं उन मेकफाइल्स को उत्पन्न करने की कोशिश कर रहा हूं जो उतने ही सामान्य हैं जितने मैं विंडोज़ / लिनक्स के बीच हो सकता है) - यह बहुत ही एकमात्र है जिसे मैं काम कर सकता हूं, लेकिन यह इतनी अच्छी तरह से काम करता है! :)
code_fodder

67

आप परीक्षण कमांड का उपयोग कर सकते हैं:

test -d $(OBJDIR) || mkdir $(OBJDIR)

7
यह पसंदीदा तरीका है यदि आपको विंडोज़ (gnuwin32 और PowerShell) और POSIX-compliant OS दोनों के साथ काम करने के लिए अपने मेकफाइल्स की आवश्यकता है।
क्रि हार्डी

6
प्रदान की है कि आप 'परीक्षण' उपयोगिता प्रदान करने के लिए gnuwin32 CoreUtils पैकेज है।
davenpcj

2
यहाँ देर से रास्ता है, लेकिन मैं यह बताना चाहूंगा कि make -jजब निर्देशिका को अस्तित्व के लिए परीक्षण किया जाता है और इसे बनाया जाता है, तो रेस की स्थिति के कारण समानांतर ( ) में निर्माण होने पर यह समाधान टूट सकता है। एक काम यह परीक्षण कर सकता है कि यह वहां नहीं है, लेकिन इसे बनाने से पहले, दूसरी नौकरी निर्देशिका बनाती है। फिर जब पहला इसे बनाने की कोशिश करता है, तो यह विफल हो जाएगा क्योंकि निर्देशिका पहले से मौजूद है। इस मामले में सबसे अच्छा समाधान केवल आदेशों का उपयोग करना है जैसा कि @ TeKa के उत्तर (जो स्वीकृत उत्तर होना चाहिए) में उल्लिखित है।
C0deH4cker

@MarcusJ मेरे OS X El Capitan पर काम करता है। किस संस्करण ने इसे तोड़ दिया?
फ्रैंकलिन यू

@ C0deH4cker - मेरी अज्ञानता को क्षमा करें ... कौन सा जवाब तीखा है? मुझे लगता है कि TeKa ने टिप्पणी करने के बाद से अपना नाम बदल लिया।
jww

18

यहाँ एक ट्रिक है जिसका उपयोग मैं GNU मे कंपाइलर-आउटपुट डायरेक्टरी बनाने के लिए करता हूँ। पहले इस नियम को परिभाषित करें:

  %/.d:
          mkdir -p $(@D)
          touch $@

फिर उस निर्देशिका में .d फ़ाइल पर निर्भर निर्देशिका में जाने वाली सभी फ़ाइलें बनाएँ:

 obj/%.o: %.c obj/.d
    $(CC) $(CFLAGS) -c -o $@ $<

$ ^ के बजाय $ <का उपयोग नोट करें।

अंत में .d फ़ाइलों को अपने आप हटाने से रोकें:

 .PRECIOUS: %/.d

.D फ़ाइल को छोड़ना, और निर्देशिका पर सीधे निर्भर रहना, काम नहीं करेगा, क्योंकि निर्देशिका संशोधन समय को हर बार उस निर्देशिका में एक फ़ाइल के लिखे जाने पर अद्यतन किया जाता है, जो मेक के हर आह्वान पर पुनर्निर्माण को मजबूर करता है।


1
आह, धन्यवाद, मैं काम करने के लिए इस तरह से कुछ पाने की कोशिश कर रहा था। मैं कई परीक्षणों पर "परीक्षण -d फू || mkdir फू" नहीं चाहता, तब से "मेक -j2" का उपयोग करके उन्हें एक ही समय में परीक्षण किया जाएगा, दोनों परीक्षण झूठे दे रहे हैं, और फिर दो प्रक्रिया mkdir करने की कोशिश करेंगे, उनमें से अंतिम असफल रहा।
अनहैमर

13

यदि निर्देशिका पहले से मौजूद है, तो आपके लिए कोई समस्या नहीं है, तो आप उस आदेश के लिए केवल पुनर्निर्देशित कर सकते हैं, त्रुटि से छुटकारा पा सकते हैं:

-mkdir $(OBJDIR) 2>/dev/null

यह विंडोज पर काम करने का भी फायदा है। आदेश के सामने '-' मत भूलना ताकि जमानत न हो।
माइकल बूर

11

अपने मेकअप के अंदर:

target:
    if test -d dir; then echo "hello world!"; else mkdir dir; fi

10

विंडोज पर

if not exist "$(OBJDIR)" mkdir $(OBJDIR)

यूनिक्स पर | लिनक्स

if [ ! -d "$(OBJDIR)" ]; then mkdir $(OBJDIR); fi

विंडोज के लिए यह एक।
चेकसम

/bin/sh: 1: Syntax error: end of file unexpected (expecting "then")
वोतानी

पहला संस्करण विंडोज के लिए है, दूसरा विकल्प लिनक्स पर काम करता है क्योंकि @checksum ने कहा
लील

पहला, विंडोज, संस्करण परमाणु नहीं है इसलिए यह तब काम नहीं करता है जब कोई अन्य प्रक्रिया (उदाहरण के लिए समानांतर मोड में एक नियम) "अस्तित्व में नहीं" और "mkdir" के बीच निर्देशिका बनाता है।
पेट्र वेपेक

7
ifeq "$(wildcard $(MY_DIRNAME) )" ""
  -mkdir $(MY_DIRNAME)
endif

यह अतिरिक्त उपकरणों की आवश्यकता के बिना मिंगव के मेक के लिए अच्छी तरह से काम करता है।
davenpcj

6
$(OBJDIR):
    mkdir $@

जो कई डायरेक्टरी के लिए भी काम करता है, जैसे।

OBJDIRS := $(sort $(dir $(OBJECTS)))

$(OBJDIRS):
    mkdir $@

$(OBJDIR)पहले लक्ष्य के रूप में जोड़ना अच्छी तरह से काम करता है।


3

यह mingw32 / msys / cygwin / linux के तहत काम करता है

ifeq "$(wildcard .dep)" ""
-include $(shell mkdir .dep) $(wildcard .dep/*)
endif

0

यदि आप स्पष्ट रूप से रिटर्न कोड को नजरअंदाज करते हैं और त्रुटि स्ट्रीम को डंप करते हैं तो आपका मेक उस त्रुटि को नजरअंदाज करेगा यदि ऐसा होता है:

mkdir 2>/dev/null || true

यह एक समानांतर मेक में दौड़ के खतरे का कारण नहीं होना चाहिए - लेकिन मैंने इसे सुनिश्चित करने के लिए परीक्षण नहीं किया है।


0

लार्स के उत्तर की तुलना में थोड़ा सरल:

something_needs_directory_xxx : xxx/..

और सामान्य नियम:

%/.. : ;@mkdir -p $(@D)

कोई स्पर्श-फ़ाइलें साफ करने या बनाने के लिए .PRECIOUS :-)

यदि आप एक और छोटी जेमरिक ट्रिक देखना चाहते हैं, या यदि आप कम से कम मचान के साथ गैर-पुनरावर्ती मेक में रुचि रखते हैं, तो आप दो और सस्ते gmake ट्रिक्स और उस ब्लॉग में अन्य संबंधित पोस्ट की जांच कर सकते हैं ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.