3

私にはこの種のルールがあります:

"foo" *> \out do
  need something
  create "foo" somehow

正しくビルドされており、ビルドを2回実行してもターゲットはビルドされません。次に、このルールにシステムを追加します。

"foo" *> \out do
  ...
  system' something

依存関係が変更されていないため、shakeを実行しても「foo」ターゲットは再構築されません。とにかく、ルールが変わりました。したがって、新しく追加されたシステムのアクションによってルールの履歴が変更され、「foo」の再構築が強制されることを期待していますが、そうではありませんでした。通常、autoconf / automakeシステムでは、または重要なmakefileでも、ルールはMakefile自体に依存しているため、Makefileが変更されるたびに、プロジェクトが再構築されます。Shakeでは、これが機能し、きめが細かいことを期待しています。

システムのソースコードでは、実行中のコマンドに暗黙の依存関係を追加するものは何も表示されません。

私は何か間違ったことをしていますか?この種の依存関係をサポートしないことは意図的ですか、それとも単に実装されていませんか?

4

1 に答える 1

2

あなたが見ている振る舞いは予想されたものであり、ICFP 2012のペーパーS6.2は、それに対処するためのいくつかの戦略を概説しています。各出力がそれを構築するために使用されたルールに依存している場合は理想的ですが、ルール(実行中にソースコードが利用できない関数)に対してある程度の同等性が必要です。いつの日か、Shakeがあなたの説明どおりに機能することを願っていますが、GHCでは現時点では不可能だと思います。

ビルドシステムの変更の数を最小限に抑えるために、定期的に変更されると思われるものはすべてビルドシステムから除外するのが最善です。ファイルのリスト(たとえば、C実行可能ファイルをリンクするために必要なファイル)は、構成ファイルに入れるか、oracleメカニズムを使用して適切に依存させることができます。

もちろん、ルールはまだ時々変更されます、そしてあなたが取ることができる2つのアプローチがあります:

何かが変わったら、すべてを再構築します

多くのMakefileで採用されているように、単純で保守的なアプローチは、何かが変更された場合にすべてを再構築することです。この戦略を実装する簡単な方法は、Shakeスクリプトをハッシュし、それをshakeVersionフィールドとして使用することです。適度に迅速に再構築するプロジェクトの場合、これはうまく機能します。

手動制御で再構築

大規模なプロジェクトの場合、ビルドシステムは日々流動的ですが、ビルドシステムのほとんどの部分はほとんどのルールに影響を与えません。一部のルールでは、ルール内に明示的にneedいくつかのソースファイルがあります。たとえば、ファイル内に大きなジェネレーターがある場合need、生成された出力を生成するルール内でそれを行います。生成されたファイルの書き込みにも使用する場合writeFileChanged、ジェネレーターに多くの変更を加えると、最小限の再構築しか発生しません。

変更がより侵襲的である場合は、手動でshakeVersionフィールドをインクリメントし、完全な再構築を強制します。適切な依存関係の追跡を備えた成熟したビルドシステムでは、このイベントは年に数回しか発生しない可能性があります。

于 2013-02-14T22:41:59.853 に答える