Difference between revisions of "MinGW package guidelines"
(→Autotools) |
(→Autotools) |
||
(16 intermediate revisions by 3 users not shown) | |||
Line 3: | Line 3: | ||
This page expains how to write [[PKGBUILD]]s for software running on Windows using GCC. There are two options to build software for Windows on Linux: | This page expains how to write [[PKGBUILD]]s for software running on Windows using GCC. There are two options to build software for Windows on Linux: | ||
− | + | ||
− | * [[#MinGW-w64|[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 [http://sourceforge.net/apps/trac/mingw-w64/wiki/Feature%20list here]. Available in the [[AUR]] by installing {{AUR| | + | * [[#MinGW-w64|[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 [http://sourceforge.net/apps/trac/mingw-w64/wiki/Feature%20list here]. Available from Arch's [[#.5Bcommunity.5D|[community]]] repository by installing {{Pkg|mingw-w64-gcc}}. |
+ | * [[#MinGW.org|[www.MinGW.org]]]: provides 32-bit toolchains with limited DirectX support. Available in the [[AUR]] by installing {{AUR|mingw32-gcc}} | ||
There are some differences between the packaging of both projects, detailed below. | There are some differences between the packaging of both projects, detailed below. | ||
Line 12: | Line 13: | ||
=== Package naming === | === Package naming === | ||
− | A package for mingw-w64 should be named {{Ic|mingw-w64-''pkgname'' | + | A package for mingw-w64 should be named {{Ic|mingw-w64-''pkgname''}}. If a static variant of the package is being built, suffix the package name with {{ic|-static}} (see below for the cases where this is necessary). |
=== Packaging === | === Packaging === | ||
Line 26: | Line 27: | ||
* always use {{ic|any}} as the architecture | * always use {{ic|any}} as the architecture | ||
* always build both shared and static binaries, unless they conflict | * always build both shared and static binaries, unless they conflict | ||
− | * always remove Win32 executables (*.exe) if the intended package is a library | + | * always remove Win32 executables (*.exe) if the intended package is a library ({{ic|<nowiki>rm "$pkgdir"/usr/${_arch}/bin/*.exe</nowiki>}}) |
− | |||
* consider removing unneeded documentation ({{ic|<nowiki>rm -r $pkgdir/usr/i686-w64-mingw32/share/{doc,info,man}</nowiki>}}, {{ic|<nowiki>rm -r $pkgdir/usr/x86_64-w64-mingw32/share/{doc,info,man}</nowiki>}}) | * consider removing unneeded documentation ({{ic|<nowiki>rm -r $pkgdir/usr/i686-w64-mingw32/share/{doc,info,man}</nowiki>}}, {{ic|<nowiki>rm -r $pkgdir/usr/x86_64-w64-mingw32/share/{doc,info,man}</nowiki>}}) | ||
* consider using {{AUR|mingw-w64-pkg-config}} for building with configure scripts | * consider using {{AUR|mingw-w64-pkg-config}} for building with configure scripts | ||
* consider using {{AUR|mingw-w64-cmake}} for building with CMake | * consider using {{AUR|mingw-w64-cmake}} for building with CMake | ||
* consider explicitly stripping symbols with {{ic|${_arch}-strip}} in {{ic|package()}}'s for-loop as demonstrated in the below PKGBUILD examples. | * consider explicitly stripping symbols with {{ic|${_arch}-strip}} in {{ic|package()}}'s for-loop as demonstrated in the below PKGBUILD examples. | ||
− | ** if the binary is a DLL, use {{ic|${_arch}-strip --strip-unneeded *.dll}} | + | ** consider using the `find` command to iterate over {{ic|$pkgdir}} since not all DLLs, static libraries, or executables may reside in their appropriate locations. |
− | ** if the binary is a static lib, use {{ic|${_arch}-strip -g *.a}} | + | *** if the binary is a DLL, use {{ic|${_arch}-strip --strip-unneeded *.dll}} |
+ | *** if the binary is a static lib, use {{ic|${_arch}-strip -g *.a}} | ||
+ | * if a package is modular (requires certain build dependencies, but said dependencies are optional to the end user) add these to {{ic|makedepends}} and {{ic|optdepends}}. Be sure to subtract them from {{ic|depends}} if updating an existing package. Example of this in use: {{AUR|mingw-w64-ruby}}, {{AUR|mingw-w64-allegro}} | ||
+ | * if a package installs a {{ic|$pkgdir/usr/${_arch}/bin/*-config}} script, symlink it to {{ic|$pkgdir/usr/bin/${_arch}-*-config}} | ||
− | As mentioned above, the files should all be installed into {{Ic|/usr/i686-w64- | + | As mentioned above, the files should all be installed into {{Ic|/usr/i686-w64-mingw32}} and {{Ic|/usr/x86_64-w64-mingw32}}. Specifically, all DLLs should be put into {{Ic|/usr/*-w64-mingw32/bin}} as they are dynamic libraries needed at runtime. Their corresponding {{Ic|.dll.a}} files should go into {{Ic|/usr/*-w64-mingw32/lib}}. Please delete any unnecessary documentation and perhaps other files from {{Ic|/usr/share}}. Cross-compilations packages are not meant for the user but only for the compiler and binary distribution, and as such you should try to make them as small as possible. |
− | Always try to match the {{Ic|pkgver}} in your mingw-w64 packages to the {{Ic|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. | + | Always try to match the {{Ic|pkgver}} in your mingw-w64 packages to the {{Ic|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. If the corresponding native package is in the AUR, you need not follow this version policy, as many AUR packages are often orphaned or left unmaintained. |
=== Examples === | === Examples === | ||
Line 74: | Line 77: | ||
package() { | package() { | ||
− | for _arch in ${ | + | for _arch in ${_architectures}; do |
cd "${srcdir}/foo-$pkgver/build-${_arch}" | cd "${srcdir}/foo-$pkgver/build-${_arch}" | ||
make DESTDIR="${pkgdir}" install | make DESTDIR="${pkgdir}" install | ||
− | ${_arch}-strip --strip-unneeded "$ | + | find "$pkgdir" -name '*.exe' -o -name '*.bat' -o -name '*.def' -o -name '*.exp' -o -name '*.manifest' -exec rm {} \; |
− | + | find "$pkgdir" -name '*.dll' -exec ${_arch}-strip --strip-unneeded {} \; | |
+ | find "$pkgdir" -name '*.dll' -o -name '*.a' -exec ${_arch}-strip -g {} \; | ||
done | done | ||
} | } | ||
Line 118: | Line 122: | ||
cd "${srcdir}/foo-$pkgver/build-${_arch}" | cd "${srcdir}/foo-$pkgver/build-${_arch}" | ||
make DESTDIR="${pkgdir}" install | make DESTDIR="${pkgdir}" install | ||
− | ${_arch}-strip --strip-unneeded "$ | + | find "$pkgdir" -name '*.exe' -o -name '*.bat' -o -name '*.def' -o -name '*.exp' -o -name '*.manifest' -exec rm {} \; |
− | + | find "$pkgdir" -name '*.dll' -exec ${_arch}-strip --strip-unneeded {} \; | |
+ | find "$pkgdir" -name '*.dll' -o -name '*.a' -exec ${_arch}-strip -g {} \; | ||
done | done | ||
} | } | ||
Line 190: | Line 195: | ||
cd "${srcdir}/foobar" | cd "${srcdir}/foobar" | ||
− | mkdir -p ${pkgdir}/usr/i486-mingw32/{lib,include} | + | mkdir -p "${pkgdir}"/usr/i486-mingw32/{lib,include} |
make install | make install | ||
− | chmod 644 ${pkgdir}/usr/i486-mingw32/lib/libfoo.a | + | chmod 644 "${pkgdir}"/usr/i486-mingw32/lib/libfoo.a |
− | i486-mingw32-ranlib ${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 | ||
} | } | ||
</nowiki>}} | </nowiki>}} | ||
Line 241: | Line 249: | ||
url="http://www.foo.bar" | url="http://www.foo.bar" | ||
license=('GPL') | license=('GPL') | ||
− | makedepends=('mingw32- | + | makedepends=('mingw32-cmake') |
depends=('mingw32-runtime') | depends=('mingw32-runtime') | ||
options=('!strip' '!buildflags' 'staticlibs') | options=('!strip' '!buildflags' 'staticlibs') | ||
Line 250: | Line 258: | ||
build() { | build() { | ||
− | cd "${srcdir}/foobar" | + | cd "${srcdir}/foobar-$pkgver" |
− | |||
unset LDFLAGS | unset LDFLAGS | ||
− | |||
mkdir build && cd build | mkdir build && cd build | ||
− | cmake | + | i486-mingw32-cmake \ |
− | - | + | -DCMAKE_BUILD_TYPE=Release |
− | + | .. | |
make | make | ||
} | } | ||
package() { | package() { | ||
− | cd "${srcdir}/foobar" | + | cd "${srcdir}/foobar-$pkgver" |
− | |||
cd build | cd build | ||
− | make DESTDIR=${pkgdir} install | + | make DESTDIR="${pkgdir}" install |
i486-mingw32-strip -x -g "${pkgdir}"/usr/i486-mingw32/bin/*.dll | i486-mingw32-strip -x -g "${pkgdir}"/usr/i486-mingw32/bin/*.dll | ||
i486-mingw32-strip -g "${pkgdir}"/usr/i486-mingw32/lib/*.a | i486-mingw32-strip -g "${pkgdir}"/usr/i486-mingw32/lib/*.a | ||
} | } | ||
</nowiki>}} | </nowiki>}} | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |
Revision as of 13:25, 20 November 2013
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:
- [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 from Arch's [community] repository by installing mingw-w64-gcc.
- [www.MinGW.org]: provides 32-bit toolchains with limited DirectX support. Available in the AUR by installing mingw32-gccAUR
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
(see below for the cases where this is necessary).
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-crtAUR to
depends
- always add mingw-w64-gccAUR to
makedepends
- always add
!strip
,staticlibs
and!buildflags
tooptions
- always use the original
pkgdesc
and append(mingw-w64)
to the end ofpkgdesc
- always use and follow the original
pkgver
of the official package - always add
unset LDFLAGS CPPFLAGS
in 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-mingw32
and/usr/x86_64-w64-mingw32
prefix - always use
any
as 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-configAUR for building with configure scripts
- consider using mingw-w64-cmakeAUR for building with CMake
- consider explicitly stripping symbols with
${_arch}-strip
inpackage()
's for-loop as demonstrated in the below PKGBUILD examples.- consider using the `find` command to iterate over
$pkgdir
since not all DLLs, static libraries, or executables may reside in their appropriate locations.- 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
- consider using the `find` command to iterate over
- if a package is modular (requires certain build dependencies, but said dependencies are optional to the end user) add these to
makedepends
andoptdepends
. Be sure to subtract them fromdepends
if updating an existing package. Example of this in use: mingw-w64-rubyAUR, mingw-w64-allegroAUR - if a package installs a
$pkgdir/usr/${_arch}/bin/*-config
script, symlink it to$pkgdir/usr/bin/${_arch}-*-config
As mentioned above, the files should all be installed into /usr/i686-w64-mingw32
and /usr/x86_64-w64-mingw32
. Specifically, all DLLs should be put into /usr/*-w64-mingw32/bin
as they are dynamic libraries needed at runtime. Their corresponding .dll.a
files should go into /usr/*-w64-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 binary distribution, 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. If the corresponding native package is in the AUR, you need not follow this version policy, as many AUR packages are often orphaned or left unmaintained.
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 ${_architectures}; do cd "${srcdir}/foo-$pkgver/build-${_arch}" make DESTDIR="${pkgdir}" install find "$pkgdir" -name '*.exe' -o -name '*.bat' -o -name '*.def' -o -name '*.exp' -o -name '*.manifest' -exec rm {} \; find "$pkgdir" -name '*.dll' -exec ${_arch}-strip --strip-unneeded {} \; find "$pkgdir" -name '*.dll' -o -name '*.a' -exec ${_arch}-strip -g {} \; 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 find "$pkgdir" -name '*.exe' -o -name '*.bat' -o -name '*.def' -o -name '*.exp' -o -name '*.manifest' -exec rm {} \; find "$pkgdir" -name '*.dll' -exec ${_arch}-strip --strip-unneeded {} \; find "$pkgdir" -name '*.dll' -o -name '*.a' -exec ${_arch}-strip -g {} \; 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
,staticlibs
and!buildflags
tooptions
- always use the original
pkgdesc
and append(mingw32)
to the end ofpkgdesc
- always use and follow the original
pkgver
of the official package - always add
unset LDFLAGS CPPFLAGS
in front of toolchain configure/Makefile generation sequences - always put all stuff under the
/usr/i486-mingw32
prefix - always use
any
as 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
!libtool
inoptions
if you get.la
files in$pkgdir
- consider removing unneeded documentation (
rm -r $pkgdir/usr/i486-mingw32/share/{doc,info,man}
) - consider explicitly stripping symbols with
i486-mingw32-strip
inpackage()
- 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-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-$pkgver" unset LDFLAGS mkdir build && cd build i486-mingw32-cmake \ -DCMAKE_BUILD_TYPE=Release .. make } package() { cd "${srcdir}/foobar-$pkgver" 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 }