MXE静态编译相关库

准备MXE运行环境

1
2
3
4
5
6
7
# Debian系下编译,编译32位的话还需要安装:g++-multilib libc6-dev-i386
sudo apt install autoconf automake autopoint bash bison bzip2 flex \
g++ gettext git gperf intltool lzip make openssl p7zip-full patch \
perl python3 python3-mako ruby sed unzip wget xz-utils libtool-bin \
libgdk-pixbuf2.0-dev libltdl-dev libssl-dev libxml-parser-perl

# 其他系统的要求到这查看:https://mxe.cc/#requirements

获取MXE并构建静态库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 可设置代理来加速下载
# export http_proxy="192.168.128.1:7890"
# export https_proxy="192.168.128.1:7890"

# 从GitHub上克隆MXE项目
git clone https://github.com/mxe/mxe.git
cd mxe

# 使用MXE项目构建的例子
make gcc -j 8 MXE_TARGETS='x86_64-w64-mingw32.static'
make glib -j 8 MXE_TARGETS='x86_64-w64-mingw32.static i686-w64-mingw32.shared'
make cairo -j 8 MXE_TARGETS='x86_64-w64-mingw32.static' MXE_USE_CCACHE= PREFIX=/home/leux/cairo

# MXE_TARGETS 的可选值及其含义
x86_64-w64-mingw32.static # 可生成运行在64位Windows上的静态可执行文件
x86_64-w64-mingw32.shared # 可生成运行在64位Windows上的动态可执行文件
i686-w64-mingw32.static # 可生成运行在32位Windows上的静态可执行文件
i686-w64-mingw32.shared # 可生成运行在32位Windows上的动态可执行文件

# 其他相关选项
make update # 更新所有源码包
make clean # 删除所有构建的包
make clean-junk # 删除所有未使用的文件,包括未使用的软件包文件、临时文件夹和日志
make show-deps-gtk3 # 显示gtk3的所有依赖
make check-requirements # 检查编译系统是否满足MXE项目所需的依赖条件
make download -j 8 # 并行下载所有源码包
make download-only-foo # 只下载foo源码包而不下载其依赖包
make download-gtk3 -j 8 # 并行下载gtk3及其依赖项的源码包
make foo_SOURCE_TREE=/src # 指定foo包源码所在路径绕过下载,校验和和打补丁
MXE_TMP=/tmp/mxe-tmp # 设置MXE项目编译时临时目录所在路径,默认在mxe目录下
MXE_USE_CCACHE= # 关闭ccache功能
EXCLUDE_PKGS='pcre' # 构建的包不包括pcre和所有依赖pcre的下游包
PREFIX=/home/leux/cairo # 构建完成的安装目录,默认 $MXE_DIR/usr

用生成的库交叉编译MXE项目中不存在的新包

  1. 配置相关环境变量
1
2
3
4
5
6
export PATH=$PATH:/home/leux/mxe/usr/bin
export PKG_CONFIG_PATH="原生编译平台的pkgconfig目录路径"
export PKG_CONFIG_PATH_x86_64-w64-mingw32_static="mxe/usr/x86_64-w64-mingw32.static/lib/pkgconfig"

# 如果您使用的是自定义$PKG_CONFIG_PATH 条目,则可以为交叉编译添加单独的变量
# 使用 x86_64-w64-mingw32_static-pkg-config 而不是 pkg-config ,autotools会自动为您配置编译环境
  1. 使用autotools的项目可如下调用MXE生成的库
1
2
./configure --host=i686-w64-mingw32.static
make
  1. 交叉编译静态库需先强制构建其依赖的静态库
1
2
./configure --host=i686-w64-mingw32.static --enable-static --disable-shared
make
  1. 使用cmake构建的项目需要使用编译链的cmake
1
i686-w64-mingw32.static-cmake ...
  1. 交叉编译普通的Makefile项目
1
2
3
4
5
6
7
# 可能需要添加其他一些命令,具体取决于您的项目
CC=$(CROSS)gcc
LD=$(CROSS)ld
AR=$(CROSS)ar
PKG_CONFIG=$(CROSS)pkg-config

make CROSS=i686-w64-mingw32.static-
  1. 如果需要静态编译某程序,一般这些是不可少的 -static-libgcc -lstdc++ -lgcc_eh -lpthread -static
  1. 其他MXE中相关的信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
make gtk3 -j 8 MXE_TARGETS='x86_64-w64-mingw32.static' MXE_USE_CCACHE=

# 上面的命令会将相关的参数传给 mxe/src/gtk3.mk
PKG = gtk3
MXE_TARGETS := x86_64-w64-mingw32.static
MXE_DIR = /home/leux/mxe
MXE_TMP := $(shell pwd)
PREFIX = mxe/usr
BUILD = $(shell mxe/ext/config.guess)
TARGET = x86_64-w64-mingw32.static
MXE_GCC_THREADS = posix,win32

BUILD_DIR # 编译目录
SOURCE_DIR # 源码目录
PKG_CMAKE_OPTS # 选定包的CMKAE添加的选项
MXE_MFLAGS # 标准禁用文档,垃圾箱等(可能也或选项)-l--max-load
PKG_MFLAGS # 特定于包的覆盖(不太可能被使用)

# mxe中每成功编译一次,会在 usr/$(TARGET)/installed/ 下建空文件防止重复编译
--prefix=/usr/local/i586-mingw32 --host=i586-mingw32msvc --build=i686-linux
build # 构建 gcc 编译器的平台系统环境,编译该软件使用的平台
host # 是执行 gcc 编译器的平台系统环境,该软件运行的平台
target # 是让 gcc 编译器产生能在什么格式运行的平台的系统环境

使用MXE项目静态编译CAIRO图形库

  1. 编译Cairo静态库并获取静态编译所需的参数
1
2
3
4
5
6
7
make cairo -j 8 MXE_TARGETS='x86_64-w64-mingw32.static' PREFIX=/home/leux/cairo

export PKG_CONFIG_PATH=/home/leux/cairo/x86_64-w64-mingw32.static/lib/pkgconfig
pkg-config --libs --cflags --static cairo

# 执行了上面 pkg-config 命令后的输出
-pthread -mms-bitfields -DPCRE_STATIC -I/home/leux/cairo/x86_64-w64-mingw32.static/include/cairo -I/home/leux/cairo/x86_64-w64-mingw32.static/include -I/home/leux/cairo/x86_64-w64-mingw32.static/include/glib-2.0 -I/home/leux/cairo/x86_64-w64-mingw32.static/lib/glib-2.0/include -I/home/leux/cairo/x86_64-w64-mingw32.static/include -I/home/leux/cairo/x86_64-w64-mingw32.static/include/pixman-1 -I/home/leux/cairo/x86_64-w64-mingw32.static/include -I/home/leux/cairo/x86_64-w64-mingw32.static/include/freetype2 -I/home/leux/cairo/x86_64-w64-mingw32.static/include/libpng16 -I/home/leux/cairo/x86_64-w64-mingw32.static/include -L/home/leux/cairo/x86_64-w64-mingw32.static/lib -L/home/leux/cairo/x86_64-w64-mingw32.static/lib/../lib -L/home/leux/cairo/x86_64-w64-mingw32.static/lib -lcairo -lz -lmsimg32 -lgdi32 -lpixman-1 -lz -lmsimg32 -lgdi32 -lpixman-1 -lgobject-2.0 -lintl -liconv -lffi -lglib-2.0 -lintl -liconv -pthread -lws2_32 -lwinmm -lm -lole32 -lshlwapi -luuid -lpcre -lpixman-1 -lfontconfig -lexpat -lfreetype -lbz2 -lpng16 -lz -lpng16 -lz
  1. 使用MinGW64在Windows下静态编译Cairo程序
1
2
3
4
5
# 添加MinGW64到Windows系统变量
SET PATH=%PATH%;C:\Soft\mingw64\bin

# 静态编译命令
gcc taichi_png.c -o taichi.exe -pthread -mms-bitfields -DPCRE_STATIC -ID:\cairo\include\cairo -ID:\cairo\include\glib-2.0 -ID:\cairo\lib\glib-2.0\include -ID:\cairo\include\pixman-1 -ID:\cairo\include\freetype2 -ID:\cairo\include\libpng16 -ID:\cairo\include -LD:\cairo\lib -lcairo -lz -lmsimg32 -lgdi32 -lpixman-1 -lz -lmsimg32 -lgdi32 -lpixman-1 -lgobject-2.0 -lfontconfig -lintl -liconv -lffi -lglib-2.0 -lintl -liconv -pthread -lws2_32 -lwinmm -lm -lole32 -lshlwapi -luuid -lpcre -lpixman-1 -lexpat -lfreetype -lbz2 -lpng16 -lz -lpng16 -lz -static-libgcc -lstdc++ -lgcc_eh -static
  1. 静态编译时的错误情况
1
2
3
4
5
6
7
8
9
10
C:\Users\leux\Desktop>gcc taichi_png.c -o taichi.exe -pthread -mms-bitfields -DPCRE_STATIC -ID:\cairo\include\cairo -ID:\cairo\include\glib-2.0 -ID:\cairo\lib\glib-2.0\include -ID:\cairo\include\pixman-1 -ID:\cairo\include\freetype2 -ID:\cairo\include\libpng16 -ID:\cairo\include -LD:\cairo\lib -lcairo -lz -lmsimg32 -lgdi32 -lpixman-1 -lz -lmsimg32 -lgdi32 -lpixman-1 -lgobject-2.0 -lintl -liconv -lffi -lglib-2.0 -lintl -liconv -pthread -lws2_32 -lwinmm -lm -lole32 -lshlwapi -luuid -lpcre -lpixman-1 -lfontconfig -lexpat -lfreetype -lbz2 -lpng16 -lz -lpng16 -lz -static-libgcc -lstdc++ -lgcc_eh -static
C:/Soft/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: D:\cairo\lib\libfontconfig.a(fccfg.o): in function `FcConfigAdd':
/home/leux/mxe/tmp-fontconfig-x86_64-w64-mingw32.static/fontconfig-2.14.0/src/fccfg.c:1806: undefined reference to `libintl_fprintf'
C:/Soft/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: /home/leux/mxe/tmp-fontconfig-x86_64-w64-mingw32.static/fontconfig-2.14.0/src/fccfg.c:1809: undefined reference to `libintl_fprintf'
C:/Soft/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: /home/leux/mxe/tmp-fontconfig-x86_64-w64-mingw32.static/fontconfig-2.14.0/src/fccfg.c:1864: undefined reference to `__printf__'
......

# 解决问题:因为 `libfontconfig.a` 依赖 `libintl.a`。所以把 `-lfontconfig` 移动到 `-lintl` 参数之前
-lpixman-1 -lgobject-2.0 -lintl -liconv -lffi -lglib-2.0
-lpixman-1 -lgobject-2.0 -lfontconfig -lintl -liconv -lffi -lglib-2.0

使用MXE项目静态编译GTK3图形库

  1. 编译GTK3静态库并获取静态编译所需的参数
1
2
3
4
5
6
7
make gtk3 -j 8 MXE_TARGETS='x86_64-w64-mingw32.static' PREFIX=/home/leux/gtk3

export PKG_CONFIG_PATH=/home/leux/gtk3/x86_64-w64-mingw32.static/lib/pkgconfig
pkg-config --libs --cflags --static gtk+-3.0

# 执行了上面 pkg-config 命令后的输出
-DEPOXY_STATIC -DFRIBIDI_LIB_STATIC -pthread -mms-bitfields -DPCRE_STATIC -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/gtk-3.0 -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/cairo -I/home/leux/gtk3/x86_64-w64-mingw32.static/include -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/pango-1.0 -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/fribidi -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/harfbuzz -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/atk-1.0 -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/cairo -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/pixman-1 -I/home/leux/gtk3/x86_64-w64-mingw32.static/include -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/freetype2 -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/libpng16 -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/gdk-pixbuf-2.0 -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/libpng16 -I/home/leux/gtk3/x86_64-w64-mingw32.static/include -I/home/leux/gtk3/x86_64-w64-mingw32.static/include/glib-2.0 -I/home/leux/gtk3/x86_64-w64-mingw32.static/lib/glib-2.0/include -I/home/leux/gtk3/x86_64-w64-mingw32.static/include -L/home/leux/gtk3/x86_64-w64-mingw32.static/lib -L/home/leux/gtk3/x86_64-w64-mingw32.static/lib/../lib -L/home/leux/gtk3/x86_64-w64-mingw32.static/lib -lgtk-3 -lgdk-3 -lgdi32 -limm32 -lshell32 -lole32 -Wl,-luuid -lwinmm -ldwmapi -lsetupapi -lcfgmgr32 -lhid -lwinspool -lcomctl32 -lcomdlg32 -lepoxy -lopengl32 -lgdi32 -lopengl32 -lpangocairo-1.0 -lm -lgdi32 -lpangoft2-1.0 -lm -lpangowin32-1.0 -lm -lgdi32 -lpango-1.0 -lm -lfribidi -lharfbuzz -lm -latk-1.0 -lcairo-gobject -lcairo -lz -lmsimg32 -lgdi32 -lpixman-1 -lz -lmsimg32 -lgdi32 -lpixman-1 -lfontconfig -lexpat -lfreetype -lbz2 -lpng16 -lz -lharfbuzz -lfreetype -lbz2 -lpng16 -lz -lglib-2.0 -lintl -liconv -pthread -lws2_32 -lwinmm -lm -lpcre -lole32 -lshlwapi -luuid -lharfbuzz_too -lfreetype_too -lglib-2.0 -lintl -liconv -pthread -lws2_32 -lwinmm -lm -lpcre -lole32 -lshlwapi -luuid -lpng16 -lz -lgdk_pixbuf-2.0 -lm -lintl -liconv -ljpeg -lpng16 -lz -ltiff -lwebp -llzma -ljpeg -lz -lgio-2.0 -lintl -liconv -lshlwapi -ldnsapi -liphlpapi -lws2_32 -luuid -lgobject-2.0 -lintl -liconv -lffi -lgmodule-2.0 -pthread -lintl -liconv -lglib-2.0 -lintl -liconv -pthread -lws2_32 -lwinmm -lm -lole32 -lshlwapi -luuid -lpcre -lz
  1. 使用MinGW64在Windows下静态编译GTK3程序
1
2
3
4
5
# 添加MinGW64到Windows系统变量
SET PATH=%PATH%;C:\Soft\mingw64\bin

# 静态编译命令
gcc gtk3.c -o gtk3.exe -DEPOXY_STATIC -DFRIBIDI_LIB_STATIC -pthread -mms-bitfields -DPCRE_STATIC -ID:\gtk3\include\gtk-3.0 -ID:\gtk3\include\pango-1.0 -ID:\gtk3\include\fribidi -ID:\gtk3\include\harfbuzz -ID:\gtk3\include\atk-1.0 -ID:\gtk3\include\cairo -ID:\gtk3\include\pixman-1 -ID:\gtk3\include\freetype2 -ID:\gtk3\include\libpng16 -ID:\gtk3\include\gdk-pixbuf-2.0 -ID:\gtk3\include\libpng16 -ID:\gtk3\include\glib-2.0 -ID:\gtk3\lib\glib-2.0\include -ID:\gtk3\include -LD:\gtk3\lib -lgtk-3 -lgdk-3 -lgdi32 -limm32 -lshell32 -lole32 -Wl,-luuid -lwinmm -ldwmapi -lsetupapi -lcfgmgr32 -lhid -lwinspool -lcomctl32 -lcomdlg32 -lepoxy -lopengl32 -lgdi32 -lopengl32 -lpangocairo-1.0 -lm -lgdi32 -lpangoft2-1.0 -lm -lpangowin32-1.0 -lm -lgdi32 -lpango-1.0 -lm -lfribidi -lharfbuzz -lm -latk-1.0 -lcairo-gobject -lcairo -lz -lmsimg32 -lgdi32 -lpixman-1 -lz -lmsimg32 -lgdi32 -lpixman-1 -lfontconfig -lexpat -lfreetype -lbz2 -lpng16 -lz -lharfbuzz -lfreetype -lbz2 -lpng16 -lz -lglib-2.0 -lintl -liconv -pthread -lws2_32 -lwinmm -lm -lpcre -lole32 -lshlwapi -luuid -lharfbuzz_too -lfreetype_too -lglib-2.0 -lintl -liconv -pthread -lws2_32 -lwinmm -lm -lpcre -lole32 -lshlwapi -luuid -lpng16 -lz -lgdk_pixbuf-2.0 -lm -lintl -liconv -ljpeg -lpng16 -lz -ltiff -lwebp -llzma -ljpeg -lz -lgio-2.0 -lintl -liconv -lshlwapi -ldnsapi -liphlpapi -lws2_32 -luuid -lgobject-2.0 -lintl -liconv -lffi -lgmodule-2.0 -pthread -lintl -liconv -lglib-2.0 -lintl -liconv -pthread -lws2_32 -lwinmm -lm -lole32 -lshlwapi -luuid -lpcre -lz -static-libgcc -lstdc++ -lgcc_eh -static
  1. 静态编译时的错误情况
1
2
3
4
5
6
7
8
9
#################################################
C:/Soft/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lharfbuzz_too: No such file or directory
C:/Soft/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lfreetype_too: No such file or directory
collect2.exe: error: ld returned 1 exit status

# 这两个libxxx_too.a在Linux下是软连接到libxxx.a上的,而Win32下软连接就失效了
rm D:\gtk3\lib\libharfbuzz_too.a D:\gtk3\lib\libfreetype_too.a
cp D:\gtk3\lib\libharfbuzz.a D:\gtk3\lib\libharfbuzz_too.a
cp D:\gtk3\lib\libfreetype.a D:\gtk3\lib\libfreetype_too.a