Delphiは同じプロジェクトで異なるバイナリを作成して構築する
-
19-09-2019 - |
質問
新鮮なVCLアプリケーションで コンパイル と 建てる 操作は、同じバイナリファイルとマップファイルを生成します(「プロジェクトにバージョン情報を含める」オプションがオフになっていても、.exeファイルの最後にわずかな違いがあります - すでに説明されています)。マップファイルは同じバイトからバイトです。しかし、ビルドとコンパイルによって生成されたバイナリとマップ(!)ファイルにサードパーティコンポーネントを追加します。
Delphiの2つのバージョンでテストされています:
- バージョン7.0(ビルド8.1)
-CodeGear™Rad Studio 2007バージョン11.0.2902.10471(+2007年12月の更新)
複製するためのステップ:
- 新しいVCLアプリケーションを作成します。おそらく、ネイティブのDelphiコンポーネントを追加する可能性があります(Standart、追加、Win32、およびシステムタブのすべてのコンポーネントを試してください)。
- プロジェクトオプションの[リンカー]タブの詳細なマップファイルをオンにします。
- プロジェクトを構築します.
- output .exeおよび.mapファイルの名前を変更します(例:project1.exe to project1b.exeおよびproject1.map to project1b.mapに)。
- プロジェクトをコンパイルします.
- output .exeおよび.mapファイルの名前を変更します(例:project1.exe to project1c.exeおよびproject1.map to project1c.mapに)。
- ステップ4と6のファイルを比較します(Winmerge 2.12.4.0を使用しています)。
.exeファイルと完全に同一の.mapファイルはほとんどありません。次に、すべての手順を再度繰り返しますが、プロジェクトのサードパーティコンポーネント(ODAC、DOA、DevexPress、SelfMadeを試してみてください)で使用すると、Exeと異なる.Mapファイルがより異なります。
なんで?助言がありますか?
アップデート
私がこれをどのように見つけたか、そしてそれが私に興味を持っている理由についてのいくつかの情報:
プロジェクトは、MSBuildを使用したSimple Scriptからビルドされています。プロジェクトに翻訳が追加されたとき(リソースを備えたDLL)、プロジェクトが構築されたとき(スクリプトまたはIDEから) - 翻訳バージョンが間違っていることがわかりました - ボタン、ラベルなどのテキストが間違った場所から得られました(文字通り別のものからボタン、ラベル)。 IDEからコンパイルされたプロジェクト - すべてが問題ありません。それで、私はビルドとコンパイルの出力をコンパイルし始めます...
解決
あなたが見ているのは、単に内蔵のアーティファクトであり、コンパイラのロジックを作成します。ビルドを行うと、利用可能なすべてのソースを構築するようコンパイラに指示します。したがって、Delphiは各ソースファイルを処理し、ソースを見つけた使用リストの各ユニットについて、そのファイルを構築します。これは再帰的に行います。コンパイルを実行すると、既存の.DCUファイルのみがロードされ、最新のものがわかった場合、何も行われません。これにより、各.DCUが使用リストを効果的に「平ら」するため、ユニットが発見される別の順序につながる可能性があります。ユニットは別の順序で発見され、ロードされているため、それらは折り返され、別の順序でリンクされています。これが、マップファイルが非常に異なって見える理由です。同じソースを考えると、マップファイルは、1つまたは連続して2つのビルドを連続して行う場合、同じでなければなりません。
違いの他の原因はより平凡で、PEヘッダータイムスタンプ、その他のパディングやアライメントなどが含まれます。
他のヒント
この答えには2つの部分があります。
あなたの見ている問題の一部であるIIRCは、コンパイル/ビルドを行う前にコンパイラがメモリをゼロにしないことです。したがって、非初期化されたメモリに残っているものはすべて、アラインメントのために出力のフィラーになります。
また、アプリケーションのPEヘッダー情報にデートタイムスタンプが含まれていることを思い出すようです。それは毎回違いを引き起こします。
私はこれを確認するのに最適な人ではありませんが、これは私が過去の議論から思い出すように思われるものです。
アレン・バウアーやバリー・ケリーのような人々は、おそらくこれに関するより良い/より正確な情報を提供できるでしょう。
コンパイラを使用してプロジェクトで定義し、それらを変更しただけで、コンパイルを実行すると、DCUと結果のモジュール(EXEまたはDLL)に変更が表示されません。完全な再構築を行うと、コンパイラが定義されているのは、新しく作成されたDCUおよびモジュールで使用されます。
これは、異なる定義を伴うさまざまなプロジェクトでモジュールを使用し、すべてのDCUが同じディレクトリに保存される大規模なプロジェクトグループでこれを見てきました。
Ergo:コンパイラは、この場合の定義の依存関係を実施しません。
おそらくあなたは同じ問題を見たでしょう。