跳转至内容

MinGW 包指南

来自 ArchWiki
Arch 软件包指南

32位CLRCMake交叉编译DKMSEclipseElectron字体Free PascalGNOMEGoHaskellJavaKDE内核模块LispMesonMinGWNode.js非自由软件OCamlPerlPHPPythonRRubyRust - 安全ShellVCSWebWine

本页面解释了如何为运行在 Windows 上的软件编写 PKGBUILDs

为了在 Linux 上构建 Windows 软件,需要

  • 用于 WinAPI 和 C 标准库的 Windows 头文件和导入库。有两种获取方式:
    • mingw-w64:提供支持 secure crt、Vista+ API、DDK (ReactOS) 和 DirectX (WINE) 的 32 位和 64 位工具链。有关支持功能的完整列表以及与旧版 MinGW.org 的区别,请参阅此处。可以通过安装官方仓库中的 mingw-w64-headersmingw-w64-crt 来获取。提供进一步库的 AUR 软件包依赖于这些包。
    • MinGW:提供对 DirectX 支持有限的 32 位工具链。它在线程局部存储 (TLS) 的实现和浮点库支持方面存在长期未解决的故障。它已从官方仓库和 AUR 中移除。
  • 编译器及其运行时库。
    • 对于 C/C++,可以使用 GCC 和 Clang。要使用 GCC,需要安装 mingw-w64-gcc,因为常规的 gcc 软件包无法使用。要使用 Clang,可以直接使用 clang 并指定 `*-w64-mingw32` 平台三元组作为目标。由于常规的 clang 软件包不包含 Windows 目标的编译器运行时库,因此需要单独编译它们或使用 mingw-w64-gcc 提供的运行时。提供进一步库的 AUR 软件包依赖于 mingw-w64-gcc
    • 对于 Rust,可以使用 mingw-w64-rustAUR。常规的 rust 软件包并非为了能够交叉编译到 Windows 而构建。如果使用 rustup 软件包安装了 Rust,则应添加 Windows 目标:rustup target add x86_64-pc-windows-gnu
    • 对于 Go,可以直接使用常规的 go 软件包。
  • C/C++ 标准库。可以使用 mingw-w64-gcc 提供的 libstdc++ 或 LLVM 项目的 libc++。提供进一步库的 AUR 软件包依赖于 libstdc++。
  • 链接器和额外工具。可以使用 mingw-w64-binutils 提供的 GNU binutils,或由 llvmlld 提供的 LLVM/lld。此外还有 mingw-w64-toolsAUR,提供一些额外的 Windows 特定工具。

对于 ix86/x86_64,典型的选择是使用 mingw-w64- 搭配 GCC/libstdc++ 和 binutils。因此,遵循 mingw-w64-pkgname 命名规则的 AUR 软件包均采用此方案。本 Wiki 页面的其余部分将重点讨论这些软件包。

此外还有名为 llvm-mingw-w64-pkgname 的 AUR 软件包,它们使用 LLVM/Clang/libc++,除了 i686 和 x86_64 之外还支持 aarch64。这些软件包依赖于 https://github.com/mstorsjo/llvm-mingw 的构建版本,不使用 Arch Linux 提供的 LLVM/Clang。目前仅存在少量核心软件包。

还有由 https://github.com/Martchus/PKGBUILDs 提供的名为 mingw-w64-clang-arch-pkgname 的软件包。这些软件包使用 Arch Linux 提供的 llvm, lldclang,并在其之上仅提供 mingw-w64、LLVM 编译器运行时和 libc++。这些软件包目前仅针对 aarch64 目标存在。它们主要是通过转换脚本从 mingw-w64-pkgname AUR 软件包生成的,以便在无需过多额外工作的情况下提供除核心工具链以外的内容。目前已有 100 多个 mingw-w64-pkgname 软件包被转换为 mingw-w64-clang-aarch64-pkgname 软件包。由于它们是自动生成的,因此尚未上传到 AUR,但可以在上述 GitHub 仓库中找到生成器和二进制仓库。

包命名

mingw-w64 的软件包应命名为 mingw-w64-pkgname。如果构建的是软件包的静态变体,请在包名后加上 -static 后缀(见下文必要情况)。

打包

跨平台软件包的打包可能相当棘手,因为存在许多不同的构建系统和底层古怪之处。但请注意以下几点:

  • 始终将 mingw-w64-crt 添加到 depends 中,除非它依赖于另一个隐式依赖于它的软件包
  • 始终将 mingw-w64-gcc 添加到 makedepends 中,除非使用了 mingw-w64-configureAURmingw-w64-cmakeAUR
  • 始终在 options 中添加 !strip, staticlibs!buildflags
  • 始终使用原始的 pkgdesc 并在 pkgdesc 末尾追加 (mingw-w64)
  • 始终使用并遵循官方软件包的原始 pkgver
  • 始终构建库的 32 位和 64 位版本
  • 始终将所有内容放在 /usr/i686-w64-mingw32/usr/x86_64-w64-mingw32 前缀下
  • 始终使用 any 作为架构(除非软件包包含必须在构建系统上运行的可执行文件)
  • 始终构建共享库和静态库
    • 基于 autotools 的项目通常支持一次性同时构建;使用 mingw-w64-configureAUR 时,共享库和静态库均已启用
    • 如果构建系统或项目不支持此操作,请分别构建
    • 如果共享构建和静态构建冲突(例如因为头文件或 CMake 配置文件不同),考虑将静态库安装到 /usr/i686-w64-mingw32/static/usr/x86_64-w64-mingw32/static
    • 对于较大的项目,考虑创建一个单独的 -static 软件包
  • 考虑删除不需要的文档 (rm -r $pkgdir/usr/i686-w64-mingw32/share/{doc,info,man}, rm -r $pkgdir/usr/x86_64-w64-mingw32/share/{doc,info,man})
  • 考虑使用 mingw-w64-configureAUR 进行 configure 脚本构建
  • 考虑使用 mingw-w64-cmakeAUR 进行 CMake 构建
  • 考虑使用 mingw-w64-mesonAUR 进行 Meson 构建
  • 考虑使用 mingw-w64-makeAUR 进行原始 Makefile 构建
  • 考虑使用 mingw-w64-qt6-baseAUR 进行 QMake 构建
  • 考虑在 package() 的 for 循环中像下面的 PKGBUILD 示例那样,使用 ${_arch}-strip 显式地去除符号
    • 考虑使用 find 命令遍历 $pkgdir,因为并非所有 DLL、静态库或可执行文件都位于其相应位置。
      • 如果二进制文件是 DLL,请使用 ${_arch}-strip --strip-unneeded *.dll
      • 如果二进制文件是静态库,请使用 ${_arch}-strip -g *.a
  • 如果软件包是模块化的(需要某些构建依赖,但这些依赖对最终用户是可选的),请将这些依赖添加到 makedependsoptdepends 中。如果更新现有软件包,请确保将其从 depends 中减去。使用示例:mingw-w64-qt6-baseAUR
  • 如果软件包安装了 $pkgdir/usr/${_arch}/bin/*-config 脚本,请将其符号链接到 $pkgdir/usr/bin/${_arch}-*-config
  • 如果软件包使用 autoconf,请为 configure 显式设置 --build="$CHOST" 以规避 autoconf bug #108405,或使用 mingw-w64-configureAUR

如上所述,所有文件应安装到 /usr/i686-w64-mingw32/usr/x86_64-w64-mingw32。具体而言,所有 DLL 应放在 /usr/*-w64-mingw32/bin 中,因为它们是运行时需要的动态库。对应的 .dll.a 文件应放在 /usr/*-w64-mingw32/lib 中。请删除 /usr/share 中任何不必要的文档以及其他可能不需要的文件。交叉编译软件包并非面向用户,而是面向编译器和二进制分发,因此应尽量将其体积减小。

始终尝试将 mingw-w64 软件包中的 pkgver 与 Arch Linux 官方仓库(而非 testing 仓库)中相应常规软件包的 pkgver 保持一致。这可以确保交叉编译的软件在 Windows 上以完全相同的方式运行,而不会出现意外 bug。如果 Arch 中的软件包版本过旧,通常有充分的理由,你仍然应该遵循 Arch 的版本而非使用最新的上游发行版。如果对应的原生软件包在 AUR 中,则无需遵循此版本策略,因为许多 AUR 软件包经常被遗弃或无人维护。

示例

以下示例将尝试涵盖一些最常见的约定和构建系统。

Autotools

pkgname=mingw-w64-foo
pkgver=1.0
pkgrel=1
pkgdesc="Foo bar (mingw-w64)"
arch=('any')
url="http://www.foo.bar"
license=('GPL')
makedepends=('mingw-w64-configure')
depends=('mingw-w64-crt')
options=('!strip' '!buildflags' 'staticlibs')
source=("http://www.foo.bar/foobar.tar.gz")
sha256sums=('8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406')

_architectures="i686-w64-mingw32 x86_64-w64-mingw32"

build() {
  cd foo-$pkgver
  for _arch in ${_architectures}; do
    mkdir -p build-${_arch} && pushd build-${_arch}
    ${_arch}-configure ..
    make
    popd
  done
}

package() {
  cd "foo-$pkgver"
  for _arch in ${_architectures}; do
    make DESTDIR="${pkgdir}" install -C build-${_arch}
    ${_arch}-strip --strip-unneeded "$pkgdir"/usr/${_arch}/bin/*.dll
    ${_arch}-strip -g "$pkgdir"/usr/${_arch}/lib/*.a
  done
}

CMake

pkgname=mingw-w64-foo
pkgver=1.0
pkgrel=1
pkgdesc="Foo bar (mingw-w64)"
arch=('any')
url="http://www.foo.bar"
license=('GPL')
makedepends=('mingw-w64-cmake')
depends=('mingw-w64-crt')
options=('!strip' '!buildflags' 'staticlibs')
source=("http://www.foo.bar/foobar.tar.gz")
sha256sums=('8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406')

_architectures="i686-w64-mingw32 x86_64-w64-mingw32"

build() { 
  cd foo-$pkgver
  for _arch in ${_architectures}; do
    ${_arch}-cmake -B build-${_arch} .
    cmake --build build-${_arch}
  done
}

package() {
  cd "foo-$pkgver"
  for _arch in ${_architectures}; do
    DESTDIR="${pkgdir}" cmake --install build-${_arch}
    ${_arch}-strip --strip-unneeded "$pkgdir"/usr/${_arch}/bin/*.dll
    ${_arch}-strip -g "$pkgdir"/usr/${_arch}/lib/*.a
  done
}

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.