はじめに
最近、Qiitaへの投稿ができていませんでした。特に新しい技術を学ぶ機会が少なかったというのが大きいのですが、逆に基礎的な知識が必要になることがあったので、ざっくりまとめてみたいと思います。
背景
同じソースコードを使って異なるPCでビルドしたexeが、同じように動くことを説明する必要がありましが、exeにはバイナリレベルで数バイトの差がありました。開発する側の人間からすると、気にするなと言いたいところですが、どこの世界でも外部に対してはそれなりに筋の通った説明が必要になるのです。
なお、今回の基本的な条件は以下の通りです。(細かいところは意図的に濁しています)
- 使用するフレームワークなど
- QtとVisualStudioは全環境で統一(同じインストーラを使用)
- ビルド環境
- 異なるWindows環境
今回コンパイラにはVisualStudioを使っていました。おそらくどのコンパイラも、以下のようにバイナリの同一性は保証していないと思いますので、あくまでこの記事の内容は自己責任で参照願います。
ビルド日時の違い
まずは普通に考えて、exeにはビルド日時が埋でのめ込まれているはずなので、その埋め込まれ方を調べました。現在のWindowsでのexeのフォーマットについては、だいたい次のページでわかります。
このページに従いexeのバイナリを読んだところ、COFFファイルヘッダーのTimeDateStampに埋め込まれているビルド日時の違いで説明できました。
想定外の差分
上記のビルド時刻のズレで基本的に問題はなくなったのですが、ある環境だけまったく別の差分が出ていました。その環境でのビルド動作を順に調査したところ、Qtが作成してVisualStudioに渡している中間ソースコードの中に、exeに埋め込む画像のファイル名と何らかの日時が存在し、その環境だけその日時がわずかに違うようでした。
そこで該当のバージョンのQtのソースコードをダウンロードし、問題のソースコードに日時を書き出している部分を読むと、リソースとして埋め込む画像ファイルの作成日時であることと、埋め込まれている形式が分かりました。
そして具体的に埋め込まれたバイナリを形式に従い読んでみたところ、本来のファイルの作成日時が偶数秒に丸められミリ秒がありませんでした。この段階で分かる人には分かると思いますが、この環境にソースコードを持ち込む際、FATフォーマットのUSBメモリを使用していたため、画像ファイルの作成日時が変化していたのが原因でした。
結論
どんな最新技術を使おうとも、結局はOSやコンパイラの制限などは避けられません。新しい技術も必要だけど、昔から経験したことはなんらかの形で役に立つと実感したお仕事でした。