ご用件はタイトルのお尋ねをさせて頂きたい事です。
( 例 VC++8 でビルドした.libを、VC++10で.exeをビルド時に、まともにリンクできる? )
誠に恐縮ですが、下記の詳細について皆様のお知恵を拝借させて頂けると幸いです。
【質問の動機】
ビルド済の静的ライブラリを、複数の他者に譲渡したい。が、各人で使っているVC++の版
が異なる。その際 下記情報を第3者から得た。
「 版の違いが原因で、ビルド不能に陥ってしまう問題がある。が暗黙的リンクの動的ラ
イブラリ( インポートライブラリとのリンクが要る.dll )として譲渡すれば解決できる
」
が「 いくら動的ライブラリにしても、インポートライブラリ( .lib )が要るなら、状況
は静的ライブラリ( .lib )使用時と変わらないのでは? 」と思えた。
静的ライブラリとインポートライブラリのABIは同じではないか、と推測した為。
極力 自分で調べたが、最終的な判断の知識と資源(時間・費用)が足りない為、多くの識
者を頼らせて頂く事で それを補いたい。
【条件】
1. ライブラリの開発言語はC言語(C89)
2. ライブラリの処理内容は、唯一のプロセス(.exe)でしか実行されない
複数プロセスで同時実行されない。
3. 譲渡するライブラリのビルド構成は、DebugとRelease
4. .lib と .exe の間で、下記を統一する
A. ビルド( コンパイル・アーカイブ・リンク )時のオプション
B. 全ての版のVC++にあるオプションのみ使う
5. .lib内でマルチスレッド処理を行う
6. ライブラリのソース+プロジェクトは、譲渡不可
静的ライブラリー(.lib)
これはリンカーを使って実行ファイルに結合するためのもの
ファイルの構成はリンカーに必要な内容でできています
動的ライブラリー(.dll)
これはロード時、実行中に結合するもの
ファイルの構成は実行ファイルと同じです
.lib のファイル構成は VC++ のバージョン毎に違っていてもおかしくないが
.dll のファイル構成はコンパイラーではなく OS により違うと考えてよい
例えば WinXP 以降なら 32bit/64bit で違うだろう
>「 いくら動的ライブラリにしても、インポートライブラリ( .lib )が要るなら、状況
>は静的ライブラリ( .lib )使用時と変わらないのでは? 」と思えた。
使用目的、ファイル構造等が違うので状況が変らないとはいえないと思います。
どうも有難うございます。
>.lib のファイル構成は VC++ のバージョン毎に違っていてもおかしくない
私もある程度 推測しましたが、「論理的な裏付け(証拠)のある情報源を探している」状態
です。
事前確認
・静的ライブラリを (たとえば) VS2005 で作る
・作った静的ライブラリを (たとえば) VS2010 で使う
であるとして。
> 版の違いが原因で、ビルド不能に陥ってしまう問題がある。
一切 C RunTime Library (CRT) を使わないように意識して作らない限り
VS2005 で作った静的ライブラリは VS2005 の CRT を使用しようとする。
一方で VS2010 しかもっていない人は VS2010 の CRT を使わざるを得ない。
VS2005 の CRT と VS2010 の CRT は果たして100%互換であるか否か。
ってことだと・・・
たとえばこんな事例もあるし
http://bbs.wankuma.com/index.cgi?mode=al2&namber=64454&KLOG=108
互換であると断言することは困難だろう。
俺的には ABI って用語は関数呼び出し規則などを意味していて
ライブラリの中にどんな関数があるかは ABI に含まれないので
ABI 互換だけどリンク不能 (ないしは動作不良) ってのはごく普通のことだと思う。
> 暗黙的リンクの動的ライブラリとして譲渡すれば解決できる
VS2005 で作った DLL は VS2005 の CRT を含んでいる
VS2010 で作った DLL は VS2010 の CRT を含んでいる
(インポートライブラリとして外部にある MSV*.DLL を必要とするかもしれないが
それはインストーラで VS**** Redistributables をインストールすればいい)
わけで、上記のような問題は発生しにくい。
100% 発生しないか、と問われればそれは作り方次第だろう。
静的ライブラリー(.lib)
は一言で言うとオブジェクトファイル(*.obj)の固まりです。
なので、コンパイラバージョンに依存する。
動的ライブラリー(.dll)
は基本的にLoadLibrary(), GetProcAddress()で関数呼び出しを行うものです。
よって、C++のコンパイラバージョン違いどころか、言語の壁さえも乗り越えら
れる。
問題のインポートライブラリですが、要はGetProcAddress()呼び出しで内部的
に使用する情報をライブラリとして持っているだけです。
リンク時にその情報だけを実行ファイルに内包するわけです。
GetProcAddress()呼び出しで動作するDLLなら、インポートライブラリにしても
問題なく動作するはずです。
なお、
分かりやすくするために、曲解的なことを書いていますが、大筋は間違ってい
はずです(^^;)
ブツは純粋にC言語だけのスタティックライブラリなのですよね。
なら、単純にやってみれば良いだけの様な気がします。
簡単だし。
VS2008Expressは見つかりませんでしたが、2010と2012のExpressは
タダで手に入ります。これらはMFCが使えない点を除けば製品版と
ほとんど変わりません。
1.VS20xx ExpressでLibを再構築してみたらどうでしょう。
特に難しいことはありません。
これらはそのまま提供できるわけですよね(悩むこと無し)。
2.経験があれば、それらの内、いくつかの関数をエクスポートした
DLLを作成するのは、たいした手間ではありません。
最終的には全部やる必要がありますが、テストなら数個で十分。
ついでに、DLL、Staticを問わず、以下点にも注意が必要ですね。
A.32bit版/64bit版のどちら又は両方を供給するのか。
B.UNICODE版/MBCS版のどちら又は両方を供給するのか。
皆様、貴重なご意見を下さり、誠に有難うございます。現時点では下記のような暫定的な
結論を得ました。私の誤解へのご指摘や、更なる情報があれば、ぜひお寄せ頂けると幸い
です。
・ライブラリ使用者のVC++の版を不問にしたいなら、暗黙的リンクのDLL( .lib(インポー
トライブラリ) と .dll )としてライブラリを配布した方が良い
・静的ライブラリのABIは、VC++の異なる版で互換性が無い事を前提にした方が良い
【tetrapodさん】
>たとえばこんな事例もあるし
> http://bbs.wankuma.com/index.cgi?mode=al2&namber=64454&KLOG=108
>互換であると断言することは困難だろう。
なるほど。静的ライブラリが複数版で使えない事例( 証拠 )、になりそうですね。
条件が本件と大きく違い、更なる調査は要りますが、有力な参考情報になりえます。
【bunさん】
>インポートライブラリですが、要はGetProcAddress()呼び出しで内部的に使用する情報
をライブラリとして持っているだけ
>リンク時にその情報だけを実行ファイルに内包する
>GetProcAddress()呼び出しで動作するDLLなら、インポートライブラリにしても問題なく
動作するはず
「インポートライブラリのABIは、VC++の複数の版の間で互換性を持つ形式の筈」と、解
釈させて頂きました。
これが本当に正しければ、しまさんの「ファイル構造等が違うので状況が変らないとはい
えないと思います」というご意見が的中しますね。
※「インポートライブラリのABIは、静的ライブラリのABIの殆どを拝借しているかもし
れない。
もしそうなら、インポートライブラリ≒静的ライブラリ だろう」と推測していまし
た。
【仲澤@失業者さん】
>ブツは純粋にC言語だけのスタティックライブラリなのですよね
はい、その通りです。
>単純にやってみれば良いだけ
はい、回答を頂けなければ無論 自前で検証する予定でした。
が、初回投稿文の通り「資源(時間・費用)が足りない」為、皆様を頼らせて頂いた次第で
す。
>簡単だし
いいえ、現実には難しいと思います。
「本件の為だけに複数版のVC++をインストールをし、各検証をする事」は、
作業内容は簡単( = 頭を使わない内容 )でも、何時間も費やす事が許されるかを考えると
極めて難しい、と思う為です。
何をするにも、資源(時・金・労)を有効活用する事が求められる世の中だからです。
又、タイトルの通りVC++8以降が対象であり、2つの版だけでは検証した事にはならず、許
される投資の仕方ではない、と考えたのです。
2つの版の間だけでは、ABIが変わらない可能性もありえる為です。運よく差が出れば良い
ですが、高費用と思う作業を運任せにできません。
>VS2008Expressは見つかりませんでしたが
http://search.microsoft.com/ja-JP/results.aspx?q=2008+express&x=0&y=0
のPDF中のリンクから、VS2008Expressのisoイメージが取得できる。
ようです。
2005は…さすがに見つからないかなぁ……。
>PDF中のリンクから
2番目の「Visual Studio 2008 Express Edition with Service Pack 1 の ...」ってリン
クです。
PDFのファイル名は「vstudio_2008_product_express_offline.pdf」。
どうも有難うございます。参考にさせて頂きます。
気になったので少し実験してみました。
MyLib.libを /MDで作り、利用側のLibUser.exeも /MDで作ると
LibUser.exeは実行時に msvcrXX.dllをリンクします。
MyLib.libをvs2003で作成し、この中で、_winver と _strcmpi を使用します。
これらは、msvcr71.dllにあります。
LibUser.exeをVS2003で作成すると
LibUser.exeはmsvcr71.dllから _winver と _strcmpiをインポートします。
LibUser.exeをVC2010Expressで作成すると、
error LNK2001: 外部シンボル __imp___winver は未解決です。
で失敗します。原因は、msvcr100.dllに _winverが無いからです。
MyLib.libの中で _winverを使わないように変更すると、
LibUser.exeはmsvcr100.dllから _stricmpをインポートします。
msvcr100.dllには、_strcmpiがありませんが、
msvcrt.libは、oldnames.lib経由で _stricmpに変換しているようです。
------------------------
_winverは、msvcrt.dllにもあります。そして、msdnのCRTライブラリの機能によれ
ば、msvcr100.dllはmsvcrt.dllと互換のように書かれています(ここらは何遍読み返して
も確信は得られませんでした)。
では、どうしたらよいのか。
「非標準の関数等は使わず、Win32の関数を使う」でどうでしょう。
ちなみに、LibUser.libを/MDでDLL化するには、たとえば、DLLでmallocしExeでfreeして
いないか等、ソースの点検が必要になります。
> msvcr100.dllには、_strcmpiがありませんが、
> msvcrt.libは、oldnames.lib経由で _stricmpに変換しているようです。
間違いでした。
vc2010Expressのmsvcrt.libをdumpbinで調べた結果は
002 00000000 UNDEF notype External | __stricmp
003 00000000 UNDEF notype WeakExternal | __strcmpi
__strcmpiの代わりに__stricmpを使っているようです。
「 C89のAPIで作った静的ライブラリは、VC++の版が異なると 確かにビルド不能に陥った事
があった。その解法として暗黙的リンクによるDLLを使った。具体的な状況は忘れてしまっ
た 」
という 自信に満ち溢れた言質を、職場で辛うじて得る事ができました。
強い証拠になる具体的情報が無いのは残念ですが、最重要の回答は得られた事 と これ以上
の深入りは費用対効果が下がってしまうだろう故、これで良しとしようと思います。
皆様、どうも有難うございました。
【 ロマさん 】
「MS製ライブラリのAPIは後方互換を捨てた物があり、それに依存したアプリケーションコ
ードがあった場合、ハマる」事は既知でした。
が、本件はそれに該当しません。
∴折角 検証して頂いたのに恐縮ですが、残念乍 両検証とも本件には無関係でした。でも、
有難うございます。