2023/12/01(金) [n年前の日記]
#1 [prog][windows] FreeImageライブラリをMinGWで使ってみたい
C/C++から利用できる、画像読み込みをしてくれる FreeImage というライブラリがある。
_The FreeImage Project
Windows10 x64 22H2 + MSYS2 + MinGW64 上であれば、FreeImage のパッケージが用意されているので、該当パッケージをインストールするだけで利用できるようになる。そのことについては以前試した。
_mieki256's diary - FreeImageとDevILライブラリを試用
これを、MinGW (g++ 9.2.0) から利用してみたいと思い立った。環境は Windows10 x64 22H2。
_The FreeImage Project
Windows10 x64 22H2 + MSYS2 + MinGW64 上であれば、FreeImage のパッケージが用意されているので、該当パッケージをインストールするだけで利用できるようになる。そのことについては以前試した。
_mieki256's diary - FreeImageとDevILライブラリを試用
これを、MinGW (g++ 9.2.0) から利用してみたいと思い立った。環境は Windows10 x64 22H2。
◎ ファイルを入手 :
_The FreeImage Project
公式サイトから、以下の2つを入手。バージョンは FreeImage 3.18.0。2018/08/01頃に公開された版らしい。
公式サイトから、以下の2つを入手。バージョンは FreeImage 3.18.0。2018/08/01頃に公開された版らしい。
- FreeImage3180.zip : ソースファイル群
- FreeImage3180Win32Win64.zip : VisualC++用のライブラリファイル(バイナリ)
◎ MinGW用ライブラリファイルに変換 :
FreeImage3180Win32Win64.zip を解凍してみたところ、README.minGW というテキストファイルがあった。その中で、MinGW用ライブラリファイル、libfreeimage.a への変換方法が書いてあった。FreeImage.dll の中にある関数名をリストアップして、その関数を呼ぶライブラリファイルになるらしい。いわゆる動的リンク、というヤツだろうか。
解凍して得られたフォルダ内の、Dist\x32\ に移動して作業。
とりあえず、これで、libfreeimage.a が生成できた。各ファイルを以下の場所にコピーしておく。
余談。ググってたら、pexports について、この日記にもメモしてあった…。完全に記憶の中から無くなっていた…。
_mieki256's diary - dllからMinGW用のライブラリファイルを作成
解凍して得られたフォルダ内の、Dist\x32\ に移動して作業。
pexports FreeImage.dll | sed "s/^_//" > libfreeimage.def dlltool --add-underscore -d libfreeimage.def -l libfreeimage.a
- pexports を使って、dll内の関数名の一覧を libfreeimage.def に書き込む。
- dlltool を使って、ライブラリファイル libfreeimage.a を作成する。
- pexports は、自分の環境では、何故か Strawberry Perl 5.32.0.1 x64 のインストールフォルダの中にあった。調べてみたら、本来は MinGW Installer 経由でインストールできるようだなと…。パッケージが用意されてた。
- dlltool は、Mingwインストールフォルダ\bin\ の中にあった。
とりあえず、これで、libfreeimage.a が生成できた。各ファイルを以下の場所にコピーしておく。
- libfreeimage.a を、MinGWインストールフォルダ\lib\ にコピー。
- FreeImage.dll を、MinGWインストールフォルダ\bin\ にコピー。
- MinGWインストールフォルダ\include\
- MinGWインストールフォルダ\lib\gcc\mingw32\9.2.0\include\c++\
余談。ググってたら、pexports について、この日記にもメモしてあった…。完全に記憶の中から無くなっていた…。
_mieki256's diary - dllからMinGW用のライブラリファイルを作成
◎ FreeImageを使うファイルをビルド :
FreeImage を使うプログラムをビルドしたい時は、以下のように -lfreeimage を指定すればいいらしい。
ちなみに、上記の指定では、-static を付けているので、極力静的リンクをしてくれるらしい。ただ、前述のように、FreeImage.dll は動的リンクなので、出来上がった exe を実行するには、別途 FreeImage.dll が必要になる。
g++ -static 01_load_png01.cpp -o 01_load_png01.exe -lfreeimage
ちなみに、上記の指定では、-static を付けているので、極力静的リンクをしてくれるらしい。ただ、前述のように、FreeImage.dll は動的リンクなので、出来上がった exe を実行するには、別途 FreeImage.dll が必要になる。
◎ stdlib.h が見つからないというエラーが出た :
以前、
_MSYS2 + MinGW64用に書いたサンプル
を MinGW でビルドしようとしたら、fatal error: stdlib.h: No such file or directory というエラーが出た。
includeパス(ヘッダーファイル群が入ってる場所)を指定する環境変数がおかしかったらしい…。以下のように環境変数を設定したらエラーが出ずにビルドが通るようになった。
ちなみに、元々は以下のように指定していた。
関連情報を調べたところ、CPATH という環境変数で、C/C++共通のヘッダファイルの場所を指定できるらしい。合ってるのかどうかわからんけど、とりあえず以下のような指定をしておいた。
includeパス(ヘッダーファイル群が入ってる場所)を指定する環境変数がおかしかったらしい…。以下のように環境変数を設定したらエラーが出ずにビルドが通るようになった。
CPLUS_INCLUDE_PATH=(MinGWインストールフォルダ)\lib\gcc\mingw32\9.2.0\include\c++
ちなみに、元々は以下のように指定していた。
CPLUS_INCLUDE_PATH=(MinGWインストールフォルダ)\include
関連情報を調べたところ、CPATH という環境変数で、C/C++共通のヘッダファイルの場所を指定できるらしい。合ってるのかどうかわからんけど、とりあえず以下のような指定をしておいた。
set MINGW_PATH=(MinGWインストールフォルダ) set CPATH=%MINGW_PATH%\include set C_INCLUDE_PATH=%MINGW_PATH%\include set CPLUS_INCLUDE_PATH=%MINGW_PATH%\lib\gcc\mingw32\9.2.0\include\c++
◎ FreeImage を静的リンクできない :
生成されたexeファイルが要求してくる dll を調べたら以下のようになった。
.exe とは別に、FreeImage.dll が必要な状態。いわゆる動的リンク。コンパイル済みの FreeImage バイナリを利用する分には、こういう状態になる。
どうせなら静的リンクをしたい。README.minGW を眺めたら、「静的リンクができる FreeImage (libfreeimage.a) は、環境変数 FREEIMAGE_LIBRARY_TYPE を STATIC に変更してビルドすれば作れる」と書いてあった。試しにビルドしてみる。
FreeImage3180.zip を解凍。
Makefile.mingw の、18行目のコメントアウトを外すように修正。
以下を実行。
あるいは、Makefile の最初のあたりの、MAKEFILE = gnu という指定を、mingw に書き変えて、その状態で make とだけ打っても良い。
Dist\ の中に以下の2ファイルが生成された。
それぞれ、以下の場所にコピーする。
しかし、このファイルを使ってビルドすると、ld.exe (リンカ)がエラーを出してしまう…。
_c++ - Fail to static linking FreeImage 3.15.4 on MingW - Stack Overflow
以前は FreeImage 3.15.4 で成功したという話を見かけたので、3.15.4 や 3.17.0 (FreeImage3154.zip, FreeImage3170.zip) を入手して試してみたけれど、3.15.4 も 3.17.0 もビルドの途中でエラーが出てしまう…。3.18.0 ならビルドだけは通るのだけど…。
_FreeImage / Discussion / Help: MinGW compiling errors
_FAQ - The FreeImage Project
FAQページに、静的リンクは難しいぞ、と書いてあるように見える…。基本的に、dll が別にあることを前提に作られているっぽい。
色々試してたら、静的リンクができた、かもしれない。以下の指定でリンカがエラーを出さなくなったし、生成された .exe もそれらしく動いてくれた。
要求される dll を調べてみる。
freeimage.dll の名前が出てこなくなった。
生成された .exe も、freeimage.dll を使う版は 2.2MBだったけど、静的リンクをしたら 8.9MB になった。今までよりサイズが大きくなったので、静的リンクされているのだろう。たぶん。
でもまあ、dll を使って動作するようにしておくか…。元々、動的リンクで使うことを前提にしてあるライブラリのようだし…。
> objdump -p 01_load_png01.exe | grep -e "DLL Name" DLL Name: FreeImage.dll DLL Name: KERNEL32.dll DLL Name: msvcrt.dll DLL Name: msvcrt.dll
.exe とは別に、FreeImage.dll が必要な状態。いわゆる動的リンク。コンパイル済みの FreeImage バイナリを利用する分には、こういう状態になる。
どうせなら静的リンクをしたい。README.minGW を眺めたら、「静的リンクができる FreeImage (libfreeimage.a) は、環境変数 FREEIMAGE_LIBRARY_TYPE を STATIC に変更してビルドすれば作れる」と書いてあった。試しにビルドしてみる。
FreeImage3180.zip を解凍。
Makefile.mingw の、18行目のコメントアウトを外すように修正。
#FREEIMAGE_LIBRARY_TYPE = STATIC ↓ FREEIMAGE_LIBRARY_TYPE = STATIC
以下を実行。
make -f Makefile.mingw
あるいは、Makefile の最初のあたりの、MAKEFILE = gnu という指定を、mingw に書き変えて、その状態で make とだけ打っても良い。
MAKEFILE = gnu ↓ MAKEFILE = mingw
Dist\ の中に以下の2ファイルが生成された。
- FreeImage.h
- libFreeImage.a
それぞれ、以下の場所にコピーする。
- libfreeimage.a を、(MinGWインストールフォルダ)\lib\ にコピー。
- FreeImage.h を、(MinGWインストールフォルダ)\include\ にコピー。
- FreeImage.h を、(MinGWインストールフォルダ)\lib\gcc\mingw32\9.2.0\include\c++\ にコピー。
しかし、このファイルを使ってビルドすると、ld.exe (リンカ)がエラーを出してしまう…。
> g++ 01_load_png01.cpp -o 01_load_png01.exe -lfreeimage -static d:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\xxxxxxxxx\AppData\Local\Temp\ccmw2cGP.o:01_load_png01.cpp:(.text+0x3e): undefined reference to `_imp__FreeImage_Initialise@4' d:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\xxxxxxxxx\AppData\Local\Temp\ccmw2cGP.o:01_load_png01.cpp:(.text+0x48): undefined reference to `_imp__FreeImage_GetVersion@0' d:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\xxxxxxxxx\AppData\Local\Temp\ccmw2cGP.o:01_load_png01.cpp:(.text+0x5f): undefined reference to `_imp__FreeImage_GetCopyrightMessage@0' ...
_c++ - Fail to static linking FreeImage 3.15.4 on MingW - Stack Overflow
以前は FreeImage 3.15.4 で成功したという話を見かけたので、3.15.4 や 3.17.0 (FreeImage3154.zip, FreeImage3170.zip) を入手して試してみたけれど、3.15.4 も 3.17.0 もビルドの途中でエラーが出てしまう…。3.18.0 ならビルドだけは通るのだけど…。
_FreeImage / Discussion / Help: MinGW compiling errors
_FAQ - The FreeImage Project
FAQページに、静的リンクは難しいぞ、と書いてあるように見える…。基本的に、dll が別にあることを前提に作られているっぽい。
- 最初に FreeImage_Initialise() を呼んで、最後に FreeImage_DeInitialise() を呼べ、とか。
- #define FREEIMAGE_LIB を追加せよ、とか。
- あるいはリンカに、-DFREEIMAGE_LIB を追加したり、-lwsock32 -lws2_32 も追加せよ、とか。
色々試してたら、静的リンクができた、かもしれない。以下の指定でリンカがエラーを出さなくなったし、生成された .exe もそれらしく動いてくれた。
g++ 01_load_png01.cpp -DFREEIMAGE_LIB -static -lfreeimage -lwsock32 -lws2_32 -o 01_load_png01.exe
要求される dll を調べてみる。
> objdump -p 01_load_png01.exe | grep -e "DLL Name" DLL Name: KERNEL32.dll DLL Name: msvcrt.dll DLL Name: msvcrt.dll DLL Name: WSOCK32.DLL
freeimage.dll の名前が出てこなくなった。
生成された .exe も、freeimage.dll を使う版は 2.2MBだったけど、静的リンクをしたら 8.9MB になった。今までよりサイズが大きくなったので、静的リンクされているのだろう。たぶん。
でもまあ、dll を使って動作するようにしておくか…。元々、動的リンクで使うことを前提にしてあるライブラリのようだし…。
[ ツッコむ ]
以上です。