2012-06-18 15 views
5

यदि कुछ पूर्व शर्त पूरी नहीं हुई हैं तो मैं अपनी मेक प्रक्रिया को रद्द करने के लिए $(error ...) का उपयोग करना चाहता हूं। test -d /foobar विफल होने पर लक्ष्य निरस्त होना चाहिए।

BAD.mk

all: this_works fails_to_work 

this_works: 
     @echo echo works... 
     @test -d ~ || echo ~ is not a directory 
     @test -d /foobar || echo /foobar is not a directory 

fails_to_work: 
     @echo error does not work... 
     @test -d ~ || $(error ~ is not a directory) 
     @test -d /foobar || $(error /foobar is not a directory) 

$ बनाने BAD.mk

echo works... 
/foobar is not a directory 
BAD.mk:9: *** ~ is not a directory. Stop. 

-f आप देख सकते हैं, यहां तक ​​कि नहीं "त्रुटि काम नहीं करता है ..." स्क्रीन पर गूँजती है। fails_to_work के लिए नुस्खा शुरू होने से पहले विफल रहता है। मैं इसे कैसे हल करूं? मेरे उपयोग मामलों में से एक @test -d $(MY_ENV_VAR) है, लेकिन मुझे नहीं लगता कि उदाहरण में दिए गए हार्ड-कोड किए गए पथ से अलग है।

अद्यतन (संस्करण जानकारी)

$ बनाने --version

GNU Make 3.81 
Copyright (C) 2006 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. 
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE. 

This program built for x86_64-pc-linux-gnu 

उत्तर

5

आप एक नुस्खा में खोल सामान पाने के लिए सशर्त makefile सामान आह्वान करने के लिए है, जो काम नहीं करता है कोशिश कर रहे हैं जैसा कि आपने पाया है।

मैं दो विकल्प के बारे में सोच सकते हैं:

  1. सीधे शब्दों में $(error) सामान को हटा दें। यदि test विफल रहता है, तो यह एक गैर-शून्य निकास स्थिति वापस कर देगा, और उस बिंदु पर मेक प्रक्रिया समाप्त हो जाएगी।

  2. शासन से बाहर परीक्षण ले लो, और एक सशर्त करें (जो बारी में खोल कार्यक्षमता का आह्वान), का उपयोग उदाहरण के लिए:

    ifeq ($(shell test -d /foobar; echo $$?),1) 
    $(error Not a directory) 
    endif 
    
+0

धन्यवाद। आपका पहला सुझाव काम करता है (जिसे मैं इस तरह अपना रहा हूं: 'if! Test -d/foobar; फिर गूंजें "/ foobar निर्देशिका नहीं है"; बाहर निकलें 1; fi'), लेकिन आपका दूसरा नहीं है। एक वैध निर्देशिका के साथ, त्रुटि अभी भी हिट है। –

0

आप क्यों नहीं बस exit 1 शेल कमांड के बजाय का उपयोग नहीं करते $(error ...) का? क्या उत्तरार्द्ध का उपयोग करने का कोई कारण है?

try_this: 
    @test -d /foobar || { echo /foobar is not a directory; exit 1; } 

or_this: 
    @if [ ! -d /foobar ]; then echo /foobar is not a directory; exit 1; fi 

इन दोनों मेकअप प्रक्रिया को निरस्त कर देगा जब तक कि -k flag निर्दिष्ट किया जाता है।

-k --keep-going

एक त्रुटि के बाद जितना संभव हो उतना जारी रखें। जबकि लक्ष्य जो असफल रहा, और जो लोग इस पर निर्भर हैं, उन्हें पुनर्निर्मित नहीं किया जा सकता है, इन लक्ष्यों की अन्य आवश्यकताओं को भी संसाधित किया जा सकता है।

+0

मैं गलत धारणा के तहत विंडोज सेमीड शैल/sh पोर्टेबिलिटी के लिए शूटिंग कर रहा था कि 'test -d' दोनों में उपलब्ध था। हालांकि, मैं अभी भी सशर्त रूप से $ (त्रुटि ...) का आह्वान करने के सही तरीके से रूचि रखता हूं। –

5

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

ध्यान दें कि $(if ...) या $(or ...) & सी की अन्तर्निहित शाखा। विस्तारित नहीं किया जाएगा।इस प्रकार, तुम कर सकते हो

.PHONY: rule-with-assert 
rule-with-assert: 
    $(if $(realpath ${should-be-file}/),$(error Assertion failure: ${should-be-file} is a folder!)) 
    ⋮ 

ध्यान दें कि realpath में / अनुगामी।

बेशक मैक्रोज़ इसे बहुत साफ करने में मदद करते हैं।

assert-is-file = $(if $(realpath $1/),$(error Assertion failure: [$1] is a folder!)) 

.PHONY: rule-with-assert 
rule-with-assert: 
    $(call assert-is-file,${should-be-file}) 
    ⋮ 

यह फिर से ध्यान देने योग्य बात यह है कि यह कोई फर्क नहीं पड़ता है जहाँ आप नुस्खा में $(call assert-is-file,…) डाल लायक है। कोई भी $(error) तैयार किया जाएगा क्योंकि नुस्खा का विस्तार किया गया है, से पहले कोई भी खोल आदेश चलाए जाते हैं।