কিভাবে একটি Makefile এ লুপ লিখবেন?


217

আমি নিম্নলিখিত কমান্ডগুলি কার্যকর করতে চাই:

./a.out 1
./a.out 2
./a.out 3
./a.out 4
.
.
. and so on

এ-তে লুপ হিসাবে এই জিনিসটি কীভাবে লিখবেন Makefile?


অনুরূপ, তবে খানিকটা জেনেরিক:
মেকফাইলে মাল্টলাইন

উত্তর:


273

নিম্নলিখিতটি এটি করবে যদি আমি আপনার ব্যবহার হিসাবে ধরে নিই ./a.out, আপনি একটি ইউনিক্স-টাইপ প্ল্যাটফর্মে আছেন।

for number in 1 2 3 4 ; do \
    ./a.out $$number ; \
done

পরীক্ষা নিম্নরূপ:

target:
    for number in 1 2 3 4 ; do \
        echo $$number ; \
    done

সৃষ্টি করে:

1
2
3
4

বড় ব্যাপ্তির জন্য, ব্যবহার করুন:

target:
    number=1 ; while [[ $$number -le 10 ]] ; do \
        echo $$number ; \
        ((number = number + 1)) ; \
    done

এটি 1 এর মধ্যে 10 টি অন্তর্ভুক্ত করে, whileআপনার মন্তব্যে উল্লিখিত হিসাবে আরও বড় পরিসরের জন্য কেবলমাত্র সমাপ্তির শর্তটি 10 ​​থেকে 1000 এ পরিবর্তন করুন।

নেস্টেড লুপগুলি এভাবে করা যেতে পারে:

target:
    num1=1 ; while [[ $$num1 -le 4 ]] ; do \
        num2=1 ; while [[ $$num2 -le 3 ]] ; do \
            echo $$num1 $$num2 ; \
            ((num2 = num2 + 1)) ; \
        done ; \
        ((num1 = num1 + 1)) ; \
    done

উৎপাদন:

1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3

1
কিওয়ার্ট হ'ল একটি টার্গেট নাম যা আসল ফাইল হওয়ার সম্ভাবনা কম। মেকফিল বিধিগুলির একটি লক্ষ্য প্রয়োজন। বাক্য গঠন ত্রুটি হিসাবে, আপনি কিছু স্টাফ মিস করছেন - আপডেট দেখুন।
paxdiablo

2
যেহেতু আপনি ধরে নিচ্ছেন যে তাঁর শেলটি ((...)) স্বীকৃতি দেয়, তাই কেন ((i = 0; i <WHATVER; ++ i)) এর জন্য এত সহজ ব্যবহার করবেন না; কর ...; সম্পন্ন ?
আইডেলিক

1
নোট করুন যে seqকমান্ডটি সংখ্যার ক্রম উত্পন্ন করে তা বেশিরভাগ (সমস্ত?) ইউনিক্স সিস্টেমে বিদ্যমান রয়েছে, সুতরাং আপনি লিখতে পারেন for number in ``seq 1 1000``; do echo $$number; done(দুইটি নয়, সেক কমান্ডের প্রতিটি পাশের একক ব্যাকটিক লাগান, আমি জানি না কীভাবে এটি সঠিকভাবে ফর্ম্যাট করা যায়)
স্ট্যাকওভারফ্লো

3
ধন্যবাদ, লুপ ভেরিয়েবলের জন্য রেফারেন্স দিতে আমি ডাবল missing মিস করছি।
লাইফ গ্রুইনওয়েল্ট

1
@ জঞ্জ: লাইন ধারাবাহিকতা চরিত্রটি হ'ল কারণ makeসাধারণত প্রতিটি লাইনকে আলাদা সাব-শেল চালানোর জিনিস হিসাবে বিবেচনা করে । ধারাবাহিকতা ছাড়াই for number in 1 2 3 4 ; do, এটি বাকী লুপ ছাড়াই কেবল (উদাহরণস্বরূপ) দিয়ে একটি সাবশেল চালানোর চেষ্টা করবে । এটির সাথে এটি কার্যকরভাবে ফর্মের একক লাইনে পরিণত হয় while something ; do something ; done, যা একটি সম্পূর্ণ বিবৃতি। $$: প্রশ্নের উত্তর এখানে দেওয়া হয় stackoverflow.com/questions/26564825/... , আপাতদৃষ্টিতে এই খুব উত্তর থেকে :-) নিষ্কাশিত কোড সহ
paxdiablo

265

আপনি যদি জিএনইউ মেক ব্যবহার করছেন তবে আপনি চেষ্টা করতে পারেন

সংখ্যা = 1 2 3 4
এটা কর:
        $ (ফোরচ ভার, $ (NUMBERS),। / a.out $ (var);)

যা উত্পন্ন এবং কার্যকর করবে

./a.out 1; ./a.out 2; ./a.out 3; ./a.out 4;

27
এই উত্তরটি আইএমএইচও আরও ভাল, কারণ এটির কোনও শেল ব্যবহার করার প্রয়োজন নেই, এটি খাঁটি মেকফিল (এটি জিএনইউ-নির্দিষ্ট থাকলেও)।
জোসলিন ডেলাল্যান্ডে

7
সেমিকোলনটি অত্যন্ত গুরুত্বপূর্ণ অন্যথায় কেবল প্রথম পুনরাবৃত্তি কার্যকর হবে
জেরেমি লিপজিগ

7
এই দ্রবণটি এর প্রস্থান কোডটি আড়াল করে ./a.out 1./a.out 2নির্বিশেষে মৃত্যুদন্ড কার্যকর করা হবে
বোবোগো

1
@ আলেকজান্ডার: আপনি কোন সীমাবদ্ধতার কথা উল্লেখ করছেন সে সম্পর্কে আপনি বিশদ বর্ণনা করতে পারেন?
আইডেলিক

1
@ ইডেলিক, হ্যাঁ নিম্নলিখিত মেকফিল এবং শেলসক্রিপ্টের জন্য, শেলসক্রিপ্টটি কাজ করে (এলএস-তে আর্গুমেন্ট প্রেরণ করে), যখন মেকফিল একটি ত্রুটি দেয়: তৈরি করুন: এক্সিকিউপি: / বিন / শ: আর্গুমেন্টের তালিকাটি অনেক দীর্ঘ মেকফিল : ix.io/d5L শেলসক্রিপ্ট: ix.io / d5M এটি ফোরচ ফাংশনে একটি সমস্যা যা আমি কর্মক্ষেত্রে মুখোমুখি হয়েছিলাম, যখন একটি অনন্যভাবে ফাইলের নামের দীর্ঘ তালিকা (দীর্ঘ পথ সহ) কমান্ডের কাছে পাঠানো হয়। আমাদের একটি কাজ খুঁজে বের করতে হবে।
আলেকজান্ডার

107

থেকে ব্যবহার করতে এই প্রোগ্রামটিতে প্রধান কারণ নেই -jপতাকা। make -j5একবারে 5 টি শেল কমান্ড চালাবে। আপনার 4 টি সিপিইউ যদি বলা হয় তবে এটি ভাল, এবং কোনও মেকফিলের একটি ভাল পরীক্ষা।

মূলত, আপনি এমন কিছু দেখতে চান:

.PHONY: all
all: job1 job2 job3

.PHONY: job1
job1: ; ./a.out 1

.PHONY: job2
job2: ; ./a.out 2

.PHONY: job3
job3: ; ./a.out 3

এটি -jবন্ধুত্বপূর্ণ (একটি ভাল লক্ষণ)। আপনি বয়লার-প্লেট স্পট করতে পারেন? আমরা লিখতে পারি:

.PHONY: all job1 job2 job3
all: job1 job2 job3
job1 job2 job3: job%:
    ./a.out $*

একই প্রভাবের জন্য (হ্যাঁ, এটা পূর্ববর্তী সূত্র হিসাবে একই যতটা হয় করতে সংশ্লিষ্ট হয়, শুধু একটি বিট আরো কম্প্যাক্ট)।

আরও কিছু প্যারামিটারাইজেশন যাতে আপনি কমান্ড-লাইনের একটি সীমা নির্দিষ্ট করতে পারেন (ক্লান্তিকর যেমন makeকোনও ভাল গাণিতিক ম্যাক্রো নেই, তাই আমি এখানে প্রতারণা করব এবং ব্যবহার করব $(shell ...))

LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*

আপনি এটি 1000 make -j5 LAST=550দিয়ে LASTডিফল্ট করে দিয়ে চালান ।


7
এই হ 'ল সর্বোত্তম উত্তর, কারণ যে উল্লেখ bobbogo (জন্য -J )।
dbn

কোন বিশেষ কারণ এটি ব্যবহার করে। PHONY প্রত্যয়? এগুলি কি কোনও কিছুর জন্য দরকার?
Seb

6
@ সেব: ছাড়া .PHONY: all, মেক কল করা কোনও ফাইল সন্ধান করবে all। যদি এই জাতীয় কোনও ফাইল বিদ্যমান থাকে তবে তারপরে সেই ফাইলটির সর্বশেষ-পরিবর্তিত সময়টি যাচাই করুন এবং মেকফাইলটি অবশ্যই আপনার ইচ্ছা অনুযায়ী কাজ করবে না। .PHONYঘোষণা কি যে বলে allএকটি সিম্বলিক লক্ষ্য। তাই মেক allলক্ষ্যটিকে সর্বদা অতিক্রান্ত মনে করবে । পারফেক্ট। ম্যানুয়াল দেখুন।
বোবোগো

4
এই লাইনটি কীভাবে কাজ করে: {O জবস}: চাকরি%: দ্বিতীয় সেমিকোলনটি কীসের জন্য? আমি gnu.org/software/make/manual/make.htm- এ
জো

2
@ জোস gnu.org/software/make/manual/make.html# স্ট্যাটিক- প্যাটার্ন (আমি মনে করি আপনি বোঝাতে চেয়েছিলেন ২ য় * কোলন * এর জন্য )। আন-সুন্দর (আইএমএইচও) প্যাটার্ন বিধিগুলির সাথে তাদের গুলিয়ে ফেলবেন না । স্থির নকশাগুলির নিয়মগুলি কার্যকরভাবে কার্যকর যখনই লক্ষ্যগুলির তালিকার সাথে কোনও তৈরির নোডি প্যাটার্নগুলি (নির্ভরতার ক্ষেত্রে একই প্রযোজ্য) মেলা যায় । এখানে আমি কেবল একটি সুবিধার্থে ব্যবহার করি যে %নিয়মের সাথে যা কিছু মিলছে $*তা রেসিপি হিসাবে পাওয়া যায় ।
বোবোগো

22

আমি বুঝতে পারি যে প্রশ্নটি বেশ কয়েক বছরের পুরনো, তবে এই পোস্টটি এখনও কারওরূপে কার্যকর হতে পারে কারণ এটি একটি দৃষ্টিভঙ্গি দেখায় যা উপরের থেকে পৃথক, এবং শেল অপারেশনগুলির উপর নির্ভর করে না বা বিকাশকারীকে হার্ডকোড বের করার প্রয়োজন নেই সংখ্যার মানগুলির স্ট্রিং।

দ্য $ (ইভাল ....) অন্তর্নির্মিত ম্যাক্রো আপনার বন্ধু। বা কমপক্ষে হতে পারে।

define ITERATE
$(eval ITERATE_COUNT :=)\
$(if $(filter ${1},0),,\
  $(call ITERATE_DO,${1},${2})\
)
endef

define ITERATE_DO
$(if $(word ${1}, ${ITERATE_COUNT}),,\
  $(eval ITERATE_COUNT+=.)\
  $(info ${2} $(words ${ITERATE_COUNT}))\
  $(call ITERATE_DO,${1},${2})\
)
endef

default:
  $(call ITERATE,5,somecmd)
  $(call ITERATE,0,nocmd)
  $(info $(call ITERATE,8,someothercmd)

এটি একটি সরল উদাহরণ। এটি বৃহত্তর মূল্যবোধগুলির জন্য সুন্দর স্কেল করবে না - এটি কাজ করে, তবে যেমন ITERATE_COUNT স্ট্রিং প্রতিটি পুনরাবৃত্তির জন্য 2 টি অক্ষর (স্থান এবং বিন্দু) বৃদ্ধি পাবে, আপনি হাজারে উঠার সাথে সাথে শব্দগুলি গণনা করতে এটি ক্রমশ বেশি সময় নেয়। যেমনটি লেখা আছে, এটি নেস্টেড পুনরাবৃত্তি পরিচালনা করে না (এটি করার জন্য আপনার পৃথক পুনরাবৃত্তি ফাংশন এবং কাউন্টারের প্রয়োজন হবে)। এটি নিখুঁতভাবে জিনু মেক, কোনও শেলের প্রয়োজনীয়তা নেই (যদিও স্পষ্টতই ওপি প্রতিবারই একটি প্রোগ্রাম চালাচ্ছিল - এখানে, আমি কেবল একটি বার্তা প্রদর্শন করছি)। যদি ITERATE এর মধ্যে এটির মান 0 ধরা হয়, কারণ $ (শব্দ ...) অন্যথায় ত্রুটি ঘটবে।

মনে রাখবেন যে কাউন্টার হিসাবে পরিবেশন করার জন্য ক্রমবর্ধমান স্ট্রিংটি নিযুক্ত করা হয়েছে কারণ in (শব্দগুলি ...) বিল্টিন একটি আরবিক গণনা সরবরাহ করতে পারে তবে এটি অন্যথায় গণিত ক্রিয়াকলাপকে সমর্থন করে না (আপনি কোনও কিছুতে 1 + 1 নির্ধারণ করতে পারবেন না এবং 2 পান, যদি না আপনি শেল থেকে আপনার জন্য এটি সম্পাদন করার জন্য কিছু অনুরোধ করছেন বা সমান সংশ্লেষিত ম্যাক্রো অপারেশন ব্যবহার করছেন)। এটি একটি অবৈতনিক কাউন্টারের জন্য দুর্দান্ত কাজ করে, তবে কোনও এক অস্বীকারকারীর পক্ষে এটি এতটা ভাল নয়।

আমি এটি নিজেই ব্যবহার করি না, তবে সম্প্রতি, মাল্টি-বাইনারি, মাল্টি-লাইব্রেরি বিল্ড এনভায়রনমেন্ট যেখানে আপনার অন্য লাইব্রেরিগুলি আনার জন্য আপনাকে জানতে হবে যেখানে লাইব্রেরি নির্ভরতা মূল্যায়নের জন্য একটি পুনরাবৃত্ত ফাংশন লিখতে হয়েছিল যখন আপনি কিছু লাইব্রেরি অন্তর্ভুক্ত করেন যা নিজেই অন্যান্য নির্ভরতা রয়েছে (যার কয়েকটি বিল্ড প্যারামিটারের উপর নির্ভর করে পরিবর্তিত হয়) এবং আমি উপরের মতো একটি $ (ইভাল) এবং কাউন্টার পদ্ধতি ব্যবহার করি (আমার ক্ষেত্রে, কাউন্টারটি কোনওভাবেই অন্তহীন না হয়ে যায় তা নিশ্চিত করার জন্য কাউন্টারটি ব্যবহার করা হয়) লুপ এবং কতগুলি পুনরাবৃত্তি প্রয়োজনীয় ছিল তা জানার জন্য ডায়াগনস্টিক হিসাবেও)।

অপার কিসের জন্য মূল্যবান কিছু না, যদিও ওপি'র কিউর জন্য তাৎপর্যপূর্ণ নয়: $ (alওয়াল ...) বিজ্ঞপ্তি সংক্রান্ত রেফারেন্সগুলিকে মেকের অভ্যন্তরীণ ঘৃণা বাধা দেওয়ার জন্য একটি পদ্ধতি সরবরাহ করে, যা ভেরিয়েবল একটি ম্যাক্রোর ধরণের (কার্যকরভাবে অন্তর্নিহিত) কার্যকর করার জন্য সমস্ত কার্যকর এবং সূক্ষ্ম =), একটি তাত্ক্ষণিক কার্যভার (বনাম: =) দিয়ে শুরু করুন) আপনি তার নিজের কার্যভারের মধ্যে একটি ভেরিয়েবল ব্যবহার করতে সক্ষম হতে চান এমন সময় রয়েছে এবং $ (ইভাল ...) আপনাকে এটি করতে সক্ষম করবে। এখানে গুরুত্বপূর্ণ বিষয়টি বিবেচনা করার বিষয়টি হ'ল আপনি যখন চালান চালাবেন তখন চলকটি সমাধান হয়ে যায় এবং যে অংশটি সমাধান হয় সেটিকে আর ম্যাক্রো হিসাবে বিবেচনা করা হবে না। আপনি যদি জানেন যে আপনি কী করছেন এবং আপনি নিজের কোনও অ্যাসাইনমেন্টের আরএইচএসে একটি ভেরিয়েবল ব্যবহার করার চেষ্টা করছেন, তবে আপনি সাধারণত যেভাবেই ঘটতে চান তা এটি।

  SOMESTRING = foo

  # will error.  Comment out and re-run
  SOMESTRING = pre-${SOMESTRING}

  # works
  $(eval SOMESTRING = pre${SOMESTRING}

default:
  @echo ${SOMESTRING}

হ্যাপি মেকিং '


20

ক্রস-প্ল্যাটফর্ম সহায়তার জন্য, কমান্ড বিভাজক (একই লাইনে একাধিক কমান্ড কার্যকর করার জন্য) কনফিগারযোগ্য করুন।

উদাহরণস্বরূপ আপনি যদি উইন্ডোজ প্ল্যাটফর্মে MinGW ব্যবহার করেন তবে কমান্ড বিভাজকটি হ'ল &:

NUMBERS = 1 2 3 4
CMDSEP = &
doit:
    $(foreach number,$(NUMBERS),./a.out $(number) $(CMDSEP))

এটি এক লাইনে সংক্ষিপ্ত আদেশগুলি কার্যকর করে:

./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 &

যেমন অন্য কোথাও উল্লেখ করা হয়েছে, * নিক্স প্ল্যাটফর্ম ব্যবহারে CMDSEP = ;


7

এটি আসলে প্রশ্নের খাঁটি উত্তর নয়, তবে এই জাতীয় সমস্যাগুলি সমাধান করার একটি বুদ্ধিমান উপায়:

একটি জটিল ফাইল লেখার পরিবর্তে, কেবল উদাহরণস্বরূপ একটি বাশ স্ক্রিপ্ট যেমন: মেকফিলের নিয়ন্ত্রণ নিয়ন্ত্রণ করুন

foo : bar.cpp baz.h
    bash script.sh

এবং স্ক্রিপ্ট.শ দেখতে দেখতে:

for number in 1 2 3 4
do
    ./a.out $number
done

মেকফিল লেখার সময় আমি এক ধাপে আটকে গিয়েছি। আমার কাছে নিম্নলিখিত কোড রয়েছে: সেট_ওয়ার: @ NUM = 0; [[$$ NUM <1]] এর সময়; "আমি এখানে আছি"; cho প্রতিধ্বনি $$ NUM ডাম্প {{NUM} .txt; \ var = "SSA_CORE $$ $$ NUM} _MAINEXEC"; \ প্রতিধ্বনি $$ var; \ var1 = eval echo \$${$(var)}; \ প্রতিধ্বনি $$ var1; \ ((NUM = NUM ​​+ 1)); all সব সম্পন্ন করেছেন: এখানে_সেট_ভার এখানে এসএসএ_সিআরইসি_আরএইএক্সইসিইসি একটি পরিবেশগত পরিবর্তনশীল যা ইতিমধ্যে সেট করা আছে o সুতরাং আমি এই মানটি ভেরিয়েবল ভেরিয়েবল ব্যবহার করে মূল্যায়ন করতে বা মুদ্রণ করতে চাই। আমি এটি উপরে দেখানো মত চেষ্টা করেছি কিন্তু কাজ করছি না। সাহায্য করুন.
XYZ_Linux

2
এটি প্রকৃতপক্ষে একটি সহজ কাজ, তবে এটি আপনাকে প্রক্রিয়াগুলিকে সমান্তরালভাবে চালানোর জন্য দুর্দান্ত "মেক-জে 4" বিকল্পটি ব্যবহার থেকে বিরত রাখে।
তাবেইকিচকা

1
@ টেবিকিছকা: সত্যই। এটি " প্রস্তাবিত " উপায় ছিল না , তবে এটির অর্থ হ'ল যদি কারও যদি এমন কোনও বৈশিষ্ট্য প্রয়োজন হয় যা মেকফাইল দ্বারা প্রদত্ত না হয় তবে কোনওটি প্রয়োগের ক্ষেত্রে ফলব্যাক করতে পারে bashএবং এই বৈশিষ্ট্যগুলি ব্যবহার করতে পারে। লুপটি এমন বৈশিষ্ট্যগুলির মধ্যে একটি যা এটি প্রদর্শিত হতে পারে।
উইলেম ভ্যান অনসেম

4

আপনি ব্যবহার করতে পারেন:

xxx:
    for i in `seq 1 4`; do ./a.out $$i; done;

3

আপনি set -eলুপের জন্য উপসর্গ হিসাবে ব্যবহার করতে পারেন । উদাহরণ:

all:
    set -e; for a in 1 2 3; do /bin/false; echo $$a; done

makeএকটি প্রস্থান কোড সহ অবিলম্বে প্রস্থান করবে <> 0


0

যদিও GNUmake টেবিল টুলকিটটির সত্যিকারের whileলুপ রয়েছে (তার কার্যকর প্রয়োগের দুটি বা তিনটি পর্যায় সহ GNUmake প্রোগ্রামিংয়ের অর্থ যা কিছু), যদি প্রয়োজনীয় জিনিসটি পুনরুক্তিযুক্ত তালিকার সাথে থাকে তবে একটি সহজ সমাধান রয়েছে interval। এর মজাদার জন্য, আমরা সংখ্যাগুলি হেক্সেও রূপান্তর করি:

include gmtt/gmtt.mk

# generate a list of 20 numbers, starting at 3 with an increment of 5
NUMBER_LIST := $(call interval,3,20,5)

# convert the numbers in hexadecimal (0x0 as first operand forces arithmetic result to hex) and strip '0x'
NUMBER_LIST_IN_HEX := $(foreach n,$(NUMBER_LIST),$(call lstrip,$(call add,0x0,$(n)),0x))

# finally create the filenames with a simple patsubst
FILE_LIST := $(patsubst %,./a%.out,$(NUMBER_LIST_IN_HEX))

$(info $(FILE_LIST))

আউটপুট:

./a3.out ./a8.out ./ad.out ./a12.out ./a17.out ./a1c.out ./a21.out ./a26.out ./a2b.out ./a30.out ./a35.out ./a3a.out ./a3f.out ./a44.out ./a49.out ./a4e.out ./a53.out ./a58.out ./a5d.out ./a62.out

0

একটি সাধারণ, শেল / প্ল্যাটফর্ম-স্বতন্ত্র, খাঁটি ম্যাক্রো সমাধান হ'ল ...

%sequence = $(if $(word ${1},${2}),$(wordlist 1,${1},${2}),$(call %sequence,${1},${2} $(words _ ${2})))

$(foreach i,$(call %sequence,10),$(info ./a.out ${i}))

-1
#I have a bunch of files that follow the naming convention
#soxfile1  soxfile1.o  soxfile1.sh   soxfile1.ini soxfile1.txt soxfile1.err
#soxfile2  soxfile2.o   soxfile2.sh  soxfile2.ini soxfile2.txt soxfile2.err
#sox...        ....        .....         ....         ....        ....
#in the makefile, only select the soxfile1.. soxfile2... to install dir
#My GNU makefile solution follows:
tgt=/usr/local/bin/          #need to use sudo
tgt2=/backup/myapplication/  #regular backup 

install:
        for var in $$(ls -f sox* | grep -v '\.' ) ; \
        do \
                sudo  cp -f $$var ${TGT} ;     \
                      cp -f  $$var ${TGT2} ;  \
        done


#The ls command selects all the soxfile* including the *.something
#The grep command rejects names with a dot in it, leaving  
#My desired executable files in a list. 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.