aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2023-02-12 14:51:46 +0000
committerJuan J. Martinez <jjm@usebox.net>2023-02-12 15:04:02 +0000
commitdd896b93e33038119fabda0e73367e460a75996f (patch)
treeedbd5ae3b8ac7ac82411c6d2a09e9fc4a85a30fd
downloadcross-compile-hs-wine-dd896b93e33038119fabda0e73367e460a75996f.tar.gz
cross-compile-hs-wine-dd896b93e33038119fabda0e73367e460a75996f.zip
Initial import
-rw-r--r--.gitignore3
-rw-r--r--README.md84
-rwxr-xr-xbin/cabal-wine12
-rwxr-xr-xbootstrap72
4 files changed, 171 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3e14be5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+packages/
+cache/
+workdir/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..cf90a21
--- /dev/null
+++ b/README.md
@@ -0,0 +1,84 @@
+# Cross-compile Haskell on Linux targeting Windows using WINE
+
+This is aimed at Linux + Haskell + SDL2 + SDL2_Image, but it could be used for other cases.
+
+The main idea is to run the Windows version of all the needed compilers, on Linux using Wine. Cabal it is the entry point and it needs a script wrapping it so it runs with Wine and it can find the needed tools.
+
+It comes with no warranty, I'm documenting this for myself, and sharing it because *it is fiddly* and I hope that it might help other people.
+
+What is needed:
+
+- Cabal for Windows
+- GHC for Windows
+- MingGW-W64
+- SDL2 development for MinGW
+- pkg-config-lite for Windows
+- Wine on a Linux host (used Debian 11)
+- Patience and luck!
+
+Install Wine with:
+```
+sudo dpkg --add-architecture i386
+sudo apt-get update
+sudo apt-get install --no-install-recommends -y wine wine32 wine64
+```
+
+(or similar, I don't think it matters much as long it is a healthy Wine installation)
+
+## bootstrap script
+
+Edit the `bootstrap` script (you may need to adapt it to your system), and check that you are happy with the versions. It is a convenient way of setting up everything *for me*, but may not be useful for anybody else (also: it is a bit fragile).
+
+It requires: wget, 7z, unzip, tar and make (among other more common POSIX tools).
+
+The directory structure will be:
+
+- cache: where the requirements are downloaded.
+- packages: where the different Windows tools are setup.
+- workdir: where you should put your project (can be in any directory).
+- bin: contains `cabal-wine` helper.
+
+Currently I'm using:
+
+- Cabal 3.8.1.0
+- GHC 9.2.5
+- MinGW-W64 12.2.0
+- SDL2 2.26.3
+- SDL2_Image 2.6.3
+
+**Important**: you need to copy SDL2.dll and SDL2_image.dll to your `system32` directory in WINE, usually:
+```
+~/.wine/drive_c/windows/system32/
+```
+This is needed to compile sdl2 and sdl2-image. When you have your binary, you need to distribute those two DLLs with your .EXE.
+
+## Updating packages
+
+Run `bin/cabal-wine update` and Cabal should download the latest package list from hackage.
+
+## Building your peoject
+
+Get into workdir/your-project and run:
+
+`../../bin/cabal-wine build --builddir build`
+
+And it should work!
+
+## Troubleshooting
+
+**Extra logging**
+
+Pass `-v` option when running `cabal-wine` for exta information.
+
+**Failed to compile SDL2_Image**
+
+I have found that SDL2_Image is trying to include a SDL_Main when is not necessary.
+
+Once you have compiled sdl2, you can edit `packages/mingw64/x86_64-w64-mingw32/include/SDL2/SDL.h` and comment out the `#include "SDL_main.h"` line.
+
+There must be a better way of fixing this (perhaps a bug report to sdl2-image could help!).
+
+**Wine can't run the resulting binary**
+
+I use Debian stable, and the Wine version can be a bit old. It compiles fine, but running the resulting binary may not work. Try a more recent Wine version (tested with 8 and works fine).
+
diff --git a/bin/cabal-wine b/bin/cabal-wine
new file mode 100755
index 0000000..4e11e70
--- /dev/null
+++ b/bin/cabal-wine
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+set +e
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+BASE=`realpath $SCRIPT_DIR/..`
+
+export WINEPATH=`winepath -w $BASE/ghc/bin/`:`winepath -w $BASE/mingw64/bin/`:`winepath -w $BASE/bin/`
+export PKG_CONFIG_PATH=`winepath -w $BASE/packages/mingw64/x86_64-w64-mingw32/lib/pkgconfig`
+
+wine $BASE/packages/cabal/cabal.exe --http-transport=plain-http $* -w $BASE/packages/ghc/bin/ghc.exe --with-gcc=$BASE/packages/mingw64/bin/gcc.exe
+
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..aba6584
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+set +e
+
+PACKAGES="""
+https://downloads.haskell.org/~cabal/cabal-install-3.8.1.0/cabal-install-3.8.1.0-x86_64-windows.zip
+https://downloads.haskell.org/~ghc/9.2.5/ghc-9.2.5-x86_64-unknown-mingw32-integer-simple.tar.xz
+https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev2/x86_64-12.2.0-release-win32-seh-msvcrt-rt_v10-rev2.7z
+https://github.com/libsdl-org/SDL/releases/download/release-2.26.3/SDL2-devel-2.26.3-mingw.tar.gz
+https://github.com/libsdl-org/SDL_image/releases/download/release-2.6.3/SDL2_image-devel-2.6.3-mingw.tar.gz
+https://downloads.sourceforge.net/project/pkgconfiglite/0.28-1/pkg-config-lite-0.28-1_bin-win32.zip
+"""
+
+mkdir -p packages cache workdir
+
+for p in $PACKAGES; do
+ fname=`basename $p`
+ if [ -f cache/$fname ]; then
+ echo $fname already downloaded: OK
+ else
+ wget $p -O cache/$fname
+ fi
+done
+
+if [ -d packages/cabal ]; then
+ echo packages/cabal directory exists, skipping
+else
+ echo Extracting Cabal
+ unzip cache/cabal-install-3.8.1.0-x86_64-windows.zip -d packages/cabal
+fi
+
+if [ -d packages/ghc ]; then
+ echo packages/ghc directory exists, skipping
+else
+ echo Extracting GHC
+ tar -C packages -xJf cache/ghc-9.2.5-x86_64-unknown-mingw32-integer-simple.tar.xz
+ mv packages/ghc-9.2.5-x86_64-unknown-mingw32 packages/ghc
+fi
+
+if [ -f packages/cabal/pkg-config.exe ]; then
+ echo packages/cabal/pkg-config.exe exists, skipping
+else
+ echo Extracting pkg-config.exe
+ unzip -j cache/pkg-config-lite-0.28-1_bin-win32.zip pkg-config-lite-0.28-1/bin/pkg-config.exe -d packages/cabal
+fi
+
+if [ -d packages/mingw64 ]; then
+ echo packages/mingw84 directory exists, skipping
+else
+ echo Extracting MingGW-W64
+ 7z x -opackages cache/x86_64-12.2.0-release-win32-seh-msvcrt-rt_v10-rev2.7z
+fi
+
+if [ -d packages/sdl ]; then
+ echo packages/sdl directory exists, skipping
+else
+ echo Extractig SDL2
+ tar -C packages -xzf cache/SDL2-devel-2.26.3-mingw.tar.gz
+ mv packages/SDL2-2.26.3 packages/sdl
+ make CROSS_PATH=`realpath $PWD/packages/mingw64` -C packages/sdl cross
+fi
+
+if [ -d packages/sdl-image ]; then
+ echo packages/sdl-image directory exists, skipping
+else
+ echo Extracting SDL2_Image
+ tar -C packages -xzf cache/SDL2_image-devel-2.6.3-mingw.tar.gz
+ mv packages/SDL2_image-2.6.3 packages/sdl-image
+ make CROSS_PATH=`realpath $PWD/packages/mingw64` -C packages/sdl-image cross
+fi
+
+echo "DONE!"