web-dev-qa-db-ja.com

"make"のインクリメンタルビルドがハッシュアルゴリズムを使用しないのはなぜですか?

私はmakeの初心者であり、make cleanをいつ使用するかについて疑問に思っています。

ある同僚は、makeを使用したインクリメンタルビルドはファイルのタイムスタンプに基づいていると私に言った。そのため、VCSで古いバージョンのファイルをチェックアウトすると、そのファイルには「古い」タイムスタンプが付けられ、「このファイルを再コンパイルする必要はありません」とマークされます。その後、そのファイルは次のビルドに含まれません。
同じ同僚によれば、make cleanを使用するのはそのためです。

とにかく、私は他のStackExchangeの質問から「make cleanを使用するタイミング」という質問への回答を大まかに得ましたが、他の質問は次のとおりです。

makeを使用したインクリメンタルビルドが、たとえばSHA-1ではなくファイルのタイムスタンプに依存するのはなぜですか?たとえば、Gitは、SHA-1を使用してファイルが変更されたかどうかを正常に判断できることを示しています。
速度の問題ですか?

10
filaton

明白な(そしておそらく表面的な)問題は、ビルドシステムが最後のビルドに使用されたファイルのハッシュの記録を保持しなければならないことです。この問題は確実に解決できますが、タイムスタンプ情報がファイルシステムにすでに存在する場合は、サイドストレージが必要になります。

しかし、もっと真剣に、ハッシュは同じセマンティクスを伝えません。そのファイルを知っている場合 T 依存関係から構築されました D ハッシュ付き H1 そしてそれを見つける D 今ハッシュする H2、再構築する必要があります T?おそらくそうですが、それもそうかもしれません H2 実際には、ファイルの古いバージョンを指します。タイムスタンプは順序を定義しますが、ハッシュは同等である場合にのみ比較できます。

タイムスタンプがサポートする機能は、touchをだまして次のことを考えさせるために、タイムスタンプを単に更新できることです(たとえば、POSIXコマンドラインユーティリティ make を使用)。依存関係が変更された、または興味深いことに、ターゲットが実際よりも新しい。これで遊ぶことは足に自分を撃つ絶好の機会ですが、時々役立ちます。ハッシュベースのシステムでは、実際には何もビルドせずに、最後のビルドに使用されたハッシュの内部データベースを更新するために、ビルドシステム自体からのサポートが必要になります。

タイムスタンプよりもハッシュを使用することについては確かに議論の余地はありますが、私の目標は、同じ目標を達成するためのより良い解決策ではなく、異なる目標を達成するための異なる解決策であるということです。これらの目標のどちらが望ましいかは、議論の余地があります。

7
5gon12eder

ビルドシステムのハッシュとタイムスタンプに関するいくつかのポイント:

  1. ファイルをチェックアウトすると、タイムスタンプが現在の時刻に更新され、再構築がトリガーされます。同僚が説明するのは、通常、タイムスタンプシステムの障害モードではありません。
  2. タイムスタンプはハッシュよりわずかに高速です。タイムスタンプシステムはタイムスタンプのみをチェックする必要がありますが、ハッシュシステムはタイムスタンプをチェックし、次にハッシュをチェックする必要があります。
  3. Makeは軽量で自己完結型になるように設計されています。 (2)を克服するために、ハッシュベースのシステムは通常、ハッシュをチェックするためのバックグラウンドプロセスを実行します(例:Facebookの ウォッチマン )。これは、Makeの設計目標(および履歴)に反しています。
  4. ハッシュは、タイムスタンプが変更されたが内容は変更されなかった場合に、不要な再構築を防止します。多くの場合、これはハッシュを計算するコストを相殺します。
  5. ハッシュを使用すると、アーティファクトキャッシュをプロジェクト間およびネットワーク経由で共有できます。繰り返しますが、これはハッシュの計算コストを相殺する以上のものです。
  6. 最新のハッシュベースのビルドシステムには、 Bazel (Google)および Buck (Facebook)が含まれます。
  7. Makeが設計されたときと同じ要件がないため、ほとんどの開発者はハッシュベースのシステムの使用を検討する必要があります。
1
sdgfsdh

プロジェクト全体のハッシュは非常に遅いです。すべてのファイルのすべての1バイトを読み取る必要があります。 Gitは、git statusを実行するたびにすべてのファイルをハッシュするわけではありません。また、VCSチェックアウトは通常、ファイルの変更時刻を元の作成時刻に設定しません。バックアップを復元する場合は、注意してください。ファイルシステムにタイムスタンプがあるのは、このようなユースケースのためです。

依存関係がMakefileの変更によって直接追跡されない場合、開発者は通常make cleanを実行します。皮肉なことに、これには通常Makefile自体が含まれます。通常、コンパイラのバージョンも含まれます。 Makefileの作成状況によっては、外部ライブラリのバージョンを含めることができます。

これらは、バージョン管理の更新を行うときに更新される傾向がある種類のことなので、ほとんどの開発者はmake cleanを同時に実行する習慣を身に付けるだけなので、クリーンな状態から開始できます。スレート。多くの場合それをしなくても逃げることができますが、できない時間を予測することは本当に難しいです。

1
Karl Bielefeldt