আপনার মেকফিলের বর্তমান আপেক্ষিক ডিরেক্টরিটি কীভাবে পাবেন?


202

অ্যাপটির মতো নির্দিষ্ট ডিরেক্টরিগুলিতে আমার বেশ কয়েকটি মেকফাইল রয়েছে:

/project1/apps/app_typeA/Makefile
/project1/apps/app_typeB/Makefile
/project1/apps/app_typeC/Makefile

প্রতিটি Makefile এই স্তরে এক স্তর আপ একটি। ইন ফাইল অন্তর্ভুক্ত:

/project1/apps/app_rules.inc

অ্যাপ_রুলস এর অভ্যন্তরে আমি গন্তব্য স্থির করছি যেখানে আমি চাই যখন বাইনারিগুলি তৈরি করা হবে। আমি চাই সমস্ত বাইনারি তাদের নিজ নিজ app_typeপথে চলুক:

/project1/bin/app_typeA/

আমি এটির$(CURDIR) মতো ব্যবহার করার চেষ্টা করেছি :

OUTPUT_PATH = /project1/bin/$(CURDIR)

তবে এর পরিবর্তে আমি বাইনারিগুলি পুরো পথের নামে সমাহিত করলাম: (অযথা লক্ষ্য করুন)

/project1/bin/projects/users/bob/project1/apps/app_typeA

এক্সিকিউশনের "বর্তমান ডিরেক্টরি" পেতে আমি কী করতে পারি যাতে app_typeXবাইনারিগুলি তাদের নিজ নিজ প্রকারের ফোল্ডারে রাখার জন্য আমি কেবলমাত্র জানতে পারি ?

উত্তর:


271

শেল ফাংশন।

আপনি ব্যবহার করতে পারেন shellফাংশন: current_dir = $(shell pwd)। অথবা shellসঙ্গে একযোগে notdir, যদি আপনি সুনির্দিষ্ট পাথ না প্রয়োজন: current_dir = $(notdir $(shell pwd))

হালনাগাদ.

প্রদত্ত সমাধান কেবল তখনই কার্যকর হয় যখন আপনি makeমেকফিলের বর্তমান ডিরেক্টরি থেকে চালাচ্ছেন ।
যেমন @ ফ্লিম উল্লেখ করেছেন:

নোট করুন যে এটি মেকফিলের পিতামহিত ডিরেক্টরি নয়, বর্তমান কার্যকারী ডিরেক্টরিটি প্রদান করে।
উদাহরণস্বরূপ, আপনি চালনা cd /; make -f /home/username/project/Makefileকরলে current_dirচলকটি হবে /, না /home/username/project/

নীচের কোডটি কোনও ডিরেক্টরি থেকে আহবান করা মেকফিলের জন্য কাজ করবে:

mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))

5
যে কাজ করে না। এটা একই সমস্যা। পিডব্লিউডি পুরো পথের নাম মুদ্রণ করে, আমি কেবলমাত্র আসল বর্তমান ফোল্ডারের
নামটিই চাই

6
এটির সাথে সাথে মানটি প্রসারিত হওয়া দরকার যাতে: = অপারেটরটি ব্যবহার করা উচিত। এমকিফাইল_পাথের মতো: = এবং কারেন্ট_ডির = (অন্যথায় ডান পার্শ্বের মানগুলি পরে মূল্যায়ন করা যেতে পারে যখন অন্য মেকফিলগুলি অন্তর্ভুক্ত করার পরে ম্যাকএফাইল_লিস্ট পরিবর্তন করা হয়েছিল
টম গ্রুনার

10
আমি জানি এটি একটি পুরানো প্রশ্ন তবে আমি কেবল দৌড়ে এসেছি এবং ভেবেছিলাম এটি কার্যকর হতে পারে। মেকফিলের আপেক্ষিক পথে কোনও স্থান থাকলে এটিও কাজ করবে না। বিশেষত, $(lastword "$(MAKEFILE_LIST)")পথে একটি মেকফিল "Sub Directory/Makefile"আপনাকে দেবে "Directory/Makefile"। আমি মনে করি না এর চারপাশে কোনও উপায় আছে কারণ $(MAKEFILE_LIST)দুটি মেকফাইল আপনাকে একটি একক স্ট্রিং দেয় "Makefile One Makefile Twoযা স্পেস পরিচালনা করতে পারে না
ম্রোসলে

2
এটি current_dirআমার পক্ষে কাজ করে না। $(PWD)এবং এটি অনেক সহজ।
CaTx

3
"solution only works when you are running make from the Makefile's current directory""সত্যিই কাজ করছে না" বলার একটি হালকা উপায়। আমি উত্তরের শীর্ষে সর্বশেষতম টুকরা রাখব।
ভিক্টর সার্জিইঙ্কো

137

যেমন এখান থেকে নেওয়া ;

ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

হিসাবে দেখায়;

$ cd /home/user/

$ make -f test/Makefile 
/home/user/test

$ cd test; make Makefile 
/home/user/test

আশাকরি এটা সাহায্য করবে


3
আইএমএইচও এটি পিছনে অক্ষরের সাথে পথের নাম পাওয়ার dirপরিবর্তে অভ্যন্তরীণ মেক-ফাংশনটি ব্যবহার করা ভাল । shell dirname/
সার্জ রাউসাক

3
বাহ্যিক সরঞ্জামগুলির উপর নির্ভরতা হ্রাস করার কারণে। অর্থাৎ যদি কোনও সিস্টেমে ডায়ারনেম কমান্ডের উপাধি পাওয়া যায়? ..
সার্জে রউসাক

6
এটি প্রায় আমার জন্য কাজ করেছিল, তবে ডিআইআর একটি শীর্ষস্থানীয় সাদা জায়গা ছিল তাই একটি ছোটখাটো পরিবর্তন পুরোপুরিভাবে কাজটি করেছে:DIR:=$(strip $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))))
থর্স্টেন লরেঞ্জ

9
বর্তমান মেকফিলটি উল্লেখ করতে, $MAKEFILE_LISTঅবশ্যই কোনও includeক্রিয়াকলাপ ( ডক্স ) এর আগে অবশ্যই তৈরি করতে হবে ।
nobar

2
অন্ততপক্ষে যুক্তির আশেপাশে - কোথাও dirnameযদি পথে ফাঁকা স্থান থাকে তবে উক্তি ব্যবহার করা উচিত ।
nobar

46

আপনি যদি জিএনইউ মেক ব্যবহার করছেন তবে $ (সিডিআরডিআর) আসলে বিল্ট-ইন ভেরিয়েবল। এটি সেই অবস্থান যেখানে মেকফিল বর্তমান কার্যনির্বাহী ডিরেক্টরিটি বাস করে, যা সম্ভবত মেকফিল যেখানে রয়েছে তবে সর্বদা নয়

OUTPUT_PATH = /project1/bin/$(notdir $(CURDIR))

Http://www.gnu.org/software/make/manual/make.html এ পরিশিষ্টের একটি দ্রুত রেফারেন্স দেখুন


18
জিএনইউ মেক ম্যানুয়াল (পৃষ্ঠা 51) থেকে: "যখন জিএনইউ মেক শুরু শুরু হয় (এটি কোনও সি-সি বিকল্পগুলি প্রক্রিয়া করার পরে) এটি চলমান কর্মনির্দেশকের ডিরেক্টরিতে চলক CURDIR সেট করে।" মেকফিল যেখানে অবস্থিত তার অবস্থান নয় - যদিও, তারা একই হতে পারে।
সাইমন পেভেরেট

4
উত্তোলন করা হয়েছে কারণ উত্তরটি প্রযুক্তিগতভাবে সঠিক নয়, যেমনটি আগের মন্তব্যে সাইমন পেভেরেটের দ্বারা উল্লিখিত ছিল।
সাবফুজিওন

5
@ সিমোনপিভারেট: বন্ধনীগুলিতে প্রকাশের অর্থ "বর্তমান কার্যনির্বাহী ডিরেক্টরি AFTER -C অপ্ট প্রয়োগ করা হয়েছে"। যথা $ (সিডিআরডিআর) "মেক-সি এক্সএক্সএক্সএক্সএক্স" এবং "সিডি এক্সএক্সএক্সএক্সএক্স; মেক" এর জন্য ঠিক একই ফলাফল দেয়। এছাড়াও এটি পেছন সরিয়ে দেয় /। আমি gmakev3.81 এর সাথে বেঁধে দেওয়ার চেষ্টা করেছি। makeহিসাবে ডাকা হয় তবে আপনি ঠিক make -f xxx/Makefile
সত্য

CURDIRযেখানে আমার জন্য কাজ করে PWDনা। আমি mkdir -p a/s/dতখন প্রতিটি ফোল্ডারে একটি মেকফাইল ছিল যা মুদ্রিত হয়েছিল PWDএবং তার CURDIRআগেও +$(MAKE) <subdir>
কে কে কোয়ান

27
THIS_DIR := $(dir $(abspath $(firstword $(MAKEFILE_LIST))))

12
... যদি না আপনার কোনও পথে ফাঁকা থাকে।
ক্রেগ রিঞ্জার

9
... আপনি যদি আগের লাইনে অন্য
কোনও মেকফিল

1
পছন্দ করুন আমি সবেমাত্র এটাই মুখোমুখি হয়েছি। আপনার যদি কেবল দুটি মেকফাইল থাকে ( এটির মধ্যে একটি মূল প্লাস একটি অন্তর্ভুক্ত থাকে) এটি দুর্দান্ত কাজ করে ।
sherrellbc

6

আমি এই উত্তরগুলির অনেকগুলি চেষ্টা করেছিলাম, তবে আমার এআইএক্স সিস্টেমে জিনু দিয়ে 3.80 করা উচিত আমাকে কিছু কাজ করতে হবে পুরানো স্কুল।

যে সক্রিয় আউট lastword, abspathএবং realpathনা যোগ করা হয় নি 3,81 পর্যন্ত। :(

mkfile_path := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
mkfile_dir:=$(shell cd $(shell dirname $(mkfile_path)); pwd)
current_dir:=$(notdir $(mkfile_dir))

যেমনটি অন্যরা বলেছেন, এটি সবচেয়ে মার্জিত নয় কারণ এটি শেলকে দু'বার আহ্বান করে এবং এর মধ্যে স্পেসের সমস্যা রয়েছে।

তবে আমার পথে আমার কোনও ফাঁকা স্থান নেই, আমি কীভাবে শুরু করেছি তা নির্বিশেষে এটি আমার পক্ষে কাজ করে make:

  • Make -f ../herever/makefile
  • মেক-সি .. / যে কোনও জায়গায়
  • Make -C ~ / যেখানেই হোক
  • সিডি ../ কোথাও; করতে

সকল আমাকে দিতে whereverজন্য current_dirএবং সঠিক পথটি whereverজন্য mkfile_dir


আমি, একের জন্য, সমস্যা ছাড়াই আইসকে (5-6-7) gnu-make-3.1 সংকলন করেছি।
জিসিগমন্ড লরিনকি

হ্যাঁ, ৩.৮১ এর মধ্যে পূর্বের সমাধানগুলির জন্য প্রয়োজনীয় কাজগুলি কার্যকর করা হয়েছিল। আমার উত্তরটি 80.৮০ বা তারও আগের পুরানো সিস্টেমগুলির জন্য। দুঃখের বিষয়, কর্মক্ষেত্রে আমাকে এআইএক্স সিস্টেমে সরঞ্জাম সংযোজন বা আপগ্রেড করার অনুমতি নেই। :(
জেসি

5

আমি নির্বাচিত উত্তরটি পছন্দ করি তবে আমার মনে হয় এটির ব্যাখ্যা দেওয়ার চেয়ে এটি কার্যত প্রদর্শিত দেখানো আরও সহায়ক হবে।

/tmp/makefile_path_test.sh

#!/bin/bash -eu

# Create a testing dir
temp_dir=/tmp/makefile_path_test
proj_dir=$temp_dir/dir1/dir2/dir3
mkdir -p $proj_dir

# Create the Makefile in $proj_dir
# (Because of this, $proj_dir is what $(path) should evaluate to.)
cat > $proj_dir/Makefile <<'EOF'
path := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
cwd  := $(shell pwd)

all:
    @echo "MAKEFILE_LIST: $(MAKEFILE_LIST)"
    @echo "         path: $(path)"
    @echo "          cwd: $(cwd)"
    @echo ""
EOF

# See/debug each command
set -x

# Test using the Makefile in the current directory
cd $proj_dir
make

# Test passing a Makefile
cd $temp_dir
make -f $proj_dir/Makefile

# Cleanup
rm -rf $temp_dir

আউটপুট:

+ cd /tmp/makefile_path_test/dir1/dir2/dir3
+ make
MAKEFILE_LIST:  Makefile
         path: /private/tmp/makefile_path_test/dir1/dir2/dir3
          cwd: /tmp/makefile_path_test/dir1/dir2/dir3

+ cd /tmp/makefile_path_test
+ make -f /tmp/makefile_path_test/dir1/dir2/dir3/Makefile
MAKEFILE_LIST:  /tmp/makefile_path_test/dir1/dir2/dir3/Makefile
         path: /tmp/makefile_path_test/dir1/dir2/dir3
          cwd: /tmp/makefile_path_test

+ rm -rf /tmp/makefile_path_test

দ্রষ্টব্য: ফাংশনটি $(patsubst %/,%,[path/goes/here/])পিছনের স্ল্যাশ ফালা করতে ব্যবহৃত হয়।


2

Makefileশেল সিনট্যাক্স ব্যবহার করে আপনার ফাইলে নিখুঁত পাথ পেতে এখানে এক-লাইনার দেওয়া হয়েছে :

SHELL := /bin/bash
CWD := $(shell cd -P -- '$(shell dirname -- "$0")' && pwd -P)

এবং এখানে @ 0xff উত্তরের উপর ভিত্তি করে শেল ছাড়াই সংস্করণ রয়েছে :

CWD := $(abspath $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))))

এটি প্রিন্ট করে এটি পরীক্ষা করুন:

cwd:
        @echo $(CWD)

1
সমালোচনামূলক গুরুত্ব! উপরের দ্বিতীয় উদাহরণটির জন্য দরকার: = এসাইনমেন্ট অপারেটর বা অন্যথায় জটিল মেকফিলগুলি (আমার উপর বিশ্বাস করুন) দিয়ে কিছু খুব অদ্ভুত এবং ক্রুদ্ধ ঘটনা ঘটতে পারে
ইমন

1
প্রথমটি হ'ল একটি পুনরাবৃত্তি ত্রুটি এবং গাছের বাইরে-তৈরির জন্য কাজ করে না।
জোহান বুলি

2

সমাধান এখানে পাওয়া গেছে: https://sourceforge.net/p/ipt-netflow/bugs-requests-patches/53/

সমাধানটি হ'ল : $ (কর্ডির)

আপনি এটির মতো ব্যবহার করতে পারেন:

CUR_DIR = $(CURDIR)

## Start :
start:
    cd $(CUR_DIR)/path_to_folder

3
স্ট্যাক ওভারফ্লোতে আপনাকে স্বাগতম। আপনি কি নিজের উত্তরে আরও বিশদ যুক্ত করতে পারবেন? প্রশ্নটি বলে যে $(CURDIR)ইতিমধ্যে ব্যর্থ চেষ্টা করা হয়েছিল।
শান

4
সতর্কতা, দ্রুত-Googlers: এই না ডিরেক্টরির, যেখানে Makefile, কিন্তু বর্তমান পরিশ্রমী ডিরেক্টরি (যেখানে makeসালে চালু হয়)। এটি সত্যই, ওপি আসলে কী চেয়েছিল, তবে প্রশ্নের শিরোনামটি বোগাস, সুতরাং প্রশ্নটি নিজেই বেমানান। সুতরাং, এটি একটি ভুল প্রশ্নের সঠিক উত্তর। ;)
এসজেড

এটি ফ্ল্যাট আউট ভুল এবং একটি অপ্রয়োজনীয় ভুল উত্তর
আপ

0

যতদূর আমি অবগত আছি এটি এখানে একমাত্র উত্তর যা স্পেসগুলির সাথে সঠিকভাবে কাজ করে:

space:= 
space+=

CURRENT_PATH := $(subst $(lastword $(notdir $(MAKEFILE_LIST))),,$(subst $(space),\$(space),$(shell realpath '$(strip $(MAKEFILE_LIST))')))

এটি মূলত দ্বারা substituting স্থান অক্ষর পলায়নের করে কাজ করে ' 'জন্য '\ 'যা এটিকে সঠিকভাবে বিশ্লেষণ করতে অনুমতি দেয়, এবং তারপর এটি মধ্যে Makefile ফাইলের নাম সরিয়ে ফেলা হবেMAKEFILE_LIST আপনি যে ডিরেক্টরি Makefile হয় অবশিষ্ট করছি যাতে অন্য প্রতিকল্পন করে। না ঠিক সবচেয়ে কম্প্যাক্ট বিশ্বের জিনিস কিন্তু এটি কাজ করে।

আপনি এমন কিছু দিয়ে শেষ করবেন যেখানে সমস্ত স্থান ফাঁকা পড়েছে:

$(info CURRENT_PATH = $(CURRENT_PATH))

CURRENT_PATH = /mnt/c/Users/foobar/gDrive/P\ roje\ cts/we\ b/sitecompiler/

-2

নীচে যেমন আপনার রেফারেন্সের জন্য উদাহরণ:

ফোল্ডার কাঠামোটি হতে পারে:

এখানে চিত্র বর্ণনা লিখুন

যেখানে নীচে যেমন দুটি মেকফাইল রয়েছে;

sample/Makefile
test/Makefile

এখন, আসুন মেকফিলস এর সামগ্রীটি দেখুন।

নমুনা / Makefile নামক

export ROOT_DIR=${PWD}

all:
    echo ${ROOT_DIR}
    $(MAKE) -C test

পরীক্ষা / Makefile নামক

all:
    echo ${ROOT_DIR}
    echo "make test ends here !"

এখন, হিসাবে নমুনা / Makefile সঞ্চালন;

cd sample
make

আউটপুট:

echo /home/symphony/sample
/home/symphony/sample
make -C test
make[1]: Entering directory `/home/symphony/sample/test'
echo /home/symphony/sample
/home/symphony/sample
echo "make test ends here !"
make test ends here !
make[1]: Leaving directory `/home/symphony/sample/test'

ব্যাখ্যা, পিতামাত / হোম ডিরেক্টরি পরিবেশ-পত্রে সংরক্ষণ করা যেতে পারে, এবং রফতানি করা যেতে পারে, যাতে এটি সমস্ত উপ-ডিরেক্টরি মেকফিলগুলিতে ব্যবহার করা যায়।


2
এটি মেকফিলের হোম ডিরেক্টরি নয়, বর্তমান কার্যকারী ডিরেক্টরিটি পায়।
জেসি

এগুলি মেকফিলের লাইনগুলি। এখন, মেকফিল কমান্ড কার্যকর করার সাথে সাথে এটি মেকফিলটি যেখানে পাবে তা পাবে। আমি বুঝতে পারছি "মেকফাইল হোম ডিরেক্টরি" একইটিকে বোঝাচ্ছে, অর্থাত্ যে ডিরেক্টরি-পথটি মেকফিল সম্পাদন করছে।
পরজীবী

@ জেসি চিশলম দয়া করে আবার দর্শন করুন। আমি ব্যবহারের সাথে ব্যাখ্যা করেছি।
পরশ্রিশ

একটি পুনরাবৃত্তি ত্রুটি: এটি গাছের বাইরে-তৈরির জন্য কাজ করে না। এছাড়াও, আপনার জিনোম টার্মিনাল পাঠ্য অনুলিপি করার একটি সহজ উপায় সরবরাহ করে: কেবল এটি নির্বাচন করুন। গুজবটির ইমগুর ব্রংক্রেট।
জোহান বুলি

-2

2018/03/05 ফাইনাল আপডেট করুন আমি এটি ব্যবহার করি:


shellPath=`echo $PWD/``echo ${0%/*}`

# process absolute path
shellPath1=`echo $PWD/`
shellPath2=`echo ${0%/*}`
if [ ${shellPath2:0:1} == '/' ] ; then
    shellPath=${shellPath2}
fi

এটি আপেক্ষিক পথে বা পরম পথে সঠিকভাবে কার্যকর করা যেতে পারে। ক্রোনটব দ্বারা চালিত সঠিক সম্পাদিত। অন্য শেলের ক্ষেত্রে সঠিকভাবে কার্যকর করা হয়েছে।

উদাহরণ দেখান, a.sh মুদ্রণ স্ব পাথ।

[root@izbp1a7wyzv7b5hitowq2yz /]# more /root/test/a.sh
shellPath=`echo $PWD/``echo ${0%/*}`

# process absolute path
shellPath1=`echo $PWD/`
shellPath2=`echo ${0%/*}`
if [ ${shellPath2:0:1} == '/' ] ; then
    shellPath=${shellPath2}
fi

echo $shellPath
[root@izbp1a7wyzv7b5hitowq2yz /]# more /root/b.sh
shellPath=`echo $PWD/``echo ${0%/*}`

# process absolute path
shellPath1=`echo $PWD/`
shellPath2=`echo ${0%/*}`
if [ ${shellPath2:0:1} == '/' ] ; then
    shellPath=${shellPath2}
fi

$shellPath/test/a.sh
[root@izbp1a7wyzv7b5hitowq2yz /]# ~/b.sh
/root/test
[root@izbp1a7wyzv7b5hitowq2yz /]# /root/b.sh
/root/test
[root@izbp1a7wyzv7b5hitowq2yz /]# cd ~
[root@izbp1a7wyzv7b5hitowq2yz ~]# ./b.sh
/root/./test
[root@izbp1a7wyzv7b5hitowq2yz ~]# test/a.sh
/root/test
[root@izbp1a7wyzv7b5hitowq2yz ~]# cd test
[root@izbp1a7wyzv7b5hitowq2yz test]# ./a.sh
/root/test/.
[root@izbp1a7wyzv7b5hitowq2yz test]# cd /
[root@izbp1a7wyzv7b5hitowq2yz /]# /root/test/a.sh
/root/test
[root@izbp1a7wyzv7b5hitowq2yz /]# 

পুরাতন: আমি এটি ব্যবহার:

MAKEFILE_PATH := $(PWD)/$({0%/*})

এটি অন্য শেল এবং অন্যান্য ডিরেক্টরিতে চালিত হলে সঠিক দেখাতে পারে।


1
"অন্যান্য শেল এবং অন্যান্য ডিরেক্টরি যদি ইংরেজীতে অর্থবোধ না করে তবে এটি কার্যকর করা হলে এটি সঠিক দেখাতে পারে।" আপনি আবার ব্যাখ্যা করার চেষ্টা করতে পারেন?
কিথ এম

আমার দরিদ্র
ইংলিশের

সম্পাদনার জন্য ধন্যবাদ, আমি আপনাকে এখনই বোঝাতে চাইছি। আমি এটি চেষ্টা করার আগে এটি কী করে তা ব্যাখ্যা করতে পারেন? আমি কীভাবে এটি ব্যবহার করব তা নিশ্চিত নই। "অন্যান্য শেল" বলতে কী বোঝায়
কিথ এম

1
এই উত্তরে এতগুলি ভুল জিনিস রয়েছে এটি সম্ভবত সংশোধন করা যায় না। আমি একটি সহজ অপসারণ প্রস্তাব।
জোহান বুলি

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.