最終的な目標は、まったく同じ環境でまったく同じソースから構築された2つのバイナリを比較し、それらが実際に機能的に同等であることを確認できるようにすることです。
このための1つのアプリケーションは、リリース間で実際に変更されたものにQA時間を集中させることと、一般的な変更の監視です。
PE形式と連携したMSVCは、当然これを行うのを非常に困難にします。
これまでのところ、私はそれらのものを見つけて中和しました:
- PEタイムスタンプとチェックサム
- デジタル署名ディレクトリエントリ
- デバッガーセクションのタイムスタンプ
- PDBの署名、経過時間、ファイルパス
- リソースのタイムスタンプ
- VS_VERSION_INFOリソース内のすべてのファイル/製品バージョン
- デジタル署名セクション
私はPEを解析し、それらすべてのオフセットとサイズを見つけ、バイナリを比較するときにバイト範囲を無視します。チャームのように機能します(まあ、私が実行したいくつかのテストでは)。Win Server 2008でビルドされたバージョン1.0.2.0の署名された実行可能ファイルは、コンパイラのバージョンとすべてのソースとヘッダーが同じである限り、WinXP開発ボックスでビルドされたバージョン10.6.6.6の署名されていない実行可能ファイルと同じであることがわかります。これはVC7.1-9.0で機能するようです。(リリースビルドの場合)
注意点が1つあります。
両方のビルドの絶対パス は同じである 必要があり、同じ長さである必要があります。
cl.exeは相対パスを絶対パスに変換し、コンパイラフラグなどとともにオブジェクトに直接配置します。これは、バイナリ全体に不均衡な影響を及ぼします。パスを1文字変更すると、.textセクション全体で1バイトが何度か変更されます(ただし、リンクされているオブジェクトの数は多いと思います)。パスの長さを変更すると、大幅に多くの違いが生じます。objファイルとリンクされたバイナリの両方。
コンパイルフラグ付きのファイルパスが何らかのハッシュとして使用されているように感じます。これにより、リンクされたバイナリになり、コンパイルされたコードの無関係な部分の配置順序に影響を与えることさえあります。
それで、ここに3部構成の質問があります(「今何?」として要約されます):
私がやろうとしていることは、MSの物理法と企業方針に違反しているので、プロジェクト全体を放棄して家に帰るべきですか?
絶対パスの問題を(ポリシーレベルで、または魔法のコンパイラフラグを見つけることによって)処理すると仮定すると、他に注意すべき点はありますか?(__TIME__のようなものは変更されたコードを意味するので、無視されなくてもかまいません)
コンパイラに相対パスを使用させる方法、またはパスが実際のパスではないと思わせる方法はありますか?
最後の理由は、美しく迷惑なWindowsファイルシステムです。いくつかのギグに相当するソースとオブジェクトをいつ削除するかはわかりません。不正なファイルロックが原因でsvnメタデータが失敗します。少なくとも、スペースが残っている間は、新しいルートの作成は常に成功します。一度に複数のビルドを実行することも問題です。大量のVMを実行することは、解決策ではありますが、かなり重いものです。
プロセスとその子の仮想ファイルシステムをセットアップして、複数のプロセスツリーが同時にプライベートな異なる「C:\build」ディレクトリを表示するようにする方法があるのではないかと思います...ライト-ある種のウェイト仮想化...
更新:最近、GitHubでツールをオープンソース化しました。ドキュメントの比較セクションを参照してください。