ぼく用あれこれまとめ
zlib 1.2.6 を導入したときのメモ
最終更新:
bokuyo
-
view
zlib 1.2.6 を導入したときのメモ
- zlib 1.2.6(January 29, 2012) をWindows 環境に導入します。
- 今回は3通りの方法でビルドしています
- NMAKE を使ってビルドする方法
- Visual C++ 2010 で新規プロジェクトを作ってビルドする方法
- Visual C++ 2010 でzlib が用意してくれてるプロジェクトを使ってビルドする方法
- Visual C++ 2010, Visual Studio 2012 で手早くビルドしたい場合は以下をご覧くださいませ
ダウンロード
- http://zlib.net/(公式サイト)から「zlib source code, version 1.2.6, zipfile format」をダウンロードします。
- ダウンロードした"zlib126.zip" ファイルを解凍します。
アプリケーションに合わせて NMAKE する
- 解凍した zlib-1.2.6 フォルダを開きます
- "zlib-1.2.6/win32/Makefile.msc"をテキストファイルとして開きます。
- 開くと、以下のようにコンパイラオプション・リンカ―オプションが列挙されています。
CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC) WFLAGS = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE ASFLAGS = -coff -Zi $(LOC) LDFLAGS = -nologo -debug -incremental:no -opt:ref ARFLAGS = -nologo RCFLAGS = /dWIN32 /r
- zlib を使用するアプリケーションに合わせて、この部分を適切に書き換える必要があります。
- ぼくはCFLAGS の部分を"-MD" から"-MT"に変更しました。
CFLAGS = -nologo -MT -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC)
- 参考までに、Visual C++ 2010 のプロジェクトのプロパティとの対応表。こんな感じ。
オプション | Visual C++ 2010のプロパティとの対応 |
-nologo | 構成プロパティ>C/C++>全般>著作権情報の非表示>はい(/nologo) |
-MT | 構成プロパティ>C/C++>コード生成>ランライム ライブラリ>マルチスレッド(/MT) |
-W3 | 構成プロパティ>C/C++>全般>警告レベル>Level3(/W3) |
-O2 | 構成プロパティ>C/C++>最適化>実行速度の最大化(/O2) |
-Oy- | 構成プロパティ>C/C++>最適化>フレームポインターなし>いいえ(/Oy-) |
-Zi | 構成プロパティ>C/C++>全般>デバッグ情報の形式>プログラム データベース(/Zi) |
- 「$(LOC)」はnmake するときにコンソールに渡す変数です。
# optional build flags LOC =
- まずはこれでビルドしてみます。
- コマンドプロンプトを開き、まずはVisual C++ の環境変数を読み込みます。
>"C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat"
- NMAKE します。
C:\Users\hoge>"C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" Setting environment for using Microsoft Visual Studio 2010 x86 tools. C:\Users\hoge>cd Desktop/zlib-1.2.6/ C:\Users\hoge\Desktop\zlib-1.2.6>nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF"
- 失敗します。
(... 省略) link -nologo -debug -incremental:no -opt:ref -def:win32/zlib.def -dll -i mplib:zdll.lib -out:zlib1.dll -base:0x5A4C0000 adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj gzwrite.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj zlib1.res ライブラリ zdll.lib とオブジェクト zdll.exp を作成中 deflate.obj : error LNK2019: 未解決の外部シンボル _match_init が関数 _lm_init で参照されました。 deflate.obj : error LNK2019: 未解決の外部シンボル _longest_match が関数 _deflate_fast で参照されました。 infback.obj : error LNK2019: 未解決の外部シンボル _inflate_fast が関数 _inflateBack で参照されました。 inflate.obj : error LNK2001: 外部シンボル "_inflate_fast" は未解決です。 zlib1.dll : fatal error LNK1120: 外部参照 3 が未解決です。 NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 10.0\VC\BIN\link.EXE"' : リターン コード '0x460' Stop. C:\Users\hoge\Desktop\zlib-1.2.6>
- コンパイルは成功していますが、リンクに失敗しています。
- Makefile.msc を見てみると上のほうにUsage で使い方が書いてます。OBJA を見落としてました。
C:\Users\hoge\Desktop\zlib-1.2.6>nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="inffas32.obj match686.obj"
- これでエラーが出なければ成功です。
- zlib-1.2.6 フォルダにそれぞれlib, dll ファイルができていると思います。
- zdll.lib
- zlib.dll
- zlib1.dll
面倒なのでVisual C++ 2010 でプロジェクトを作ってビルドする
- いろいろ試してみましたが、たぶんVisual C++ でビルドするほうが楽です。
- 中間ディレクトリ・出力ディレクトリの指定、あるいはDebug, Release の切り替えなどを行うならもうプロジェクト作っちゃいましょう。
適当な場所に新しいディレクトリを作る
- 適当な場所に新しいディレクトリを作ります。ここでは「zlib_msvc_v126」ディレクトリにしました
- Visual C++ 2010 を開き、
- [ファイル]->[新規作成]->[プロジェクト]->[空のプロジェクト]
- "zlib_msvc_v126" ディレクトリ内にプロジェクトとソリューションファイルを作ってください。
- 今回はプロジェクト名を「zlib_v126」にしました。
- いったんソリューションを閉じます。
- "zlib_msvc_v126/zlib_v126" ディレクトリを"zlib_msvc_v126/Source" ディレクトリに名前を変更します。
- zlib_msvc_v126/Source/zlib_v126.sln をもう一度開きます。
- zlib_msvc_v126/zlib_v126/zlib_v126 ディレクトリにプロジェクトファイルなどがあるので、そこに解凍したzlib-1.2.6 フォルダをコピペしておきます。
Visual C++ プロジェクトにファイルを追加する
- Visual C++ 上のソリューションエクスプローラーからzlib_v126 プロジェクトを[右クリック]->[追加]->[既存の項目]
- zlib_msvc_v126/Source/zlib_v126/zlib-1.2.6 の中身をすべて追加します。(ヘッダーファイル(.h)とインプリメントファイル(.c)のみでおっけーです)
- ("adler32.c" "compress.c" "crc32.c" "crc32.h" "deflate.c" "deflate.h" "gzclose.c" "gzguts.h" "gzlib.c" "gzread.c" "gzwrite.c" "infback.c" "inffast.c" "inffast.h" "inffixed.h" "inflate.c" "inflate.h" "inftrees.c" "inftrees.h" "trees.c" "trees.h" "uncompr.c" "zconf.h" "zlib.h" "zutil.h" "zutil.c" )
プロジェクトのプロパティを変更します。
- [プロジェクト]->[zlib_v126 のプロパティ]
- Debug, Release どちらも変更するのを忘れずに。
- [プロパティ]->[構成プロパティ]->[全般]
構成の種類 | スタティック ライブラリ (.lib) |
出力ディレクトリ | $(SolutionDir)..\Obj\$(Configuration)\ |
中間ディレクトリ | $(ProjectDir)Obj\$(Configuration)\ |
- [プロパティ]->[構成プロパティ]->[C/C++]->[コード生成]
Debug | Release | |
ランタイム ライブラリ | マルチスレッド デバッグ (/MTd) | マルチスレッド (/MT) |
あとはDebug, Release のそれぞれでビルドすればできあがり。
- "zlib_msvc_v126/Obj"ディレクトリにそれぞれ "zlib_v126.lib" ができあがっていると思います。
- NMAKE よりはこっちのほうが管理が楽そうです。
あとで気づきました
- zlib-1.2.6/contrib/vstudio/vc10 にVisual C++ 用のプロジェクトファイルがありました。
- zlib-1.2.6/contrib/vstudio/vc10/zlibvc.sln をVisual C++ 2010 で開きます
- プロパティを見てみると、MTd, MT にそれぞれ設定されているみたいです。
- そのままDebug, Release ビルドします。
- warning と error が出ると思います。(以下では、warning を省略してます)
1>------ ビルド開始: プロジェクト: zlibvc, 構成: Debug Win32 ------ 2>------ ビルド開始: プロジェクト: testzlib, 構成: Debug Win32 ------ 3>------ ビルド開始: プロジェクト: zlibstat, 構成: Debug Win32 ------ 2>LINK : fatal error LNK1104: ファイル '..\..\masmx86\match686.obj' を開くことができません。 1>LINK : fatal error LNK1104: ファイル '..\..\masmx86\match686.obj' を開くことができません。 4>------ ビルド開始: プロジェクト: testzlibdll, 構成: Debug Win32 ------ 5>------ ビルド開始: プロジェクト: minizip, 構成: Debug Win32 ------ 6>------ ビルド開始: プロジェクト: miniunz, 構成: Debug Win32 ------ 6>LINK : fatal error LNK1104: ファイル 'x86\ZlibDllDebug\zlibwapi.lib' を開くことができません。 5>LINK : fatal error LNK1104: ファイル 'x86\ZlibDllDebug\zlibwapi.lib' を開くことができません。 4>LINK : fatal error LNK1104: ファイル 'x86\ZlibDllDebug\zlibwapi.lib' を開くことができません。 ========== ビルド: 1 正常終了、5 失敗、0 更新不要、0 スキップ ==========
- 失敗しました。
- 「zlib-1.2.6/contrib/masmx86/ ディレクトリにmatch86.obj がないよ」とのことです。
- zlib-1.2.6/contrib/vstudio/readme.txt を読むとちゃんと手順が書いてありました。
- コマンドプロンプトを開き、以下を順に実行。
- vcvars32.bat で環境変数を読み込んで、bld_ml32.bat でinffas32.obj と match686.obj をビルドしてます
>"C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" >cd Desktop/zlib-1.2.6/contrib/masmx86 >bld_ml32.bat
- zlibvc プロジェクトのプロパティを開き、[構成プロパティ]->[全般]
- ターゲット名を"$(ProjectName)" から "zlibwapi" に変更してください。
- ビルドします
- .lib, .dll が上手くビルドされます。しかし、test コードのビルドでリンカエラーが出てます。
2>zutil.obj : error LNK2019: 未解決の外部シンボル _gzflags@0 が関数 _zlibCompileFlags@0 で参照されました。 2>x86\TestZlibDebug\testzlib.exe : fatal error LNK1120: 外部参照 1 が未解決です。
- testzlib プロジェクトのプロパティを開き、[構成プロパティ]->[リンカー]->[入力]
- 追加の依存ファイルに"x86\ZlibStatDebug\zlibstat.lib" を追加します(Debug 時)
- Release 時も同様に"x86\ZlibStatRelease\zlibstat.lib" を追加しておいてください。
- これでビルドします。たぶん成功するはずです。
スタティックライブラリを使ってみましょう
- 使用するプロジェクト内に以下のファイルをコピーしておきましょう
- zlib-1.2.6/zconf.h
- zlib-1.2.6/zlib.h
- ビルドして出力された.lib ファイル(zlib_v126.lib)
- .lib ファイルをVisual C++ でプロジェクトに追加しましょう
- [プロパティ]->[構成プロパティ]->[リンカー]->[全般]->[追加のライブラリ ディレクトリ]
- 面倒なので #pragma comment でおっけー
#pragma comment(lib, "zlib_v126.lib")
LIBCMT との競合が起きた場合
1>libcmt.lib(invarg.obj) : error LNK2005: __initp_misc_invarg は既に LIBCMTD.lib(invarg.obj) で定義されています。 1>libcmt.lib(invarg.obj) : error LNK2005: __call_reportfault は既に LIBCMTD.lib(invarg.obj) で定義されています。 1>libcmt.lib(invarg.obj) : error LNK2005: __set_invalid_parameter_handler は既に LIBCMTD.lib(invarg.obj) で定義されています。 1>libcmt.lib(invarg.obj) : error LNK2005: __get_invalid_parameter_handler は既に LIBCMTD.lib(invarg.obj) で定義されています。 1>libcmt.lib(invarg.obj) : error LNK2005: __invoke_watson は既に LIBCMTD.lib(invarg.obj) で定義されています。 1>libcmt.lib(invarg.obj) : error LNK2005: "void __cdecl _invoke_watson(unsigned short const *,unsigned short const *,unsigned short const *,unsigned int,unsigned int)" (?_invoke_watson@@YAXPBG00II@Z) は既に LIBCMTD.lib(invarg.obj) で定義されています。 1>libcmt.lib(invarg.obj) : error LNK2005: __invalid_parameter は既に LIBCMTD.lib(invarg.obj) で定義されています。 1>libcmt.lib(invarg.obj) : error LNK2005: "void __cdecl _invalid_parameter(unsigned short const *,unsigned short const *,unsigned short const *,unsigned int,unsigned int)" (?_invalid_parameter@@YAXPBG00II@Z) は既に LIBCMTD.lib(invarg.obj) で定義されています。 1>libcmt.lib(invarg.obj) : error LNK2005: ___pInvalidArgHandler は既に LIBCMTD.lib(invarg.obj) で定義されています。 1>libcpmtd.lib(xdebug.obj) : warning LNK4098: defaultlib 'libcmt.lib' は他のライブラリの使用と競合しています。/NODEFAULTLIB:library を使用してください。
- [構成プロパティ]->[リンカ―]->[入力]->[特定の既定のライブラリの無視]->"LIBCMT" を追加
- LIBCMT を無視することでしのぐこともできるが根本的に、nmake したzlib とzlib を使用するアプリケーションでランタイムライブラリが違う可能性が高い
- "/MT" でnmake したzlib を"/MTd" のアプリケーションで使うと出る。
もう一度NMAKE したときのメモ
次の命名規則に従って、.lib, .dll ファイルをmake する
ランタイム ライブラリ | .lib 名 | DLL 名 |
マルチスレッドDLL(/MD) | lib_zlib_vc100_mt_v1_26.lib | zlib_vc100_mt_v1_26.dll |
マルチスレッドデバッグDLL(/MDd) | lib_zlib_vc100_mt_gd_v1_26.lib | zlib_vc100_mt_gd_v1_26.dll |
マルチスレッド(/MT) | lib_zlib_vc100_mt_s_v1_26.lib | なし |
マルチスレッドデバッグ(/MTd) | lib_zlib_vc100_mt_sgd_v1_26.lib | なし |
- 命名規則
- vc100 - Visual C++ 2010 (ex. vc90 = Visual C++ 2008)
- gd - デバッグ(debug version)
- s - 静的リンクライブラリ(static link)
- mt - マルチスレッド(Multithreaded)
- v1_26 - zlib version 1.26
マルチスレッド(/MT)
- win32/MakeFile.msc を書き換える
# variables STATICLIB = lib_zlib_vc100_mt_s_v1_26.lib CFLAGS = -nologo -MT -W3 -O2 -Oy- -Z7 -Fd"zlib" $(LOC)
- あとはこのページの上のほうに書いた通り、nmake!
マルチスレッドデバッグ(/MTd)
- win32/MakeFile.msc を書き換える
# variables STATICLIB = lib_zlib_vc100_mt_sgd_v1_26.lib
CFLAGS = -nologo -MTd -W3 -O2 -Oy- -Z7 -Fd"zlib" $(LOC)
- あとはこのページの上のほうに書いた通り、nmake!