2017-11-21 23 views
3

Javaコードをコンパイルしています。ファイル名にドル記号がある場所で.classファイルを作成することがよくあります。 GNU makeはこれを嫌うようで、ファイル名に干渉し続けます。GNU makeがドル記号を含むファイル名に干渉しないようにするにはどうすればよいですか?

単純な(工夫した)例として、MyFolderディレクトリ(およびサブフォルダ)内のすべての.classファイルに対してhexdumpを実行するGNU Makefileタスクを作成したいとします。

今はMyFolderは、以下のファイルがあるとします。

MyFolder/makefile 
MyFolder/sample.java 
MyFolder/subdir/abc$1.class 
MyFolder/subdir/test.java 
MyFolder/xyz.class 

目標はhexdumpに対してを実行しているレシピを書くことで、MyFolderという(およびそのサブフォルダ)内のすべての.classファイルを渡します。だから、ファイルの上記のリストについては、GNUは、実行する必要が作るであろうと、最終的なコマンド:

hexdump subdir/abc$1.class xyz.class 

これは、ログから落ちるように簡単なはずですが、GNUのmakeはこれを作るために、極端な痛みに行っているようですできるだけ難しい。次のMakefileを持つ素朴な試みが動作しません:

default: 
    hexdump $(shell find -name '*.class') 

あなたはこのMakefileを実行すると、次のエラーを取得:どのように上記の出力の最初の行では、コマンド

hexdump ./subdir/abc$1.class ./xyz.class 
hexdump: ./subdir/abc.class: No such file or directory 
make: *** [makefile:3: default] Error 1 

お知らせ正しいです(ファイル名にはドル記号文字が含まれています)。しかし実際に実行されるコマンドは実行され、 "$ 1"は評価されています。

実際、ドル記号を二重ドル記号で正しくエスケープすると、次のMakefileでさえ失敗します。もちろん、私がいないハードコードのファイル名をしてレシピを書きたいが、ファイルは

default: 
    hexdump subdir/abc$$1.class xyz.class 

がさえ、上記のMakefileが同じで失敗コマンド(...シェルが見つける。)$で発見されなければなりません最初のMakefileとしてのエラー。

ドル記号を含むファイル名にGNU makeが干渉しないようにするにはどうすればよいですか? Javaコンパイラはこれらのことを常に作成していますので、誰かがこれまでに実行していたに違いないでしょうか?

答えて

4

レシピにこの方法を使用する場合、メイクが再び$(shell …)出力を解釈しませんので、動作しますあなたの最後のコマンドは次のようなものになるだろう。問題は、シェル$1を解釈し、空の文字列である最初の(存在しない)パラメータに展開することです。

この問題を解決する方法は、この問題が発生したときの処理内容によって異なります。 GNU makeは任意のシェルクォート関数を提供しておらず、とにかく空白を含むファイル名に問題があります。あなたは、おそらく'でファイル名を囲むことにより、Javaクラスファイルのパラメータ置換を避けるために、これを試みることができる:

hexdump $(patsubst %,'%',$(shell find -name '*.class')) 

別のアプローチは、のようなものを使用して、シェル内のファイルリストを作成するには、次のようになります。

find -name -print0 | xargs -0 hexdump 

これは、シェルによる文字列の解釈を完全に回避します。コマンド置換の出力はパラメータ置換単語分割とパス名展開(グロブ)にのみ対象となりますが、ないのででも

hexdump $$(find -name '*.class') 

とシェルは、ファイル名に$兆候を解釈しないでしょう。

+0

私たちの状況のた​​めの最良の解決策は、シェル内で$$を使用してリストを作成することでした( )構文です。説明ありがとう。 – deltamind106

1

まず、出力ファイルにこのような愚かな命名規則を選んだのは、実際にはJavaの問題です。

第2に、makeを使ってJavaコードを作成しようとすると、ほぼ確実に欲求不満の練習になります。 Makeはメインファイルを入力とし、1つのファイルを出力として生成するツールでうまく動作するように構築されています。出力ファイル名は入力ファイル名に関連しています。 Javaはそうではありません。

しかし、あなたの質問に直接答えるには、$はmake変数を導入するために作成する特殊文字です。最後の例のように$$でエスケープする必要があります。 $はシェルにとって特別なもあるので

しかし、それは十分ではありませんので、あなたがレシピで$を使用する場合は、単一引用符やバックスラッシュのいずれかを使用して、シェルからそれをエスケープする必要があります。

default: 
     hexdump 'subdir/abc$$1.class' xyz.class 

か::

default: 
     hexdump subdir/abc\$$1.class xyz.class 
+0

これは、$(shell find ...)や他のメカニズムを使って実際にすべての一致するファイルを見つけ出すにはどうしたらいいですか? – deltamind106

+1

レシピ内で 'shell'関数を使うべきではありません。レシピはすでにシェルなので、makeの 'shell'関数を使用しようとすると、混乱と苦痛が加えられます。あなたのシェルプロンプトにコマンドラインを書いて、正しく動作したら、それをレシピに入れ、すべての '$'を '$$'に置き換えれば完了です。 '$'を避けるために '' '' 'find -name '* .class' \' 'と書いてください。そうでなければ' $(find -name '$。'を得るために '$'をエスケープする – MadScientist

関連する問題