#!/bin/bash
# Compiling SWI-Prolog using MinGW
# --------------------------------
#
# This file provides an overview for building SWI-Prolog using MinGW, in
# particular using the cross-compilers that are distributed with most
# todays Linux distributions. This work is mostly done by Roberto
# Bagnara (initial port of the Prolog kernel), Abramo Bagnara and Keri
# Harris.
#
# The current releases are configured and build using CMake. As a
# result, this README only applies for building the PREREQUISITES. See
# CMAKE.md and/or scripts/make-distribution for configuring and building
# SWI-Prolog.
#
# USAGE
#
# The remainder of the file is an executable specification of the
# installation process. The setup is designed to create ~/mingw32 and/or
# ~/mingw64 for building and installing the prerequisites. We describe
# the setup for Win64. Simply replace 64 with 32 to build for 32-bit
# Windows. First, install the requires tools from the Linux packages:
#
# % sudo apt-get install wine wine-binfmt mingw-w64
# % sudo apt-get install cmake ninja-build nsis
#
# Next, create and prepare the prerequisite location (the script changes
# your prompt to `W64`
#
# % cd ~
# % mkdir -p mingw64/src
# % cd mingw64/src
# % source <path/to/swipl-devel/README.mingw win64
# W64 download_prerequisites
#
# Unfortunately some of the download locations tend to be unreliable or
# require some registration or acceptance of license. So, check for
# empty .tar.gz files and try to get the archive by hand from the
# internet. Than re-run ``download_<package>`` to extract the archive.
#
# Once all is there, get the MinGW runtime libs in `bin`. The details
# may depend on exact versions of MinGW, so please check.
#
# % mkdir -p ~/mingw64/bin
# % cd ~/mingw64/bin
# % cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll .
# % cp /usr/lib/gcc/x86_64-w64-mingw32/9.2-win32/libgcc_s_seh-1.dll .
#
# Now, build the prerequisites:
#
# W64 build_prerequisites
#
# If this worked successfully, build SWI-Prolog. Below is the default
# command, see CMAKE.md for various options:
#
# % cd /path/to/swipl-devel
# % mkdir build.win64
# % cd build.win64
# % cmake -DCMAKE_BUILD_TYPE=Release \
# -DCMAKE_TOOLCHAIN_FILE=../cmake/cross/linux_win64.cmake \
# -DJAVA_COMPATIBILITY=ON \
# -G Ninja ..
# % ninja
#
# If this succeeds you should be able to run `./src/swipl-win.exe` or
# `./src/swipl.exe`
#
# To build an installer for installation on other systems, run
#
# % cpack
#
#
# PREREQUISITES
#
# The open source libraries on which SWI-Prolog depends are downloaded
# and built using the functions download_prerequisites() and
# build_prerequisites(). In addition, the following need to be
# installed:
#
# - The Oracle Java SDK for building JPL
# - jdk-<version>-windows-i586.exe into
# /C/Program Files (x86)/... (default on 64-bit Windows)
# - jdk-<version>-windows-x64.exe into
# /C/Program Files/... (default on 64-bit Windows)
TARGETHOST="$1"
MAKE="make -j 4"
case "$TARGETHOST" in
win64) BITS=64
;;
win32) BITS=32
;;
*) echo "Please run as . $BASH_SOURCE 'win32|win64'"
return
esac
PS1=W$BITS' (\W\[\e[36m\]$(__git_ps1 "; %s")\[\e[0m\]) \!_> '
export BUILDARCH=$TARGETHOST
# Versions of prerequisite packages. Used to download the right release
# file.
GMP_VERSION=6.1.2
PTHREADS_VERSION=2-9-1-release
LIBDWARF_VERSION=20120410
SSL_VERSION=1.1.1d
JPEG_VERSION=9b
ZLIB_VERSION=1.2.11
ARCHIVE_VERSION=3.4.0
UUID_VERSION=1.6.2
BDB_VERSION=6.1.26
PCRE_VERSION=8.43
FFI_VERSION=3.3
YAML_VERSION=0.2.2
PLDIR=pl-devel
# installation prefix. This path should not have spaces in one of the
# directory names.
install="${install-$HOME/mingw$BITS}"
src="$(pwd)"
PATH=$install/swipl/bin:$PATH
# Check whether we are cross-compiling or running under MSYS in Windows.
# Note that the MSYS version has not yet been tested.
case "$(uname)" in
MINGW*)
CROSSCOMPILING=no
export PATH=$install/bin:$PATH
DRIVEC="/C"
MINGWGCC=gcc
;;
*)
export CROSSCOMPILING=yes
export WINEDEBUG=-all
DRIVEC="$HOME/.wine/drive_c"
export WINEPATH="$(winepath -w $install/bin)"
;;
esac
if [ "$CROSSCOMPILING" = yes ]; then
if [ -z "$CROSS" ]; then
case $TARGETHOST in
win64)
CROSS=x86_64-w64-mingw32
;;
win32)
if [ -r /usr/bin/i686-w64-mingw32-gcc ]; then
CROSS=i686-w64-mingw32
else
CROSS=i586-mingw32msvc
fi
;;
esac
fi
MINGWGCC=$CROSS-gcc
export WINDRES=$CROSS-windres
fi
# See whether pthread is built-in
if [ -r "$($MINGWGCC -print-file-name=libwinpthread-1.dll)" ]; then
PTHREADS_VERSION=
fi
# Java configuration
# Note that Win64 javac and javadoc crash under Wine (1.5.6). But, we
# can use the native Linux versions
if [ -z "$JAVAROOT" ]; then
case $TARGETHOST in
win64)
JAVAROOT="$DRIVEC/Program Files/Java"
if [ "$CROSSCOMPILING" = yes ]; then
export JAVAC=javac
export JAVADOC=javadoc
fi
;;
win32)
JAVAROOT="$DRIVEC/Program Files (x86)/Java"
;;
esac
fi
JAVAPREFIX="$(echo "$JAVAROOT"/jdk*)/bin"
export JAVAPREFIX
# Set some variables to find the Windows libraries and include files
# export COFLAGS=-g
export CIFLAGS="-I$install/include"
export CPPFLAGS=-I$install/include
export LDFLAGS="-L$install/lib"
export PKGLDFLAGS=-I$install/lib
################################################################
# end of gathering info about the environment; the remainder are
# functions that perform steps of the build process
################################################################
################
# Handy for running autoconf from a directory
config()
{ if [ -r ./configure ]; then
./configure --host=$CROSS --prefix=$install
elif [ -r ../src/configure ]; then
./configure --host=$CROSS --prefix=$install
fi
}
################
# Create target directories
make_mingw_dirs()
{ mkdir -p $install/include
mkdir -p $install/lib
mkdir -p $install/bin
}
###########################
# Download and install the GMP library.
download_gmp()
{ GMP_FILE=gmp-$GMP_VERSION.tar.bz2
[ -f $GMP_FILE ] || \
wget ftp://ftp.gmplib.org/pub/gmp-$GMP_VERSION/$GMP_FILE
tar jxf $GMP_FILE
}
build_gmp()
{ ( cd gmp-$GMP_VERSION
./configure --host=$CROSS --prefix=$install \
--enable-shared --disable-static
make
make install
)
}
###########################
# Download and install the Pthreads-win32 library. Only if PTHREADS_VERSION
# is set. Else we assume a recent MinGW64, which ships with
# libwinpthread
download_pthread_win32()
{ if [ ! -z "$PTHREADS_VERSION" ]; then
PTHREADS_FILE=pthreads-w32-$PTHREADS_VERSION.tar.gz
cd $src
[ -f $PTHREADS_FILE ] || \
wget ftp://sourceware.org/pub/pthreads-win32/$PTHREADS_FILE
tar xzf $PTHREADS_FILE
fi
}
build_pthread_win32()
{ if [ -d pthreads-w32-$PTHREADS_VERSION ]; then
( cd pthreads-w32-$PTHREADS_VERSION
make -f GNUmakefile CROSS=$CROSS- \
LFLAGS="-lwsock32 -Wl,--out-implib=libpthreadGC2.dll.a" GC
cp pthread.h semaphore.h sched.h $install/include/
cp pthreadGC2.dll $install/bin/
cp libpthreadGC2.dll.a $install/lib/
)
fi
}
###########################
# Download and install the DWARF debugging library.
download_libdwarf()
{ LIBDWARF_FILE=libdwarf-$LIBDWARF_VERSION.tar.gz
[ -f $LIBDWARF_FILE ] || \
wget http://www.prevanders.net/$LIBDWARF_FILE
tar xzf $LIBDWARF_FILE
}
build_libdwarf()
{ ( cd dwarf-$LIBDWARF_VERSION/libdwarf
./configure --host=$CROSS --enable-shared
sed -i -e "s|libdwarf.so|libdwarf.dll|" \
-e "s|\$(CFLAGS) -shared|\$(LDFLAGS) -shared|" \
-e "/_elf_/d" -e "/[ \t]pro_/d" -e "/dwarf_addr_finder/d" Makefile
make PRELIBS="-Wl,--out-implib=libdwarf.dll.a"
mkdir -p $install/bin
cp libdwarf.dll $install/bin/
mkdir -p $install/lib
cp libdwarf.a libdwarf.dll.a $install/lib/
mkdir -p $install/include
cp dwarf.h libdwarf.h $install/include
)
}
###########################
# Download and install ssl
download_ssl()
{ SSL_FILE=openssl-$SSL_VERSION.tar.gz
[ -f $SSL_FILE ] || wget http://www.openssl.org/source/$SSL_FILE
tar xzf $SSL_FILE
}
build_ssl()
{ ( cd openssl-$SSL_VERSION
export CC=$MINGWGCC
case $CROSS in
i?86*) MINGW=mingw
;;
x86_64*) MINGW=mingw64
;;
*) echo "SSL: Unknown CROSS: $CROSS"
exit 1
;;
esac;
./Configure $MINGW --prefix=$install shared threads
make depend
make
make install_sw
)
}
###########################
# Download and install BerkeleyDB
# http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/overview/index.html
download_libdb()
{ BDB_FILE=db-$BDB_VERSION.tar.gz
[ -f $BDB_FILE ] || \
curl http://download.oracle.com/berkeley-db/$BDB_FILE > $BDB_FILE
tar zxvf $BDB_FILE
}
build_libdb()
{ ( cd db-$BDB_VERSION/build_unix
sed -i -e "s:WinIoCtl.h:winioctl.h:" ../src/dbinc/win_db.h
../dist/configure --enable-mingw --host=$CROSS --prefix=$install \
--enable-shared --disable-static
make library_build
make install_lib install_include
( cd $install/lib
[ -f libdb.dll.a ] || ln -s libdb-*.dll.a libdb.dll.a
[ -f libdb.la ] || ln -s libdb-*.la libdb.la
)
)
}
###########################
# Download and install jpeg
download_jpeg()
{ JPEG_FILE=jpegsrc.v$JPEG_VERSION.tar.gz
[ -f $JPEG_FILE ] || wget http://www.ijg.org/files/$JPEG_FILE
tar xzf $JPEG_FILE
}
build_jpeg()
{ ( cd jpeg-$JPEG_VERSION
./configure --host=$CROSS --prefix=$install --enable-shared
make
make install
)
}
###########################
# Download and install libXpm
download_libxpm()
{ if [ -d libXpm ]; then
(cd libXpm && git pull)
else
git clone https://github.com/SWI-Prolog/libXpm.git
fi
}
build_libxpm()
{ ( cd libXpm/lib
autoconf
./configure --host=$CROSS --prefix=$install
make -f Makefile.mingw
make -f Makefile.mingw install
)
}
###########################
# Download and install zlib
download_zlib()
{ ZLIB_FILE=zlib-$ZLIB_VERSION.tar.gz
[ -f $ZLIB_FILE ] || wget http://zlib.net/$ZLIB_FILE
tar xzf $ZLIB_FILE
}
build_zlib()
{ ( cd zlib-$ZLIB_VERSION
make -f win32/Makefile.gcc PREFIX=$CROSS- BINARY_PATH=$install/bin INCLUDE_PATH=$install/include LIBRARY_PATH=$install/lib SHARED_MODE=1 IMPLIB=libz.dll.a install
)
}
#################################
# Download and install libarchive
download_libarchive()
{ ARCHIVE_FILE=libarchive-$ARCHIVE_VERSION.tar.gz
[ -f $ARCHIVE_FILE ] || \
wget http://www.libarchive.org/downloads/$ARCHIVE_FILE
tar xzf $ARCHIVE_FILE
}
# lt_cv_deplibs_check_method=pass_all works around a bug in libtool
# causing: "linker path does not have real file for library" error on MinGW
# See http://lists.cairographics.org/archives/cairo/2009-July/017686.html
build_libarchive()
{ ( cd libarchive-$ARCHIVE_VERSION
export CFLAGS="-I$install/include"
export LDFLAGS="-L$install/lib"
export lt_cv_deplibs_check_method='pass_all'
export ac_cv_func__localtime64_s='no'
export ac_cv_func__ctime64_s='no'
./configure --host=$CROSS --prefix=$install --with-pic --with-zlib \
--without-iconv --without-openssl --without-nettle --without-xml2 \
--without-expat --without-libregex --without-bz2lib \
--without-lzmadec --without-lzma --without-lzo2
make
make install
)
}
#################################
# Download and install libpcre
download_libpcre()
{ PCRE_FILE=pcre-$PCRE_VERSION.tar.gz
[ -f $PCRE_FILE ] || \
wget https://ftp.pcre.org/pub/pcre/$PCRE_FILE
tar xzf $PCRE_FILE
}
build_libpcre()
{ ( cd pcre-$PCRE_VERSION
./configure --host=$CROSS --prefix=$install \
--disable-static --disable-cpp --enable-utf8 --enable-unicode-properties
make pcre.dll
make install
)
}
#################################
# Download and install libuuid
download_libuuid()
{ UUID_FILE=uuid-$UUID_VERSION.tar.gz
[ -f $UUID_FILE ] || \
curl ftp://ftp.ossp.org/pkg/lib/uuid/$UUID_FILE > $UUID_FILE
tar zxvf $UUID_FILE
}
build_libuuid()
{ ( cd uuid-$UUID_VERSION
./configure --host=$CROSS --prefix=$install
make
make install
)
}
################################
# Download and install libffi
download_libffi()
{ FFI_FILE=libffi-$FFI_VERSION.tar.gz
[ -f $FFI_FILE ] || \
curl ftp://sourceware.org/pub/libffi/$FFI_FILE > $FFI_FILE
tar zxvf $FFI_FILE
}
build_libffi()
{ ( cd libffi-$FFI_VERSION
./configure --host=$CROSS --prefix=$install
make
make install
# Bit strange location for the headers
cp $install/lib/libffi-$FFI_VERSION/include/*.h $install/include
)
}
################################
# Download and install libyaml
download_libyaml()
{ #tested 01f3a8786127748b5bbd4614880c4484570bbd44
git clone https://github.com/yaml/libyaml
}
build_libyaml()
{ ( cd libyaml
./bootstrap
./configure --host=$CROSS --prefix=$install
make
make install
)
}
###########################
# Do the whole lot for all prerequisites
clean_prerequisites()
{ ( cd gmp-$GMP_VERSION && make distclean )
( cd openssl-$SSL_VERSION && make distclean )
( cd jpeg-$JPEG_VERSION && make distclean )
( cd libXpm/lib && make distclean )
( cd zlib-$ZLIB_VERSION && make distclean )
( cd libarchive-$ARCHIVE_VERSION && make distclean )
( cd uuid-$UUID_VERSION && make distclean )
( cd ffi-$FFI_VERSION && make distclean )
if [ -d pthreads-w32-$PTHREADS_VERSION ]; then
( cd pthreads-w32-$PTHREADS_VERSION && make distclean )
fi
}
download_prerequisites()
{ download_gmp
download_pthread_win32
download_libdwarf
download_ssl
download_jpeg
download_libxpm
download_zlib
download_libarchive
download_libuuid
download_libdb
download_libpcre
download_libffi
download_libyaml
}
build_prerequisites()
{ build_gmp
build_pthread_win32
build_libdwarf
build_ssl
build_jpeg
build_libxpm
build_zlib
build_libarchive
build_libuuid
build_libdb
build_libpcre
build_libffi
build_libyaml
}