次の方法で共有


visual studio でのビルド結果について

質問

2017年6月13日火曜日 1:17 | 1 票

**「仕様の確認」「アドバイス」**を頂きたく質問させて頂きました。

これまで、ソースコードや設定ファイルを一切変更せずにビルドを行った場合、

「何度やっても exe はバイナリレベルで同じになる」という前提でコーディングと保守をしてきたのですが、

2015 では、ビルドするたびに 違う exe が作られることに気が付きました。

(リポジトリでソースと設定ファイルを管理しておけば、クローン先でも同じexeが作られると考えていたので、

ちょっとショックです…)

以下の3点がわかる方、アドバイス頂けると助かります。

① 考え方として、ソースが同じ場合、ビルドの設定値を調べ直すという方向性は大きくズレていないでしょうか?

→MS提供のコンパイラ自体が「ソース」「ビルド設定」に変更がなくても、

そもそもバイナリレベルで同じ出力にはならない仕様だったりしますでしょうか?

調べる時間がもったいないので聞いてみました。

② そもそもビルド毎に異なるexeになるのが当然なのでしょうか?同じにする方が無理なのでしょうか?

③  2015 で、このようにビルド毎に毎回異なるexeにする設定値にはどうゆうものがあるのでしょうか?

毎回同じexeにするためにはどの設定値を修正すべきでしょうか?

以上、宜しくお願い致します。

すべての返信 (12)

2017年6月13日火曜日 1:25

つい最近同じような話が別の掲示板で出てました。

http://bbs.wankuma.com/index.cgi?mode=al2&namber=84279


2017年6月13日火曜日 1:33

EXE の中にビルド時の日時が埋め込まれますので、ビルドする時間が異なれば、まったく同じ EXE にはなりません。

私の認識では、Visual Studio の設定で EXE に埋め込まれる日時を一定にすることはできないと思っています。出来上がった EXE を PE ヘッダーの仕様に基づいて書き換えるしかないのではと思います。また、EXE 内のビルド日時以外の部分については、同じソース、同じライブラリ、同じプロジェクトの設定、同じ Visual Studio のバージョン(cl.exe や link.exe なども同じもの)であって、EXE 内 に PDB のファイルパスが埋め込まれないように(埋め込まれるようにしている場合はパスが一致するように)している場合には、同一にすることが可能なのではと思います。

参考サイト:
http://codezine.jp/article/detail/412
https://stackoverflow.com/questions/5795270/keep-exe-timestamp-from-changing


2017年6月13日火曜日 2:01

別の観点では、

1.exeのバイナリが同じであっても、常に同じ実行結果になるとは保;できません。
 OSの機能を使っている場合は、それが変われば結果も変わる可能性が否定できません。

2.ソースが異なっていても、結果的に同じバイナリが生成される可能性があります。
 ネイティブのC/C;;言語の場合、異なるコードの最適化の結果が同じになることはありえます。

自分は、開発者がユーザーに保障すべきなのは製品の機能なのであって、
コードやバイナリ自体とは本質的には無関係であると考えています。
(種類の異なる複数のOSにアプリケーションを提供する場合を考えれば自明となります)


2017年6月14日水曜日 2:17

操作ミスで削除してしまいました。
すみません。再度アップします。

回答ありがとうございました。
「コード」「設定ファイル」「exe」の同一性はとても重要だと考えております。
人の作業ミスはゼロにはできないため、
複数人数で異なるコードのexeを動作させて、バグの原因の推測合戦はしたくはありません。
exeのコンペアで同一性の「有無確認」ができることはとても有用な場面もあるので、
できれば同じにならないかな、と思ってます。
これまで利用していたツールが同一性を保持していましたので…

できないようですので
Visual studio を選択するべきではなかったという結論かなと考えております。

アドバイス有難うございました。


2017年6月14日水曜日 2:31

回答ありがとうございます。
1、2、共に同じ認識でいます。
2はリポジトリを利用していますので、コードの書き方で必ず異なるようにできるため、
(リビジョンが異なればexeも異なるという意味で。)
あまり問題ではない状況です...
製品の機能保;の面も同じ認識です。

ただ、イコール「バイナリレベルで同じである必要がない」という考え方はしたくないかなと思っています。
あくまで個人感想ですが...

もちろん、ビルド時間が異なるのだから、違うexeになるべきという考え方を否定するものでもありません。

設定ファイル等で設定できるといいなぁくらいの希望です。

できないのであれば visual studio 以外にするしかなさそうです…

アドバイスありがとうございました。


2017年6月14日水曜日 2:34

ところで、使用言語は何でしょうか? ネイティブのC;;言語と.NETのC#言語とではコンパイラーが全く別物で、生成されるファイル形式も異なります。

# Visual Studio以外の選択肢も視野にあるようなので、C;;言語(もしくはC言語)でしょうか…?

具体的な差分を確認してみましたが、WindowsのEXEファイルで採用しているPE形式は先頭から108バイト目付近にTimeDateStampフィールドがあり、これがリンクを行った時刻を指すため、質問者さんの求める同一性保持は不可能ですね。

Visual Studioの問題ではないので、Windowsというプラットフォームそのものを諦める必要がありそうです。


2017年6月14日水曜日 2:45

佐祐理さんの発言にある通り言語によってアプローチは異なります。

例えばC/C;;ネイティブであれば、リンク以降の結果は信;できると仮定して、
*.obj及び*.resについてのバイナリを比較するという方法は検討の対象になりますでしょうか。


2017年6月14日水曜日 3:32

個人的にはバイナリ一致ができないからといって、即座に選択肢から外れることには違和感があります。

この挙動を変える方法がない割にその製品が続いている、ある程度のシェアがあるということはそれで困らないか、緩和できる方法があると期待できます。(通常は。よっぽどのメーカー言いなり環境であれば別ですが)

バイナリ一致を前提とするに至った課題とその製品に関して、世の中の事例を調査すれば、運用を見直して高機能な環境を使えるようになるかもしれません。

たとえば、リリース用のバイナリであれば、ビルドサーバーで作ったものを全員が使うという運用にすれば、バイナリは一度だけ生成されるのでばらつくことはありません。


2017年6月14日水曜日 13:40 | 2 票

すくなくとも、C#では、コンパイルオプション/deterministicオプションがあって、指定すればお望みの結果になるはずです。

jzkey


2017年6月14日水曜日 14:09 | 1 票

すくなくとも、C#では、コンパイルオプション/deterministicオプションがあって、指定すればお望みの結果になるはずです。

VS の GUI 上にはない…? かもしれないので、csproj を XML として編集して <Deterministic>true</Deterministic> と書くとかですね。
https://social.msdn.microsoft.com/Forums/exchange/en-US/1e86d661-333d-4774-bcd6-53c5530102dc/how-can-i-create-deterministic-builds?forum=csharpgeneral

タイムスタンプや GUID の代わりに、ソースコードのハッシュから計算しているそうです。
なので、更新日時が違ってもハッシュが同じであれば同じバイナリになるそうです。
http://blog.paranoidcoding.com/2016/04/05/deterministic-builds-in-roslyn.html


2017年6月14日水曜日 21:07

この機能の紹介をブログ記事で読んでいたのですが、回答にあたって見つけ出すことができなかったので(記のせいかもしれないと思い)触れませんでした。

deterministic: このスイッチを使用すると、同一の入力に対してバイト単位で同一の出力がビルドされます。従来は MVID や PDB の ID、タイムスタンプなどの PE エントリはビルドごとに違っていましたが、これが入力に基づいて確定的に計算されるようになります。

これですね。C# および Visual Basic に関する Visual Studio の最新機能原文


2021年10月21日木曜日 7:59 | 2 票

同じ要望を持ち、このトピックに辿り着いたので後続のために情報をまとめておきます。

開発者視点では、テスト等により要求動作を満たしていればバイナリ同一性は必要ないといえますが、セキュリティやCIの観点からは「同一ソースから同一バイナリを生成することを保;する」ことは重要です。これは「決定論的ビルド deterministic builds」「再現性のあるビルド Reproducible builds」と名付けられて議論されています。

VC;; の現状は
マイクロソフト Japan Developer Support Core Team Blog: 同一ソースコードから生成されるビルド成果物のバイナリ同一性について
> Visual C;; のコンパイラーおよびリンカーは、この記事の執筆時点では決定論的ビルドをサポートしていません。

とのことです。ウィキペディアにも小さい記事があります。
wikipedia 再現性のあるビルド