MinGW PKGBUILD Guidelines
CLR – Cross – Eclipse – Free Pascal – GNOME – Go – Haskell – Java – KDE – Kernel – Lisp – MinGW – Nonfree – OCaml – Perl – Python – Ruby – VCS – Web – Wine
This page expains how to write PKGBUILDs for software running on Windows using GCC. There are two options to build software for Windows on Linux:
- [www.MinGW.org]: provides 32-bit toolchains with limited DirectX support. Available from Arch's [community] repository by installing mingw32-gcc.
- [mingw-w64.sourceforge.net]: provides 32 and 64-bit toolchains with secure crt, Vista+ API, DDK (ReactOS), and DirectX (WINE) support. For a full list of supported features and differences with the old MinGW.org, see here. Available in the AUR by installing mingw-w64-gcc
There are some differences between the packaging of both projects, detailed below.
Contents |
MinGW-w64
Package naming
A package for mingw-w64 should be named mingw-w64-pkgname. If a static variant of the package is being built, suffix the package name with -static.
Packaging
Packaging for cross platform packages can be fairly tricky as there are many different build systems and low-level quirks. Take a note of the following things though:
- always add mingw-w64-crt to
depends - always add mingw-w64-gcc to
makedepends - always add
!strip,staticlibsand!buildflagstooptions - always use the original
pkgdescand append(mingw-w64)to the end ofpkgdesc - always use and follow the original
pkgverof the official package - always add
unset LDFLAGS CPPFLAGSin front of toolchain configure/Makefile generation sequences - always build both 32-bit and 64-bit versions of libraries, unless of course the package can only target, or is meant to only target, 32-bit or 64-bit, or if problems arise building one of the two.
- always put all stuff under the
/usr/i686-w64-mingw32and/usr/x86_64-w64-mingw32prefix - always use
anyas the architecture - always build both shared and static binaries, unless they conflict
- always remove Win32 executables (*.exe) if the intended package is a library (
rm "$pkgdir"/usr/${_arch}/bin/*.exe) - consider removing unneeded documentation (
rm -r $pkgdir/usr/i686-w64-mingw32/share/{doc,info,man},rm -r $pkgdir/usr/x86_64-w64-mingw32/share/{doc,info,man}) - consider using mingw-w64-pkg-config for building with configure scripts
- consider using mingw-w64-cmake for building with CMake
- consider explicitly stripping symbols with
${_arch}-stripinpackage()'s for-loop as demonstrated in the below PKGBUILD examples.- if the binary is a DLL, use
${_arch}-strip --strip-unneeded *.dll - if the binary is a static lib, use
${_arch}-strip -g *.a
- if the binary is a DLL, use
As mentioned above, the files should all be installed into /usr/i686-w64-mingw-w64 and /usr/x86_64-w64-mingw32. Specifically, all .dll files should be put into /usr/*-w64-mingw-w64/bin as they are dynamic libraries needed at runtime. Their corresponding .dll.a files should go into /usr/*-w64-mingw-w64/lib. Please delete any unnecessary documentation and perhaps other files from /usr/share. Cross-compilations packages are not meant for the user but only for the compiler and as such you should try to make them as small as possible.
Always try to match the pkgver in your mingw-w64 packages to the pkgver of the corresponding regular packages in the official Arch Linux repos (not the testing repos). This ensures that the cross-compiled software works exactly the same way on Windows without any unexpected bugs. If packages in Arch are out-of-date, there usually is a good reason and you should still follow the Arch version instead of using the most recent upstream release.
Examples
The following examples will try to cover some of the most common conventions and build systems.
Autotools
# Maintainer: yourname <yourmail>
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-gcc')
depends=('mingw-w64-crt')
options=('!strip' '!buildflags' 'staticlibs')
source=("http://www.foo.bar/foobar.tar.gz")
md5sums=('4736ac4f34fd9a41fa0197eac23bbc24')
_architectures="i686-w64-mingw32 x86_64-w64-mingw32"
build() {
unset LDFLAGS
cd "${srcdir}/foo-$pkgver/"
for _arch in ${_architectures}; do
mkdir -p build-${_arch} && pushd build-${_arch}
../configure \
--prefix=/usr/${_arch} \
--host=${_arch}
make
popd
done
}
package() {
for _arch in ${_targets}; do
cd "${srcdir}/foo-$pkgver/build-${_arch}"
make DESTDIR="${pkgdir}" install
${_arch}-strip --strip-unneeded "${pkgdir}"/usr/${_arch}/bin/*.dll
${_arch}-strip -g "${pkgdir}"/usr/${_arch}/lib/*.a
done
}
CMake
# Maintainer: yourname <yourmail>
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")
md5sums=('4736ac4f34fd9a41fa0197eac23bbc24')
_architectures="i686-w64-mingw32 x86_64-w64-mingw32"
build() {
unset LDFLAGS
cd "$srcdir/foo-$pkgver/"
for _arch in ${_architectures}; do
mkdir -p build-${_arch} && pushd build-${_arch}
${_arch}-cmake \
-DCMAKE_BUILD_TYPE=Release \
..
make
popd
done
}
package() {
for _arch in ${_architectures}; do
cd "${srcdir}/foo-$pkgver/build-${_arch}"
make DESTDIR="${pkgdir}" install
${_arch}-strip --strip-unneeded "${pkgdir}"/usr/${_arch}/bin/*.dll
${_arch}-strip -g "${pkgdir}"/usr/${_arch}/lib/*.a
done
}
MinGW.org
Package naming
A package for mingw32 should be named mingw32-pkgname. If a static variant of the package is being built, suffix the package name with -static.
Packaging
Packaging for cross platform packages can be fairly tricky as there are many different build systems and low-level quirks. Take a note of the following things though:
- always add mingw32-runtime to
depends - always add mingw32-gcc to
makedepends - always add
!strip,staticlibsand!buildflagstooptions - always use the original
pkgdescand append(mingw32)to the end ofpkgdesc - always use and follow the original
pkgverof the official package - always add
unset LDFLAGS CPPFLAGSin front of toolchain configure/Makefile generation sequences - always put all stuff under the
/usr/i486-mingw32prefix - always use
anyas the architecture - always build both shared and static binaries, unless they conflict
- always remove Win32 executables (*.exe) if the intended package is a library
- consider using
!libtoolinoptionsif you get.lafiles in$pkgdir - consider removing unneeded documentation (
rm -r $pkgdir/usr/i486-mingw32/share/{doc,info,man}) - consider explicitly stripping symbols with
i486-mingw32-stripinpackage()- if the binary is a DLL, use
i486-mingw32-strip -x -g *.dll - if the binary is a static lib, use
i486-mingw32-strip -g *.a
- if the binary is a DLL, use
As mentioned above, the files should all be installed into /usr/i486-mingw32. Specifically, all .dll files should be put into /usr/i486-mingw32/bin as they are dynamic libraries needed at runtime. Their corresponding .dll.a files should go into /usr/i486-mingw32/lib. Please delete any unnecessary documentation and perhaps other files from /usr/share. Cross-compilations packages are not meant for the user but only for the compiler and as such you should try to make them as small as possible.
Always try to match the pkgver in your mingw packages to the pkgver of the corresponding regular packages in the official Arch Linux repos (not the testing repos). This ensures that the cross-compiled software works exactly the same way on mingw without any unexpected bugs. If packages in Arch are out-of-date, there usually is a good reason and you should still follow the Arch version instead of using the most recent upstream release.
Examples
The following examples will try to cover some of the most common conventions and build systems.
Plain Makefile
# Maintainer: yourname <yourmail>
pkgname=mingw32-foo
pkgver=1.0
pkgrel=1
pkgdesc="Foo bar (mingw32)"
arch=('any')
url="http://www.foo.bar"
license=('GPL')
makedepends=('mingw32-gcc')
depends=('mingw32-runtime')
options=('!strip' '!buildflags' 'staticlibs')
source=("http://www.foo.bar/foobar.tar.gz")
md5sums=('4736ac4f34fd9a41fa0197eac23bbc24')
build() {
cd "${srcdir}/foobar"
unset LDFLAGS
sed "s|LOCAL = /usr/local|LOCAL = ${pkgdir}/usr/i486-mingw32|g" -i Makefile
sed "s|CXX = gcc|CXX = i486-mingw32-gcc|g" -i Makefile
sed "s|CXXFLAGS = |CXXFLAGS = -fPIC |g" -i Makefile
# or with setconf instead of sed (add 'setconf' to makedepends)
#setconf Makefile LOCAL "$pkgdir/usr/i486-mingw32"
#setconf Makefile CXX i486-mingw32-gcc
#setconf Makefile CXXFLAGS -fPIC
make
}
package() {
cd "${srcdir}/foobar"
mkdir -p "${pkgdir}"/usr/i486-mingw32/{lib,include}
make install
chmod 644 "${pkgdir}"/usr/i486-mingw32/lib/libfoo.a
i486-mingw32-ranlib "${pkgdir}"/usr/i486-mingw32/lib/libfoo.a
i486-mingw32-strip -x -g "${pkgdir}"/usr/i486-mingw32/bin/*.dll
i486-mingw32-strip -g "${pkgdir}"/usr/i486-mingw32/lib/*.a
}
Autotools
# Maintainer: yourname <yourmail>
pkgname=mingw32-foo
pkgver=1.0
pkgrel=1
pkgdesc="Foo bar (mingw32)"
arch=('any')
url="http://www.foo.bar"
license=('GPL')
makedepends=('mingw32-gcc')
depends=('mingw32-runtime')
options=('!strip' '!buildflags' 'staticlibs')
source=("http://www.foo.bar/foobar.tar.gz")
md5sums=('4736ac4f34fd9a41fa0197eac23bbc24')
build() {
cd "${srcdir}/foobar"
unset LDFLAGS
./configure --prefix=/usr/i486-mingw32 --host=i486-mingw32
make
}
package() {
cd "${srcdir}/foobar"
make DESTDIR=${pkgdir} install
i486-mingw32-strip -x -g "${pkgdir}"/usr/i486-mingw32/bin/*.dll
i486-mingw32-strip -g "${pkgdir}"/usr/i486-mingw32/lib/*.a
}
CMake
# Maintainer: yourname <yourmail>
pkgname=mingw32-foo
pkgver=1.0
pkgrel=1
pkgdesc="Foo bar (mingw32)"
arch=('any')
url="http://www.foo.bar"
license=('GPL')
makedepends=('mingw32-gcc' 'cmake')
depends=('mingw32-runtime')
options=('!strip' '!buildflags' 'staticlibs')
source=("http://www.foo.bar/foobar.tar.gz"
"cmake-toolchain.cmake")
md5sums=('4736ac4f34fd9a41fa0197eac23bbc24'
'dd2b2db48187dff84050fe191d309d81')
build() {
cd "${srcdir}/foobar"
unset LDFLAGS
mkdir build && cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=/usr/i486-mingw32/ \
-DCMAKE_TOOLCHAIN_FILE=${srcdir}/cmake-toolchain.cmake
make
}
package() {
cd "${srcdir}/foobar"
cd build
make DESTDIR=${pkgdir} install
i486-mingw32-strip -x -g "${pkgdir}"/usr/i486-mingw32/bin/*.dll
i486-mingw32-strip -g "${pkgdir}"/usr/i486-mingw32/lib/*.a
}
In this case, the toolchain is specified externally in cmake-toolchain.cmake:
cmake-toolchain.cmake
# the name of the target operating system SET(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ SET(CMAKE_C_COMPILER i486-mingw32-gcc) SET(CMAKE_CXX_COMPILER i486-mingw32-g++) SET(CMAKE_RC_COMPILER i486-mingw32-windres) # here is the target environment located SET(CMAKE_FIND_ROOT_PATH /usr/i486-mingw32) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)