2011-12-05 20 views
10

जीएनयू/मैनुअल बनाने §5.7 जीएनयू/बनाने बनाने के लिए कहा गया है निम्नलिखित:रोक निर्देशिका के सांकेतिक लिंक de-संदर्भित

5,7 की रिकर्सिव उपयोग

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

subsystem: 
     cd subdir && $(MAKE) or, equivalently, this (see Summary of Options): 

subsystem: 
     $(MAKE) -C subdir 

तो, मूल रूप से यह संकेत मिलता है कि cd subdir && $(MAKE)$(MAKE) -C subdir के समान है।

हालांकि, यह पता चला है कि यह वास्तव में समकक्ष नहीं है। -C विकल्प का उपयोग करते समय, निर्देशिका पथ, यदि यह एक सिम्लिंक है, तो हमेशा डी-रेफरेंस किया जाता है, इसलिए "लॉजिकल" (pwd -L में) निर्देशिका नाम प्राप्त करने का कोई तरीका नहीं है। निम्नलिखित उदाहरण पर विचार करें। निम्नलिखित Makefile में /tmp/b निर्देशिका, जो /tmp/a/ निर्देशिका में एक सिमलिंक है बीत रहा है:

foo: 
    @echo PWDL=$(shell pwd -L) 
    @echo PWDP=$(shell pwd -P) 
    @echo CURDIR=$(CURDIR) 

अब, चलो make अलग ढंग से आह्वान करते हैं:

$ pwd 
/tmp 
$ (cd b && make foo) 
PWDL=/tmp/b 
PWDP=/tmp/a 
CURDIR=/tmp/a 
$ make -C b foo 
make: Entering directory `/tmp/a' 
PWDL=/tmp/a 
PWDP=/tmp/a 
CURDIR=/tmp/a 
make: Leaving directory `/tmp/a' 
$ make --directory=b foo 
make: Entering directory `/tmp/a' 
PWDL=/tmp/a 
PWDP=/tmp/a 
CURDIR=/tmp/a 
make: Leaving directory `/tmp/a' 
$ 

आप देख सकते हैं, pwd -P और $(CURDIR) हमेशा डे दिखा रहे हैं संदर्भित प्रतीकात्मक लिंक। लेकिन pwd -L केवल make चलाने से पहले निर्देशिका को बदलते समय काम करता है, जो साबित करता है कि -C विकल्प जीएनयू/विकल्प हमेशा किसी भी अच्छे कारण के लिए निर्देशिका पथ को संदर्भित नहीं करता है। मैं दस्तावेज में इस व्यवहार के लिए कोई स्पष्टीकरण खोजने की कोशिश कर रहा था लेकिन नहीं कर सका। make (या w/o बहुत खराब हुक ट्रॉफ़ LD_PRELOAD) चलाने से पहले cd का उपयोग करके निर्देशिका को बदले बिना मैं इस समस्या के लिए एक समाधान के साथ आ सकता हूं।

सवाल यह है कि - क्या कोई और इस समस्या में पहले भाग लेता है, स्पष्टीकरण या कामकाज करता है? धन्यवाद!

अद्यतन:

यह की तह तक पहुंचने की कोशिश कर रहा है, मैं make के लिए स्रोत कोड डाउनलोड किया है और निर्देशिका के किसी विशेष प्रसंस्करण नहीं मिला, केवल chdir को कहता है। इसलिए मैंने एक प्रयोग करने के लिए एक छोटा सा कार्यक्रम लिखा, और यहां मुझे जो मिला वह है।

जब आप एक सिम्लिंक निर्देशिका (/tmp/b) में होते हैं और निर्देशिका को बदलने की कोशिश करते हैं, तो ऑपरेशन का कोई प्रभाव नहीं पड़ता है और वर्तमान कार्यशील निर्देशिका प्रतीकात्मक लिंक को इंगित करती रहती है।

जब आप chdir() पर कॉल करते हैं और या तो पूर्ण या सापेक्ष पथ निर्दिष्ट करते हैं, तो यह निर्देशिका को बदलने से पहले इसे संदर्भित करता है। यहाँ है एक साबित:

$ cat cd.cpp 
#include <stdio.h> 
#include <unistd.h> 

int main() 
{ 
    chdir ("/tmp/b/"); 
    printf ("Current dir: %s\n", 
     get_current_dir_name()); /* Forgive my memory leak. */ 
} 

$ gcc -o test ./cd.cpp 
$ pwd 
/tmp/b 
$ ./test 
Current dir: /tmp/b 
$ cd ../ 
$ ./b/test 
Current dir: /tmp/a 
$ cd/
$ /tmp/b/test 
Current dir: /tmp/a 
$ 

तो यह या तो libc या लिनक्स मुझ पर चालें खेल रहा है कि मैं वास्तव में के बारे में पहले ध्यान नहीं दिया की तरह लगता है।और उसके शीर्ष पर, s सीडी` किसी भी तरह से काम कर रहा है।

आश्चर्यजनक रूप से पर्याप्त, Linux chdir() man page इसके बारे में कुछ भी उल्लेख नहीं करता है, लेकिन बोर्लैंड बिल्डर (! एसआईसी) दस्तावेज, here में इसके बारे में एक नोट है। तो मुझे आश्चर्य है कि bash इस संबंध में क्या करता है।

+1

यह वह व्यवहार है जिसे मैं वास्तव में बनाने की अपेक्षा करता हूं। "तार्किक" निर्देशिका पूरी तरह से खोल द्वारा एक आविष्कार है, जो भ्रम को बनाए रखने के लिए अतिरिक्त काम करता है। – ephemient

+0

@ephemient: मैंने सोचा कि यह ऐसा कुछ कर रहा है, लेकिन अजीब बात यह है कि, 'सीडी' करते समय और 'getcwd()', 'getcwd()' को कॉल करने वाली प्रक्रिया का आह्वान करते हुए, symlink के लिए पथ देता है, न कि वास्तविक निर्देशिका। मैंने symlink के पूर्ण पथ के साथ 'chdir()' को कॉल करने का प्रयास किया है और उसी प्रभाव को प्राप्त नहीं कर सकता है। मैं सोच रहा हूं कि वास्तव में क्या चल रहा है। –

+0

'bash'' $ PWD' में कार्यरत निर्देशिका को कैश करता है। खोल अपडेट में 'सीडी' '$ पीडब्ल्यूडी'। शैल रिटर्न में 'pwd' '$ PWD' अगर यह वास्तविक कार्य निर्देशिका से मेल खाता है। जब आप 'cd && $ (MAKE)' का उपयोग करते हैं, तो चर आवर्ती आमंत्रण के लिए सेट किया जाता है; जब आप '$ (MAKE) -C' का उपयोग करते हैं, तो यह नहीं है, और 'pwd' अनचाहे भौतिक पथ पर वापस आ जाता है। – ephemient

उत्तर

7

ephemient की मदद से मैं इसे समझने में सक्षम था। तो कुछ चीजें हैं जो चल रही हैं:

  1. लिनक्स वर्तमान कार्य निर्देशिका को सिम्लिंक पर सेट करने का समर्थन नहीं करता है। chdir() हमेशा इसे वास्तविक निर्देशिका में सेट करता है।
  2. PWD नामक एक चर है जो परंपरागत कार्यशील निर्देशिका का प्रतिनिधित्व करता है।
  3. कुछ फ़ंक्शन/सिस्टम कॉल PWD वैरिएबल का सम्मान करते हैं और कुछ नहीं करते हैं।
  4. बैश प्रतीकात्मक नामों का उपयोग करके निर्मित "नकली" पथ बनाए रखता है और तदनुसार PWD चर सेट करता है।

यह gmake व्यवहार बताता है। gmakesh, PWD द्वारा gmake प्रक्रिया को निष्पादित करने से पहले अपडेट किया गया है। इस प्रकार, PWD "प्रतीकात्मक" पथ पर सेट है और इसे सम्मानित करने वाले कार्यों को ठीक काम करना जारी है। अन्यथा, gmakechdir() पर कॉल करता है, जो कार्यशील निर्देशिका को बदलता है और PWD को sh की चाल के बिना सेट करता है। इस प्रकार, PWD को सम्मानित करने वाले सभी कार्यों में "असली" पथ वापस करना शुरू हो गया है।

सब कुछ, मैं कहूंगा कि प्रतीकात्मक पथ नाम के आधार पर एक बुरा विचार है और चीजें आसानी से अलग हो सकती हैं। उदाहरण के लिए, क्योंकि getcwd() सिस्टम कॉल PWD परवाह नहीं करता है। चलाने से पहले cd को आमंत्रित करने के लिए हालांकि अल्पावधि समाधान के रूप में कार्य करता है।