■ Runtime
■ /implib
SYNTAX
/IMPLIB:filename
DESC
Link で生成される ImportLibrary 名を filename に上書きする
Default は basename
test.dll ならば test.lib
この Option の指定は必須ではない
UI
Linker > 詳細 > ImportLibrary
POINT
この Option は必須ではない
■ /LD
WARNING
この Option 自体は lib.exe のものではない
// cl の option のひとつ
DESC
Link 時の指定
DLL を作成する
これをつけると _main() がないと怒られない
// dll を build する
cl /LD /EHsc dll.cpp
// 2 つの Source
cl /LD /EHsc dllA.cpp dllB.cpp
// DLL 名を指定する
// test.dll, test.lib が作成される
cl /LD /EHsc dllA.cpp dllB.cpp /link /out:test.dll /implib:test.lib
// ImportLibrary を指定して Build
cl /EHsc call.cpp test.lib
// 実行
./call.exe
// test.dll の名前を変更すると ERROR
// test.dll が見つからなかったため このアプリケーションは実行できませんでした
mv test.dll test.dll_bk
__declspec( dllimport ) void dllfuncD();
int main()
{
dllfuncD();
return 0;
}
■ Debug
■ /DEBUG
DESC
.exe ファイルまたは DLL のデバッグ情報を作成するために指定する
デバッグ情報は、プログラム データベース (PDBファイル) に書きこまれる
デバッグ用に生成された .exe や DLL には
対応する PDB ファイルの名前とパスが書かれている
シンボルが読まれない時は以下のコマンドで調べること
strings main.exe | grep "pdb"
デバッガーでプログラムをデバッグするときにこの名前が読まれ
その PDB ファイルが使われる
'vc.exe': 'D:\test\vc\debug\vc.exe' を読み込みました。シンボルが読み込まれました。
プログラム データベースの名前として
ベース名 .pdb が使用され
PDB ファイルのパスは .exe, .DLL ファイルに書かれる
オーバーライドするには /PDB:filename で指定
link /DEBUG /PDB:foo.pdb main.obj
/Zd (行番号のみ) または /Z7 (C7 互換) を指定すると
.obj ファイルにデバッグ情報が保存される
/Zi (プログラム データベースを使用) コンパイラ オプションを指定すると
.obj ファイルのデバッグ情報が PDB ファイルに保存されます
リンカーはオプジェクトの PDB ファイルを探すときに
まず .obj ファイルに書き込まれた絶対パスを検索し
そこで見つからない場合は .obj ファイルの置かれているディレクトリを検索します
オブジェクトの PDB ファイルの名前やディレクトリをリンカーに指定できない
■ /PDB
SYNTAX
/PDB:filename
DESC
リンカーが作成するプログラムデータベース (PDB) の名前を指定する
( Default : プログラムベース名.pdb )
/DEBUG (デバッグ情報の生成) を指定すると
デバッグ情報の入ったプログラム データベース (PDB) が作成される
POINT
pdb file の生成は /DEBUG で有効にする
/DEBUG を指定しないと /PDB オプションは無視
PDB ファイルは 最大 2 GB
Debug 中に Build すると pdb File を利用されていることがわかる
「リンカー入力としての .pdb ファイル」
■ DLL
■ /DLL
DESC
DLL をビルドする
この Option をつけて Compile すれば DLL が作成される( はず ) -> 2010.07.22 -> ちがった
Link 時に指定する Option のため ,
Compile 時は特に関係ないはず
DLL の作成方法
POINT
VC の version によっては wizard で DLL を選択できない
でも Console Application を指定して 後で変更できる
( Option の設定しだいということ )
■ /export
DESC
symbol を export する
プログラムから関数をエクスポートして
ほかのプログラムがその関数を呼び出せるようにする
// こうするかわりに
__declspec( DLL_EXPORT ) void func;
// こうする
// [追加のオプション] ボックスにオプションを入力
/export:func
■ その他
■ MACHINE
DESC
対象となるアーキテクチャを指定する
/MACHINE:x86
/MACHINE:x64
/MACHINE:I386
DLL は同一のタイプを利用しないと
Module の対象 Computer と異なるといわれる
■ Entry
DESC
EXE DLL 開始アドレス(名前)を指定する。
エントリポイントとはプログラムをメモリにロードした際に
実行をはじめる開始アドレスのこと。
Linker > 詳細 > EntryPoint
link /Entry:main main.obj
POINT
実はユーザーが書いたコードよりも前に、CRT( printf など ) の初期化、例外ハンドラの設定などが実行される。
これが _mainCRTStartup(), _WinMainCRTStartup() という関数で、C のランタイムライブラリ内にある。
次の流れになる。
main() は _mainCRTStartup() からコールされる。
// CRTの初期化をして ユーザプログラムを開始
OS ---> _mainCRTStartup() ---> main()
WARNING
エントリポイントはリンカーにまかせるべき。
そうしないと C ランタイムライブラリが正確に初期化され、
静的オブジェクト用の C++ のコンストラクタが実行されない。
#include< stdio.h>
int main()
{
printf("test\n");
return 0;
}
CRT を利用しているが, main() を開始アドレスにする。
cl /c main.cpp
link /entry:main main.obj
実行すると次のエラーがでる。
runtime error R6030
- CRT not initialized
デフォルトのエントリポイントは、アプリケーションのタイプ( SUBSYSTEM )によって決まる。
SUBSYSTEM:CONSOLE ならば mainCRTStartup
SUBSYSTEM:WINDOWS ならば WinMainCRTStartup
■ SUBSYSTEM
DESC
オペレーティングシステムに .exe ファイルの実行方法を指定する。
サブシステムの選択によって
リンカが選択するエントリポイント関数が決まる。
サブシステムの指定は どんな環境用のコードを出力するかを決定するために指定する。
POINT
main() または WInMain() が定義されていると SUBSYSTEM オプションのデフォルト値が決まる。
// main() がコード内で定義されていると、サブシステムとして暗黙に CONSOLE を選択することになる。
int main() {
return 0;
}
明示する場合はリンカーオプションで指定する。
WINDOWS
アプリケーションにはコンソールは不要です。
このシステムにはユーザーとの対話用のウィンドウが作成されるからです。
WinMain() または wWinMain() が定義されていると、WINDOWS がデフォルト設定になる。
CONSOLE
Win32 文字モードアプリケーションに対して使用する。
コンソール アプリケーションには、オペレーティングシステムからコンソールが与えられる。
main() または wmain() が定義されていると、CONSOLE がデフォルト設定になる。
POINT
dumpbin /HEADERS でエントリポイントの開始アドレスがあることが確認できる。
undname.exe で C++ 修飾子前の名前を取得できる。
undname ?Foo@@YGHPAUHINSTANCE__@@0PADH@Z
■ Runtime
■ MANIFEST
WARNING
crt.dll の場所を明示することが目的
mt.exe で埋め込まないと exe をビルド後の場所から移動すると実行できない
( たぶん manifest ファイルも配布すれば 埋め込むのも必須ではないと思う )
POINT
VisualStudio では Default で manifest を実行ファイルに埋める
GenerateManifest="true"
Linker > Manifest > Manifest の生成
// いらない
link /MANIFEST:NO main.obj
// つくる ( Default )
link /MANIFEST main.obj
// 指定しない場合でも作成される
link main.obj
WARNING
/MANIFEST:NO にしても 自動で exe には組み込まれない
mt.exe を利用して埋め込む。
2 つの方法でアプリケーション || ライブラリに埋める
インクリメンタル ビルドを実行しない場合は
ビルド後のステップでマニフェストを直接埋める
// Exe の場合
mt.exe /manifest test.exe.manifest -outputresource:test.exe
// DLL の場合
mt.exe /manifest test.dll.manifest -outputresource:test.dll
インクリメンタル ビルドを実行する場合、上記のようにリソースを直接編集すると
インクリメンタル ビルドが無効になり
フル リビルドが実行されるため
異なるアプローチがいる
バイナリをリンクして
app.exe.manifest ファイルを生成
マニフェストをリソースファイルに変換
(インクリメント方式で) 再リンクして、マニフェスト リソースをバイナリに埋める
■ NODEFAULTLIB
LINK が参照を解決するときに検索するライブラリを引数 library で指定する
コマンド ラインで指定したライブラリが検索される
2. /DEFAULTLIB オプションで指定したライブラリが検索される
3. obj ファイル内で指定した既定のライブラリが検索される
/NODEFAULTLIB (すべての既定のライブラリを無視) オプションは、
/DEFAULTLIB:library の指定よりも優先されます
/NODEFAULTLIB:library (無視するライブラリ) オプションと /DEFAULTLIB:library
オプションで同じライブラリを指定すると、前者の指定が優先されるためそのライブラリは検索されません
POINT
自分でコンパイルをする必要があるライブラリを使用する時は
アプリケーションのランタイムライブラリの指定を、 ライブラリを生成した際の指定と同じにしておく必要がある。
異なる設定をしている時は、warning または、シンボルの二重定義でリンクできないなどの症状が出る。
Linker > Input > すべての既定ライブラリ無視 : YES
RunTimeLibrary の指定が必要なとき
MultiThread Application で SingleThread の指定が必要な場合
ライブラリとそれを利用するアプリケーションで、異なった設定を行った場合
/MD で作成されているライブラリを、/MT のアプリケーションで 利用しようとすると LIBCMT.lib での二重定義でエラーとなる
error LNK2005: _printf は既に LIBCMT.lib(printf.obj) で定義されています
/MT で作成されているライブラリを、/MD のアプリケーションで 利用しようとすると warning が出るが動作はする
LINK : warning LNK4098: defaultlib 'LIBCMT' は他のライブラリの使用と競合しています。/NODEFAULTLIB:library を使用してください。
debugで作成されているライブラリを releaseで使用した場合ライブラリの競合が報告される ( 逆も同じ )
// DLL 版でも同じ
test.lib ( /MTd )
app.exe ( /MT )
test.lib ( /MT )
app.exe ( /MTd )
■ 静的リンク
POINT
/MT, /MD とは C の Runtime == C標準関数 の Runtime の
LINK をどうするのか って聞いている
静的リンクとは
アプリケーションプログラムをリンクした時に
必要なライブラリをプログラムに含める方式
リンク時にオブジェクトファイルを汎用ライブラリと共につなぎ合わせ
実行可能形式のバイナリを作成する
利点
必要なAPIやライブラリのバージョン間の互換性を気にしなくてもよい
欠点
実行可能形式のプログラムサイズが大きくなる
共有ライブラリをバージョンアップしたときにプログラムを再リンクする必要がある
■ 動的リンク
プログラムを実行する時に初めて
共有ライブラリあるいはダイナミックリンクライブラリ(DLL)と結合される方式を動的リンクという
実行時にプログラムの結合を行う方式
プログラム作成は
一般に大規模なプログラムをモジュールに分割して
コンパイル後に
オブジェクトファイルを汎用ライブラリと共につなぎ合わせて実行可能形式のバイナリを作成する
これを静的リンクという
それとは異なり
プログラムを実行する時に初めて他のモジュールやライブラリと結合される方式を動的リンクと呼ぶ
この動的リンクを使ったライブラリを
共有ライブラリあるいはダイナミックリンクライブラリ(DLL)という
POINT
DLL は ライブラリのひとつ
利点
実行可能形式のプログラムサイズを小さくできること
共有ライブラリをバージョンアップしたときにプログラムを再コンパイルする必要がない
欠点 ( DLL 地獄 )
暗黙的に特定のバージョンの共有ライブラリの内部処理や仕様に依存していたプログラムが
ライブラリのバージョンアップによって動作しなくなること
バージョンアップした共有ライブラリに不良が作り込まれているとコンピュータ全体に影響が及ぶこと
バージョンアップによる影響範囲を事前に特定できないこと
複数のバージョンのライブラリがシステム内に存在するときの動作が特定できないこと等がある