यहाँ एक समाधान है कि केवल का उपयोग करता है जीएनयू कार्यों बनाते हैं। भले ही यह पुनरावर्ती है, यह बाहरी कार्यक्रम को कॉल करने से अधिक कुशल होना चाहिए। विचार बहुत सीधे आगे है: सापेक्ष पथ शून्य या अधिक होगा .. सबसे आम पूर्वजों तक जाने के लिए, फिर दूसरी निर्देशिका में जाने के लिए एक प्रत्यय। कठिन हिस्सा दोनों पथों में सबसे लंबा आम उपसर्ग ढूंढ रहा है।
# DOES not work if path has spaces
OneDirectoryUp=$(patsubst %/$(lastword $(subst /, ,$(1))),%,$(1))
# FindParentDir2(dir0, dir1, prefix) returns prefix if dir0 and dir1
# start with prefix, otherwise returns
# FindParentDir2(dir0, dir1, OneDirectoryUp(prefix))
FindParentDir2=
$(if
$(or
$(patsubst $(3)/%,,$(1)),
$(patsubst $(3)/%,,$(2))
),
$(call FindParentDir2,$(1),$(2),$(call OneDirectoryUp,$(3))),
$(3)
)
FindParentDir=$(call FindParentDir2,$(1),$(2),$(1))
# how to make a variable with a space, courtesy of John Graham-Cumming
# http://blog.jgc.org/2007/06/escaping-comma-and-space-in-gnu-make.html
space:=
space+=
# dir1 relative to dir2 (dir1 and dir2 must be absolute paths)
RelativePath=$(subst
$(space),
,
$(patsubst
%,
../,
$(subst
/,
,
$(patsubst
$(call FindParentDir,$(1),$(2))/%,
%,
$(2)
)
)
)
)
$(patsubst
$(call FindParentDir,$(1),$(2))/%,
%,
$(1)
)
# example of how to use (will give ..)
$(call RelativePath,/home/yale,/home/yale/workspace)
मैं हाल ही में एक पूरी परियोजना में पुनरावर्ती makefiles के एक बड़े सेट अनुवाद के रूप में यह अच्छी तरह से जाना जाता है पुनरावर्ती मेकअप की वजह से पूरे निर्भरता ग्राफ (http://aegis.sourceforge.net/auug97.pdf) को उजागर नहीं करने के लिए बुरा है कि सुनिश्चित करें। सभी स्रोत कोड और लाइब्रेरी पथ वर्तमान मेकफ़ाइल निर्देशिका के सापेक्ष परिभाषित किए गए हैं। जेनेरिक% बिल्ड नियमों की एक निश्चित संख्या को परिभाषित करने के बजाय, मैं प्रत्येक (स्रोत कोड निर्देशिका, आउटपुट निर्देशिका) जोड़ी के लिए नियमों का एक सेट बना देता हूं, जो vpath का उपयोग करने की अस्पष्टता से बचाता है। निर्माण नियम बनाते समय, मुझे प्रत्येक स्रोत कोड निर्देशिका के लिए एक कैननिकल पथ की आवश्यकता होती है। यद्यपि पूर्ण पथ का उपयोग किया जा सकता है, यह आमतौर पर बहुत लंबा और कम पोर्टेबल होता है (मैं सिग्विन जीएनयू का उपयोग करने के लिए हुआ जहां पूर्ण पथों में एक/साइग्राइड उपसर्ग है और विंडोज प्रोग्राम द्वारा मान्यता प्राप्त नहीं है)।इसलिए, मैं इस कार्य का उपयोग कैनोलिक पथ उत्पन्न करने के लिए भारी रूप से करता हूं।
इस मेटा-जवाब सबसे अच्छा एक है:
यहाँ एक उदाहरण है! ध्यान दें कि '- निर्देशिका' पोर्टेबल नहीं है: 'cd $ (rootdir)/src/libs/libfoo; $ (मेक) ... 'अधिक विश्वसनीय होगा। –
@ नॉर्मन ग्रे: '$ (मेक) -सी ... के साथ क्या गलत है? – Beta
मुझे नहीं लगता कि मैं _wrong_ तक जाऊंगा, लेकिन सभी 'मेक' कमांड इसका समर्थन नहीं करते हैं (और यह [posix] में नहीं है (http://www.opengroup.org/onlinepubs/009695399/utilities/make .html), उदाहरण के लिए), इसलिए यदि यह मेकफ़ाइल वितरण के लिए है, तो यह समस्याएं पैदा कर सकता है। किसी भी मामले में, मुझे लगता है कि 'सीडी फू; $ (मेक) ... 'इरादे को और स्पष्ट रूप से व्यक्त करता है। –