ぼく用あれこれまとめ

zlib 1.2.6 を導入したときのメモ

最終更新:

bokuyo

- view
管理者のみ編集可

zlib 1.2.6 を導入したときのメモ


ダウンロード

  • 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!

関連リンク

記事メニュー
目安箱バナー