私はMakefileを使います。
ビルドターゲットを実行するrun
というターゲットがあります。簡単に言うと、次のようになります。
prog: ....
...
run: prog
./prog
座ってください。これは独創的ですが、スタンディングオベーションは必要ありません。
さて、私の質問は - 引数を渡す方法はありますか?そのため
make run asdf --> ./prog asdf
make run the dog kicked the cat --> ./prog the dog kicked the cat
ありがとうございます。
私はあなたが望むことを正確に行う方法を知りませんが、回避策は次のようになります。
run: ./prog
./prog ${ARGS}
その後:
make ARGS="asdf" run
この質問はほぼ3歳ですが、とにかく...
あなたがGNU makeを使っているなら、これは簡単です。唯一の問題は、make
がコマンドラインのオプション以外の引数をターゲットとして解釈することです。解決策はそれらを何もしないターゲットに変えることなので、make
は文句を言わないでしょう:
# If the first argument is "run"...
ifeq (run,$(firstword $(MAKECMDGOALS)))
# use the rest as arguments for "run"
RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
# ...and turn them into do-nothing targets
$(eval $(RUN_ARGS):;@:)
endif
prog: # ...
# ...
.PHONY: run
run : prog
@echo prog $(RUN_ARGS)
これを実行すると以下のようになります。
$ make run foo bar baz
prog foo bar baz
以下のように変数をMakefileに渡すことができます。
run:
@echo ./prog $$FOO
使用法:
$ make run FOO="the dog kicked the cat"
./prog the dog kicked the cat
または
$ FOO="the dog kicked the cat" make run
./prog the dog kicked the cat
あるいは、 Beta が提供する解決策を使用してください。
run:
@echo ./prog $(filter-out $@,$(MAKECMDGOALS))
%:
@:
使用法:
$ make run the dog kicked the cat
./prog the dog kicked the cat
TL; DRはこれを試みません
$ make run arg
代わりにスクリプトを作成してください。
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
そしてこれを行う:
$ ./buildandrunprog.sh arg
述べられた質問に対する答え:
レシピで変数を使うことができます
run: prog
./prog $(var)
それから引数として変数代入を渡します
$ make run var=arg
これは./prog arg
を実行します。
しかし落とし穴には注意してください。このメソッドと他のメソッドの落とし穴についてさらに詳しく説明します。
質問の背後にある想定された意図に答えてください。
前提条件:いくつかの引数を指定してprog
を実行しますが、必要に応じて実行前に再構築してください。
答え:必要ならば再構築するスクリプトを作成し、その後argsでprogを実行する
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
このスクリプトはその意図を明確にしています。それはmakeを使ってそれが良いことをします。シェルスクリプトを使用して、適切なことを実行します。バッチ処理。
呼び出し構文も実質的に同一です。
$ ./buildandrunprog.sh foo "bar baz"
と比較します。
$ ./prog foo "bar baz"
加えて、シェルスクリプトの完全な柔軟性と表現力を活かして、メイクファイルに関する注意をすべて払わなくても、他に必要なことをすべて実行できます。
バックグラウンド:
makeは、ターゲットを実行してそのターゲットに引数を渡すようには設計されていません。コマンドライン上のすべての引数は、ゴール(別名ターゲット)、オプション、または変数割り当てとして解釈されます。
あなたがこれを実行するならば:
$ make run foo bar --wat var=arg
makeはrun
、foo
、およびbar
をレシピに従って更新する目標(ターゲット)として解釈します。 makeのオプションとしての--wat
。変数代入としてvar=arg
。
詳細については、 https://www.gnu.org/software/make/manual/html_node/Goals.html#Goals を参照してください。
用語については、 https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html#Rule-Introduction を参照してください。
変数の割り当て方法について、そしてなぜ私はそれに対してお勧めですか
$ make run var=arg
レシピ内の変数
run: prog
./prog $(var)
これは、レシピに引数を渡すための最も「正しい」直接的な方法です。しかし、それは引数付きでプログラムを実行するために使用することができますが、それは確かにそのように使用されるようには設計されていません。 https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding を参照してください。
私の意見では、これには大きな欠点が1つあります。あなたがやりたいことは、引数prog
を付けてarg
を実行することです。しかし書く代わりに:
$ ./prog arg
あなたは書いている:
$ make run var=arg
複数の引数やスペースを含む引数を渡そうとすると、これはさらに厄介になります。
$ make run var="foo bar\ baz"
./prog foo bar\ baz
argcount: 2
arg: foo
arg: bar baz
と比較します。
$ ./prog foo "bar baz"
argcount: 2
arg: foo
arg: bar baz
レコードのためにこれは私のprog
がどのように見えるかです:
#! /bin/sh
echo "argcount: $#"
for arg in "$@"; do
echo "arg: $arg"
done
makefileの中で$(var)
を引用符で囲むと、次のようになります。
run: prog
./prog "$(var)"
prog
は常にただ一つの引数を取ります:
$ make run var="foo bar\ baz"
./prog "foo bar\ baz"
argcount: 1
arg: foo bar\ baz
こういうわけで私はこのルートに対してお勧めします。
完全を期すために、 "make runに引数を渡す"他の方法をいくつか示します。
方法1:
run: prog
./prog $(filter-out $@, $(MAKECMDGOALS))
%:
@true
超簡単な説明:目標のリストから現在の目標を除外します。キャッチオールターゲット(%
)を作成してください。
方法2:
ifeq (run, $(firstword $(MAKECMDGOALS)))
runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
$(eval $(runargs):;@true)
endif
run:
./prog $(runargs)
超簡単な説明:ターゲットがrun
の場合、最初のゴールを削除し、eval
を使用して残りのゴールに対して何もターゲットを作成しないでください。
より深い説明のためにmakeのマニュアルを研究してください: https://www.gnu.org/software/make/manual/html_node/index.html
方法1の問題
ダッシュで始まる引数はmakeによって解釈され、目標として渡されません。
$ make run --foo --bar
workaround
$ make run -- --foo --bar
引数が偶然run
(ターゲットと等しい)である場合、それも削除されます
$ make run foo bar run
./prog foo bar
の代わりに./prog foo bar run
を実行します
方法2で可能な回避策
引数が正当なターゲットであれば、それも実行されます。
$ make run foo bar clean
./prog foo bar clean
を実行しますが、ターゲットclean
のレシピも実行します(存在すると仮定して)。
方法2で可能な回避策
スペースで引数を渡すのは面倒です
$ make run foo "bar\ baz"
回避策なし
正当なターゲットを誤入力した場合、それはcatch allターゲットのために静かに無視されます。
$ make celan
celan
を黙って無視するだけです。
回避策はすべてを冗長にすることです。それで、あなたは何が起こるかわかります。しかし、それは合法的な出力に対して多くのノイズを生み出します。
方法2の問題点
引数が既存のターゲットと同じ名前の場合、makeはそれが上書きされているという警告を表示します。
私が知っている回避策はありません
スペースで引数を渡すことはまだ厄介です。
回避策なし
スペースを含む引数は、作成しようとするeval
を中断し、ターゲットは何もしません。
回避策:グローバルキャッチオールターゲットを作成し、上記のように何もしない。上記のような問題で、タイプミスされた合法的なターゲットを再び静かに無視するでしょう。
実行時にeval
を使用してメイクファイルを変更します。読みやすさとデバッグのしやすさ、そして 最小の驚きの原則 の観点から、どれだけさらに悪いことができるのでしょう。
回避策:これをしないでください!! 1代わりにmakeを実行してからprog
を実行するシェルスクリプトを作成します。
gNU makeを使ってテストしただけです。他の機種では動作が異なる場合があります。
TL; DRはこれを試みません
$ make run arg
代わりにスクリプトを作成してください。
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
そしてこれを行う:
$ ./buildandrunprog.sh arg
これらのユースケースのいくつかを助けることができるもう一つの解決策はここにあります:
test-%:
$(PYTHON) run-tests.py $@
言い換えれば、何らかの接頭辞(この場合はtest-
)を選択してから、ターゲット名を直接プログラム/ランナーに渡します。ターゲット名を基礎となるプログラムに役立つものにアンラップできる何らかのランナースクリプトが含まれている場合、これはほとんど役に立ちます。
いいえ。GNU makeのマニュアルページの構文を見てください。
make [-f makefile] [options] ... [targets] ...
複数のターゲットを指定できるので、 'no'(少なくとも、指定したとおりにno)と指定することはできません。
コマンドラインで各n番目の引数を明示的に抽出できます。これを行うには、変数MAKECMDGOALSを使用できます。これは、 'make'に指定されたコマンドライン引数のリストを保持し、これをターゲットのリストとして解釈します。 n番目の引数を抽出する場合は、その変数を "Word"関数と組み合わせて使用できます。たとえば、2番目の引数が必要な場合は、次のように変数に格納できます。
second_argument := $(Word 2, $(MAKECMDGOALS) )
それほど誇りに思っているわけではありませんが、環境変数を渡したくなかったので、既製のコマンドを実行する方法を逆にしました。
run:
@echo command-you-want
これは実行したいコマンドを表示するので、サブシェルで評価してください。
$(make run) args to my command
これが私の例です。私はDev-Cppに同梱されているmingw32-make.exeを使って、Windows 7で書いていることに注意してください。 (私はc:\ Windows\System32\make.batを持っているので、コマンドはまだ "make"と呼ばれています。)
clean:
$(RM) $(OBJ) $(BIN)
@echo off
if "${backup}" NEQ "" ( mkdir ${backup} 2> nul && copy * ${backup} )
定期的な清掃のための用法:
make clean
Mydir /でバックアップをクリーニングして作成するための使用法
make clean backup=mydir
anon、run: ./prog
は右側がターゲットになるはずなので少し変に見えます、それでrun: prog
はよりよく見えます。
私は簡単にお勧めします:
.PHONY: run
run:
prog $(arg1)
引数を渡すことができるということを付け加えたいと思います。
make arg1="asdf" run
arg1="asdf" make run
私が使用しているもう1つのトリックは-n
フラグです。これはmake
にドライランを実行するよう指示します。例えば、
$ make install -n
# Outputs the string: helm install stable/airflow --name airflow -f values.yaml
$ eval $(make install -n) --dry-run --debug
# Runs: helm install stable/airflow --name airflow -f values.yaml --dry-run --debug