কোনও মেকফাইল থেকে কোনও প্রোগ্রাম উপস্থিত রয়েছে কিনা তা পরীক্ষা করে দেখুন


115

কোনও প্রোগ্রাম কোনও মেকফাইল থেকে কলযোগ্য কিনা তা আমি কীভাবে পরীক্ষা করতে পারি?

(এটি হ'ল প্রোগ্রামটি पथটিতে উপস্থিত থাকা উচিত বা অন্যথায় কলযোগ্য হওয়া উচিত))

উদাহরণস্বরূপ, কোন সংকলকটি ইনস্টল করা হয়েছে তা পরীক্ষা করতে এটি ব্যবহার করা যেতে পারে।

উদাহরণস্বরূপ এই প্রশ্নের মতো কিছু তবে অন্তর্নিহিত শেলটি পোসিক্সের সাথে সামঞ্জস্য না করে।


1
আপনি যা করতে পারেন ডাকা একটি POSIX সামঞ্জস্যপূর্ণ শেল?
রিনিয়ারপোস্ট

সম্ভবত না, আমি অনুমান করি যে আমি একজনকে সেখানে উপস্থিত থাকার দাবি করতে পারি, তবে যদি আমার না করা হয় তবে এটি আরও সহজ হত।
অধ্যাপক ফ্যালকেন

এর মধ্যে, আমি প্রকল্পটিতে একটি প্রোগ্রাম যুক্ত করে এটি সমাধান করেছি, যা প্রথমে নির্মিত এবং যার একমাত্র উদ্দেশ্য সেই অন্যান্য প্রোগ্রামটি পরীক্ষা করা ... ...-)
প্রফেসর ফ্যালকন

2
.তিহ্যগতভাবে কাজ করার জন্য একটি automakeস্ক্রিপ্ট থাকা যা বিভিন্ন পূর্বশর্ত পরীক্ষা করে এবং একটি উপযুক্ত লিখে দেয় Makefile
ট্রিপলি

উত্তর:


83

কখনও কখনও আপনার একটি মেকফিলের প্রয়োজন হয় বিভিন্ন টার্গেট ওএস এর চালাতে সক্ষম হয়ে এবং আপনি যদি বিল্ডটি ব্যর্থ PATHহওয়ার আগে সম্ভবত কার্যকর দীর্ঘ সময় চালানোর পরিবর্তে প্রয়োজনীয় নির্বাহযোগ্য না হয় তবে তাড়াতাড়ি ব্যর্থ হয়ে যেতে চান ।

ইঞ্জিনিয়ারচুয়ান দ্বারা সরবরাহিত দুর্দান্ত সমাধানের জন্য একটি লক্ষ্য তৈরি করা প্রয়োজন । তবে, যদি আপনার পরীক্ষার জন্য অনেক এক্সিকিউটেবল থাকে এবং আপনার মেকফিলের অনেকগুলি স্বতন্ত্র লক্ষ্যমাত্রা রয়েছে, যার প্রত্যেকটির পরীক্ষার প্রয়োজন হয়, তবে প্রতিটি লক্ষ্যটিকে নির্ভরতা হিসাবে পরীক্ষার লক্ষ্য প্রয়োজন। এটি যখন আপনি একবারে একাধিক লক্ষ্য তৈরি করেন তখন অতিরিক্ত টাইপিংয়ের পাশাপাশি প্রক্রিয়াজাতকরণের সময়ও তৈরি করে।

0xf দ্বারা সরবরাহিত সমাধানটি একটি লক্ষ্য না করে এক্সিকিউটেবলের জন্য পরীক্ষা করতে পারে। পৃথকভাবে বা একসাথে নির্মিত হতে পারে এমন একাধিক লক্ষ্য রয়েছে যখন এটি অনেকগুলি টাইপিং এবং সম্পাদনের সময় সাশ্রয় করে।

পরবর্তী সমাধানে আমার উন্নতি হ'ল whichএক্সিকিউটেবল ( whereউইন্ডোজে) ব্যবহার করার পরিবর্তে, --versionপ্রতিটি এক্সিকিউটেবলের মধ্যে একটি বিকল্প থাকার পরিবর্তে সরাসরি জিএনইউ-র ifeqনির্দেশে নতুন ভেরিয়েবল সংজ্ঞায়নের পরিবর্তে জিএনইউ মেক ব্যবহার করা হয় errorপ্রয়োজনীয় নির্বাহযোগ্য না থাকলে বিল্ডটি থামাতে ফাংশন ${PATH}। উদাহরণস্বরূপ, lzopএক্সিকিউটেবলের জন্য পরীক্ষা করা :

 ifeq (, $(shell which lzop))
 $(error "No lzop in $(PATH), consider doing apt-get install lzop")
 endif

আপনার যদি চেক করার জন্য বেশ কয়েকটি এক্সিকিউটেবল থাকে তবে আপনি এক্সিকিউটেবলের foreachসাথে কোনও ফাংশন ব্যবহার করতে চাইতে পারেন which:

EXECUTABLES = ls dd dudu lxop
K := $(foreach exec,$(EXECUTABLES),\
        $(if $(shell which $(exec)),some string,$(error "No $(exec) in PATH")))

:=আরএইচএস এক্সপ্রেশনটির তাত্ক্ষণিক মূল্যায়ন করার জন্য প্রয়োজনীয় অ্যাসাইনমেন্ট অপারেটরের ব্যবহারটি নোট করুন । যদি আপনার Makefile পরিবর্তন করে PATH, তবে উপরের শেষ লাইনের পরিবর্তে আপনার প্রয়োজন হবে:

        $(if $(shell PATH=$(PATH) which $(exec)),some string,$(error "No $(exec) in PATH")))

এটি আপনাকে অনুরূপ আউটপুট দেয়:

ads$ make
Makefile:5: *** "No dudu in PATH.  Stop.

2
যদি আপনি এক্সিকিউটেবলগুলি সমস্ত পরিবর্তনশীল, (যেমন এলএস সিসি এলডি) তৈরি করেন এবং $ ($ (এক্সিকিউটিভ)) ব্যবহার করেন, আপনি পরিবেশ বা অন্যান্য মেকফিলগুলি থেকে নির্বিঘ্নে এটি পাস করতে পারেন can ক্রস সংকলন করার সময় দরকারী।
রিকফুসুসা

1
আমার "," চলাকালীন "ifeq (, $ (শেল যা lzop)) এ
চোক করা উচিত

2
উইন্ডোজে, এর where my_exe 2>NULপরিবর্তে ব্যবহার করুন which
অ্যারন ক্যাম্পবেল

2
ইফেকের সাথে ট্যাবস ইন্ডেন্টেশনগুলি সম্পর্কে সতর্ক থাকুন যা একটি নিয়ম বাক্য গঠন! এটি ট্যাব ছাড়াই হওয়া উচিত। যে সঙ্গে একটি কঠিন সময় ছিল। stackoverflow.com/a/21226973/2118777
পাইপো

2
আপনি যদি ব্যবহার করছেন Bashতবে এর জন্য বাহ্যিক কল করার দরকার নেই whichcommand -vপরিবর্তে বিল্ট-ইন ব্যবহার করুন। আরও তথ্য
kurczynski

48

আমি @ টেনারব এবং @ 0 এক্সএফ থেকে সমাধানগুলি মিশ্রিত করেছি এবং এটি পেয়েছি:

DOT := $(shell command -v dot 2> /dev/null)

all:
ifndef DOT
    $(error "dot is not available please install graphviz")
endif
    dot -Tpdf -o pres.pdf pres.dot 

এটি খুব সুন্দরভাবে কাজ করে কারণ এক্সিকিউটেবলটি উপলভ্য না থাকলে "কমান্ড -v" কোনও কিছু মুদ্রণ করে না, সুতরাং ভেরিয়েবল DOT কখনই সংজ্ঞায়িত হয় না এবং আপনি যখনই নিজের কোডটিতে চান তখন এটি পরীক্ষা করতে পারেন। এই উদাহরণে আমি একটি ত্রুটি নিক্ষেপ করছি, তবে আপনি চাইলে আপনি আরও কিছু কার্যকর করতে পারেন।

যদি ভেরিয়েবলটি উপলভ্য থাকে তবে "কমান্ড -v" ডট ভেরিয়েবলটি নির্ধারণ করে কমান্ড পাথটি প্রিন্ট করার সস্তা অপারেশন সম্পাদন করে।


5
কমপক্ষে কয়েকটি সিস্টেমে (যেমন উবুন্টু 14.04) $(shell command -v dot)ব্যর্থ হয় make: command: Command not found। এটি ঠিক করতে স্ট্যাডার আউটপুটটিকে / dev / নাল: এ পুনঃনির্দেশ করুন $(shell command -v dot 2> /dev/null)ব্যাখ্যা
জে0

3
commandব্যাশ অন্তর্নির্মিত, আরও বহনযোগ্যতার জন্য, ব্যবহার বিবেচনা which?
জুলিয়েন পালার্ড

10
@JulienPalard আমি তোমাকে বিশ্বাস করি করছি ভুল: commandইউটিলিটি দ্বারা প্রয়োজন বোধ করা হয় posix (তত্সহ -vবিকল্প) অন্যদিকে whichকোন মান করেছেন bahaviour (যে আমি জানি) এবং কখনও কখনও সরাসরি হয় অব্যবহারযোগ্য
Gyom

3
command -vএকটি পসিক্সের মতো শেল পরিবেশ প্রয়োজন। এটি সাইগউইন বা অনুরূপ ইমুলেশন ছাড়াই উইন্ডোজে কাজ করবে না।
ডলমেন

10
কারণ commandপ্রায়ই কাজ করে না তার অনুপস্থিতির কারণ কিন্তু কারণ একটি এর অদ্ভুত অপ্টিমাইজেশান যে গনুহ করতে না যদি কমান্ড "সরল যথেষ্ট" হয় এটা করবে শেল বাইপাস; দুর্ভাগ্যক্রমে এর অর্থ বিল্ট-ইনগুলি কখনও কখনও কাজ করবে না যতক্ষণ না আপনি কমান্ডটি কিছুটা চাঙ্গা করেন।
রাফলেউইন্ড

33

তুমি কি করেছ?

check: PYTHON-exists
PYTHON-exists: ; @which python > /dev/null
mytarget: check
.PHONY: check PYTHON-exists

আমার সহকর্মীর কাছে কৃতিত্ব


না, আমি একটি টার্গেটে একটি প্রোগ্রাম সংকলন করেছি এবং এটি অন্যটিতে চালিয়েছি।
অধ্যাপক ফ্যালকেন

21

shellআপনার প্রোগ্রামটিকে এমনভাবে কল করতে ফাংশনটি ব্যবহার করুন যাতে এটি স্ট্যান্ডার্ড আউটপুটে কিছু প্রিন্ট করে। উদাহরণস্বরূপ, পাস --version

গনুহ মেক কমান্ড গৃহীত প্রস্থান অবস্থা উপেক্ষা করে shell। সম্ভাব্য "কমান্ড পাওয়া যায় নি" বার্তাটি এড়ানোর জন্য, মানক ত্রুটিটিকে পুনর্নির্দেশ করুন /dev/null

তারপর আপনি ব্যবহার ফলাফলের চেক করতে পারেন ifdef, ifndef, $(if)ইত্যাদি

YOUR_PROGRAM_VERSION := $(shell your_program --version 2>/dev/null)

all:
ifdef YOUR_PROGRAM_VERSION
    @echo "Found version $(YOUR_PROGRAM_VERSION)"
else
    @echo Not found
endif

বোনাস হিসাবে, আউটপুট (যেমন প্রোগ্রাম সংস্করণ) আপনার মেকফিলের অন্যান্য অংশে কার্যকর হতে পারে।


*** missing separator. Stop.আমার ত্রুটি হওয়ার পরে all:আমি যদি সমস্ত লাইনে ট্যাবগুলি যুক্ত করি তবে এটি ত্রুটি দেয়make: ifdef: Command not found
ম্যাথিয়াস 009

এছাড়াও: gnu.org/software/make/manual/make.html# শর্তসাপেক্ষে- সিন্থ্যাক্স না ifdefথাকলেও সত্য মূল্যায়ন করবেyour_program
ম্যাথিয়াস 009

1
ট্যাবস যুক্ত করবেন না ifdef, else, endifলাইন। @echoট্যাব দিয়ে লাইনগুলি শুরু হচ্ছে তা নিশ্চিত করুন ।
0xF

আমি আমার সমাধানটি উইন্ডোজ এবং লিনাক্সে পরীক্ষা করেছি। আপনি যে ডকুমেন্টেশনের সাথে লিঙ্ক করেছেন তাতে উল্লেখ করা হয়েছে যে ifdefখালি খালি ভেরিয়েবলের মান পরীক্ষা করে। আপনার পরিবর্তনশীল যদি খালি না থাকে তবে এটি কীসের সাথে মূল্যায়ন করবে?
0xF

1
@ ম্যাথিয়াস০০৯ যখন আমি জিএনইউ মেকটি v4.2.1 পরীক্ষা করি তখন ব্যবহার করে ifdefবা ifndef(গৃহীত উত্তর হিসাবে) কেবল তখনই কাজ করে যদি ভেরিয়েবলটি মূল্যায়ন করার সাথে সাথে অলস সেট ( :=) পরিবর্তে তাত্ক্ষণিক সেট করা হয় ( =)। তবে, তাত্ক্ষণিকভাবে সেট ভেরিয়েবলগুলি ব্যবহার করার একটি ক্ষয়ক্ষতি হ'ল এগুলি ঘোষণার সময় মূল্যায়ন করা হয়, যখন অলস সেট সেট ভেরিয়েবলগুলি ডাকা হয় তখন তাদের মূল্যায়ন করা হয়। এর অর্থ আপনি :=যখন মেক কেবল সেই নিয়মগুলি চালিত করেন না যেগুলি যখন ভেরিয়েবলগুলি কখনও ব্যবহার করে না তখনও আপনি ভেরিয়েবলগুলির জন্য কমান্ডগুলি সম্পাদন করবেন ! আপনি একটি ব্যবহার করে এই এড়াতে পারেন =সঙ্গেifneq ($(MY_PROG),)
ডেনিস

9

এখানে বিদ্যমান কিছু সমাধান পরিষ্কার করে ...

REQUIRED_BINS := composer npm node php npm-shrinkwrap
$(foreach bin,$(REQUIRED_BINS),\
    $(if $(shell command -v $(bin) 2> /dev/null),$(info Found `$(bin)`),$(error Please install `$(bin)`)))

$(info ...)যদি এই নীরব হতে চান আপনি বাদ পারবেন না।

এটি দ্রুত ব্যর্থ হবে । কোন লক্ষ্য প্রয়োজন।


8

আমার সমাধানটিতে সামান্য সহায়ক সহায়ক স্ক্রিপ্ট 1 জড়িত যা সমস্ত প্রয়োজনীয় কমান্ড উপস্থিত থাকলে একটি পতাকা ফাইল রাখে places এটি এই সুবিধাটি নিয়ে আসে যে প্রয়োজনীয় কমান্ডগুলির জন্য চেকটি কেবল একবার করা হয় এবং প্রতিটি makeঅনুরোধে নয়।

check_cmds.sh

#!/bin/bash

NEEDED_COMMANDS="jlex byaccj ant javac"

for cmd in ${NEEDED_COMMANDS} ; do
    if ! command -v ${cmd} &> /dev/null ; then
        echo Please install ${cmd}!
        exit 1
    fi
done

touch .cmd_ok

Makefile নামক

.cmd_ok:
    ./check_cmds.sh

build: .cmd_ok target1 target2

1command -v কৌশল সম্পর্কে আরও এখানে পাওয়া যাবে


2
আমি কেবল এটি পরীক্ষা করেছি এবং এটি কাজ করে এবং যেহেতু আপনার জন্য কী কাজ করছে না (বাশ স্ক্রিপ্ট বা মেকফিল কোড) বা কোনও ত্রুটি বার্তা আমি আপনাকে সমস্যাটি খুঁজে পেতে সহায়তা করতে পারি না সে সম্পর্কে কোনও ইঙ্গিত প্রদান করেন নি।
প্রবাহ

আমি প্রথম ifবিবৃতিতে "ফাইলের অপ্রত্যাশিত শেষ" পাচ্ছি ।
অ্যাডাম গ্রান্ট

6

আমার জন্য উপরের সমস্ত উত্তর লিনাক্সের উপর ভিত্তি করে এবং উইন্ডোগুলির সাথে কাজ করছে না। আমি তৈরি করতে নতুন তাই আমার পন্থাটি আদর্শ নাও হতে পারে। তবে সম্পূর্ণ উদাহরণ যা লিনাক্স এবং উইন্ডো উভয় ক্ষেত্রেই আমার পক্ষে কাজ করে তা হ'ল:

# detect what shell is used
ifeq ($(findstring cmd.exe,$(SHELL)),cmd.exe)
$(info "shell Windows cmd.exe")
DEVNUL := NUL
WHICH := where
else
$(info "shell Bash")
DEVNUL := /dev/null
WHICH := which
endif

# detect platform independently if gcc is installed
ifeq ($(shell ${WHICH} gcc 2>${DEVNUL}),)
$(error "gcc is not in your system PATH")
else
$(info "gcc found")
endif

allyচ্ছিকভাবে যখন আমাকে আরও সরঞ্জামগুলি সনাক্ত করতে হবে তখন আমি ব্যবহার করতে পারি:

EXECUTABLES = ls dd 
K := $(foreach myTestCommand,$(EXECUTABLES),\
        $(if $(shell ${WHICH} $(myTestCommand) 2>${DEVNUL} ),\
            $(myTestCommand) found,\
            $(error "No $(myTestCommand) in PATH)))
$(info ${K})        

আমি কখনও ভাবিনি যে কেউ ভয়ঙ্কর সেন্টিমিডি.এক্সই ... "শেল" দিয়ে জিএনইউ মেক ব্যবহার করবে।
জোহান বুলি

4

আপনি যেমন ব্যাশ নির্মিত কমান্ড ব্যবহার করতে পারেন type fooবা command -v fooনিচের যেমন:

SHELL := /bin/bash
all: check

check:
        @type foo

কোথায় fooআপনার প্রোগ্রাম / কমান্ড। আপনি > /dev/nullযদি এটি নিরব চান তবে পুনর্নির্দেশ করুন ।


হ্যাঁ, তবে বিষয়টি হ'ল আমি এটি কাজ করতে চেয়েছিলাম যখন আমার কেবল জিএনইউ তৈরি হয়েছিল তবে কোনও ব্যাশ ইনস্টল করা হয়নি।
অধ্যাপক ফ্যালকেন

3

ধরুন আপনার বিভিন্ন লক্ষ্য এবং বিল্ডার রয়েছে, প্রত্যেকের জন্য আরও একটি সরঞ্জামের সেট প্রয়োজন। এই জাতীয় সরঞ্জামগুলির একটি তালিকা সেট করুন এবং তাদের উপলভ্যতা পরীক্ষা করার জন্য জোর লক্ষ্য হিসাবে তাদের বিবেচনা করুন

উদাহরণ স্বরূপ:

make_tools := gcc md5sum gzip

$(make_tools):  
    @which $@ > /dev/null

file.txt.gz: file.txt gzip
    gzip -c file.txt > file.txt.gz 

3

আমি ব্যক্তিগতভাবে একটি requireলক্ষ্য নির্ধারণ করছি যা অন্য সকলের আগে চলে। এই লক্ষ্যটি একবারে সমস্ত প্রয়োজনীয়তার সংস্করণ কমান্ডগুলি চালায় এবং কমান্ডটি অবৈধ থাকলে উপযুক্ত ত্রুটি বার্তাগুলি মুদ্রণ করে।

all: require validate test etc

require:
    @echo "Checking the programs required for the build are installed..."
    @shellcheck --version >/dev/null 2>&1 || (echo "ERROR: shellcheck is required."; exit 1)
    @derplerp --version >/dev/null 2>&1 || (echo "ERROR: derplerp is required."; exit 1) 

# And the rest of your makefile below.

নীচের স্ক্রিপ্টের আউটপুট হয়

Checking the programs required for the build are installed...
ERROR: derplerp is required.
makefile:X: recipe for target 'prerequisites' failed
make: *** [prerequisites] Error 1

1

অন্য একটি মেকফিল টার্গেটে একটি বিশেষ ছোট প্রোগ্রাম সংকলন করে সমাধান করা, যার একমাত্র উদ্দেশ্য যা আমি রানটাইম স্টাফ সন্ধান করছি তা যাচাই করা।

তারপরে, আমি এই প্রোগ্রামটিকে অন্য একটি মেকফিল টার্গেট বলেছিলাম।

আমি যদি সঠিকভাবে স্মরণ করি তবে এটি এমন কিছু ছিল:

real: checker real.c
    cc -o real real.c `./checker`

checker: checker.c
    cc -o checker checker.c

ধন্যবাদ. তবে এই কি বাতিল করা উচিত, তাই না? গর্ভবতী হওয়া থেকে বিরত রাখা কি সম্ভব? প্রয়োজনীয় সরঞ্জাম না পাওয়া গেলে আমি একটি বিল্ড স্টেপ এড়িয়ে যাওয়ার চেষ্টা করছি ..
মার্ক-ক্রিশ্চিয়ান শুলজে

@ কোডিং.মোফ সম্পাদিত - এটি আরও এমন ছিল। প্রোগ্রামটি রানটাইমের সময় কিছু পরীক্ষা করেছে এবং সংকলনের বাকী অংশগুলিকে সেই অনুযায়ী তথ্য দিয়েছে।
অধ্যাপক ফ্যালকেন

1

সমাধানগুলির পরীক্ষা করে এমন প্রোগ্রামগুলি STDERRকার্যকর --versionহয় না যা STDOUTপরিবর্তে তাদের সংস্করণটি মুদ্রণ করে STDERR। তাদের আউটপুট STDERRবা এগুলি পরীক্ষা করার পরিবর্তে STDOUTপ্রোগ্রামের রিটার্ন কোডটি পরীক্ষা করুন। প্রোগ্রামটি উপস্থিত না থাকলে এর প্রস্থান কোডটি সর্বদা শূন্য নয় non

#!/usr/bin/make -f
# /programming/7123241/makefile-as-an-executable-script-with-shebang
ECHOCMD:=/bin/echo -e
SHELL := /bin/bash

RESULT := $(shell python --version >/dev/null 2>&1 || (echo "Your command failed with $$?"))

ifeq (,${RESULT})
    EXISTS := true
else
    EXISTS := false
endif

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