glib:windows下基於MSYS2環境編譯glib2的過程
如果用MSVC編譯開源庫實在是麻煩,主要的麻煩在於第三方的開源庫本身還需要一些依賴庫,這些依賴庫在windows多數並不提供編譯好的二進位制版本,所以要先編譯安裝各種依賴庫,比如glib。
我也曾想用官方提供的二進位制庫(http://ftp.gnome.org/pub/gnome/binaries/win64/glib/),但官方的伺服器上從2010年以後就不再提供二進位制版本,只提供原始碼。所以如果要用glib的新版本,只能自己編譯,glib github上也有用MSVC編譯glib的說明(參見《Compiling the GTK+ (and Clutter) stack using Visual C++ 2008 and later》
對MSYS2我還是比較熟悉的,既然官方的建議也是在MSYS,那就在MSYS2下搞吧,MSYS2安裝很簡單,網上有教程,請自行百度。
安裝依賴庫
有了MSYS2安裝依賴庫就非常簡單了,以下是通過pacman安裝所有編譯glib所需要的工具和依賴庫。
# 安裝依賴庫和必須的工具
pacman --needed --noconfirm -S automake autoconf make libtool unzip glib2-devel intltool pcre-devel \
mingw-w64-x86_64-toolchain mingw-w64-x86_64-pcre
# 可選工具用於生成文件
#pacman --needed --noconfirm -S gtk-doc
下載glib
# 從github上下載2.54.3版本的原始碼
wget https://github.com/GNOME/glib/archive/2.54 .3.zip -O glib-2.54.3.zip
# 原始碼解壓縮
unzip glib-2.54.3.zip || exit -1
編譯
cd glib-2.54.3
# 第一次要執行autogen.sh才會生成./configure,後續可以直接執行./configure來修改編譯配置
./autogen.sh --prefix=/your/install/path
# 編譯並安裝到prefix指定的位置
make install -j8
生成MSVC import library (.lib)
問題來了,在MSYS2下編譯用的是MinGW編譯器,生成的匯入庫(import library)都字尾是.dll.a
,MSVC怎麼使用呢?其實MinGW生成的import library,MSVC是可以直接用的,直接新增到msvc工程就可以。
但如果你是用cmake來組織專案,在MSVC編譯環境下cmake的find_library
是找不到字尾為.dll.a
的import library.
怎麼辦呢?
其實glib的Makefile是支援在編譯時生成MSVC的 .lib .def
檔案的。隨便開啟一個glib的Makefile(比如glib/Makefile),就可以找到生成.lib
的程式碼:
glib-2.0.lib: libglib-2.0.la glib.def
$(AM_V_GEN) lib.exe -machine:X64 -name:libglib-2.0-$(LT_CURRENT_MINUS_AGE).dll -def:$(builddir)/glib.def -out:$@
可以看到Makefile生成 .lib 是呼叫MSVC的lib.exe
(在MSVC bin資料夾下)程式來完成的。而預設情況下,MSYS2環境中搜索路徑($PATH
)中沒有MSVC編譯器的安裝位置(bin).所以這一條命令不能執行,不能生成lib。
解決的辦法就是執行編譯之前將MSVC 編譯器的安裝位置(bin)加入$PATH
:
# 以Visual Studio 2015為例
PATH="/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin":$PATH
make install
安裝後的目錄結構.dll.a
,.lib
都有了。
glib-2.54.3-x86_64
├── bin
│ ├── gdbus.exe
│ ├── gdbus-codegen
│ ├── gio.exe
│ ├── gio-querymodules.exe
│ ├── glib-compile-resources.exe
│ ├── glib-compile-schemas.exe
│ ├── glib-genmarshal
│ ├── glib-gettextize
│ ├── glib-mkenums
│ ├── gobject-query.exe
│ ├── gresource.exe
│ ├── gsettings.exe
│ ├── gspawn-win64-helper.exe
│ ├── gspawn-win64-helper-console.exe
│ ├── libgio-2.0-0.dll
│ ├── libglib-2.0-0.dll
│ ├── libgmodule-2.0-0.dll
│ ├── libgobject-2.0-0.dll
│ └── libgthread-2.0-0.dll
├── include
│ ├── gio-win32-2.0
│ └── glib-2.0
├── lib
│ ├── charset.alias
│ ├── gio
│ ├── gio-2.0.lib
│ ├── glib-2.0
│ ├── glib-2.0.lib
│ ├── gmodule-2.0.lib
│ ├── gobject-2.0.lib
│ ├── gthread-2.0.def
│ ├── gthread-2.0.lib
│ ├── libgio-2.0.dll.a
│ ├── libgio-2.0.la
│ ├── libglib-2.0.dll.a
│ ├── libglib-2.0.la
│ ├── libgmodule-2.0.dll.a
│ ├── libgmodule-2.0.la
│ ├── libgobject-2.0.dll.a
│ ├── libgobject-2.0.la
│ ├── libgthread-2.0.dll.a
│ ├── libgthread-2.0.la
│ └── pkgconfig
└── share
├── aclocal
├── bash-completion
├── gdb
├── gettext
├── glib-2.0
└── locale