wine
オーバーライド
独自修正版
配布
バイナリ互換
More than 1 year has passed since last update.

目次


Inside Wine; 独自修正 Wine の配布

結論的には、細かな独自スクリプトを除けば、以下の 6 つのファイルだけを配布すれば良い。

No
ファイル名
バイト数
コメント

1
./wine/libs/wine/libwine.so.1.0
1,933,464
WINEDLLPATH の優先順位の修正のため

2
./wine/dlls/kernel32/kernel32.dll.so
5,526,999

3
./wine/dlls/gdi32/gdi32.dll.so
2,655,524

4
./wine/dlls/user32/user32.dll.so
4,267,471

5
./wine/dlls/ntdll/ntdll.dll.so
3,256,245

6
./wine/dlls/winex11.drv/winex11.drv.so
1,797,340
X Window 専用部分

合計20MB程度。圧縮すれば 10MB程度のはず。だから、アプリ本体のバイナリと同時に 10MBを配布すれば独自修正 Wine が配布できるはず。


理由


  1. Wine は、どんなにバージョンが上がっても、Windows との互換性の向上が目指されている。

  2. Windows API は、同じバージョンでは仕様が固定されている。

  3. だから、もし、出来上がった Windows API だけを呼び出して作られているモジュールであれば、
    Wine のバージョンが上がっても、新旧モジュールの入れ替えが自由にできるはず。

  4. 構造体Aにメンバを追加したとしよう。Aを参照しているモジュールのみが再コンパイルが必要となり、
    Aを参照していないモジュールは再コンパイルの必要が無い。

  5. 例えば、surface の構造体を参照しているのは、大体、上記の 3,4,6 だけである。だから、surface
    に新しくメンバを追加しても、他のモジュールは再コンパイルの必要が無い。

  6. 「カプセル化」の概念である。カプセルの外のモジュールは、カプセルの中の事情には無頓着で良い。

  7. だから、カプセルの外のモジュールが Wine本家で変更されても、カプセルの中とは独立している。

  8. 「Wine Server」と呼ばれているものが、Wineの中で、別プロセスのアプリ間の情報伝達を担っている。
    例えば、Caretの管理である。また、別アプリのWindowの名前を取得したり、別アプリのメッセージキューに
    メッセージを PostMessage したりする場合にも、Wine Server を仲介するはずである。

  9. Wine Server は、request と reply の仕様がある。その仕様が変更になった場合は、上記の dll 群は
    異常動作をするだろう。しかし、仕様が変更されない限りは、再コンパイルの必要無く、dll 群の
    バイナリをそのまま使い続けることも可能なはずである。

なんというか、本家 Wine がバージョンアップしても、上にあげたモジュールたちは、バイナリ・レベルでそのまま使いつづけられる可能性が高いのである。バージョンアップ版の本家 Wine に、上記のモジュールによって機能をオーバーライドするような使い方が出来る可能性が高い。その場合、もちろん、上記のモジュールの中で実装されている機能は、本家 Wine のバージョンアップの恩恵は受けない。しかし、上記のモジュール以外の部分のバージョンアップの恩恵は受ける。


2ch に自分が書き込んだ内容です。


  1. 2018/02/28(水) 01:21:22.23

結論的には、Wineを改造しても Windows API の仕様を変える訳ではありませんので、もし、Wineの一部であっても、Windows API だけを使った dll の部分は、Wineのバージョンが変わっても、原則的には自由に入れ替え可能な可能性があるのです。

kernel32.dll, gdi32.dll, user32.dll, ntdll.dll の4つの dll 以外のdllは、WINEの内部がどのように実装されているかには依存していない可能性があるということです。もしそうであれば、Wine のソースを改造してもこれらのdll.so以外は、本家Wineが今後発表する新バージョンのものを、改造 Wine のバイナリファイル群に後から上書きしても、互換性が保たれ続けるんじゃないかな、と思いました。つまり、以下の 4つの dll.so だけを配布すれば、かなり長い間、独自の Wine として動作できる可能性があるのではないかと。loader.c を修正した libswine.so.1.0 を配布すれば、dll.so の検索パスも上手く「オーバーライド」できますので、以下のたかだか18MB程度のファイル群を配布しさえすれば、標準の Wine を壊さないまま、独自の Wine を特定のアプリにだけ適用し、両バージョンの Wine を共存できるのではないかと思えてきたんです。

./libs/wine/libwine.so.1.0 1,933,464 # WINEDLLPATH 修正のため

./kernel32/kernel32.dll.so 5,526,999

./gdi32/gdi32.dll.so 2,655,524

./user32/user32.dll.so 4,267,471

./ntdll/ntdll.dll.so 3,256,245


  1. 2018/02/28(水) 01:22:09.65

その際、「wine server」の「server request」の仕様を変更さえしなければ、標準の Wine を使ったアプリと、まさに同時実行も可能ではないかと。実際、自分が実験する限り、標準の Wine を使った VC++ と Wz が、特に問題なく独自 Wine の自前アプリと同時実行で来ているように見えますので。

なんというか、例えば、Wineの実装の構造体にメンバ変数を独自に追加した場合、それが直接見えているソースは、同一の構造体の他のメンバの相対アドレス、構造体のサイズが変わるために再コンパイルが必要です。しかし、それを直接見ているのは、上の 4つの dllのdll.soファイルだけではないかと。そして、その他のdllは、その構造体を直接見てないのではないかと。それで、カプセルの様にブラックボックスの中に改造が閉じ込められてしまって、再コンパイルを全くしなくても外の dll 達には、その改造が破壊的な影響を与えずに、機能としての変化だけが伝達されるのではないかと。


  1. 2018/02/28(水) 01:33:54.04

「dll.so」ではなく「drv.so」ですが、

/wine/dlls/winex11.drv/winex11.drv.so 1,797,340

も配布が必要ですので、合計20MB程度。圧縮すれば 10MB程度のはず。だから、アプリ本体のバイナリと同時に 10MBを配布すれば独自修正 Wineが配布できるかと。