From f27a702662b7930f78091395adc10e0a022a1c2b Mon Sep 17 00:00:00 2001
From: z411 <z411@omaera.org>
Date: Sun, 20 Feb 2022 16:05:03 -0300
Subject: [PATCH] Initial DLL building

---
 misc/buildsrc/dlls.sh                         | 365 ++++++++++++++++++
 .../buildsrc/toolchain-i686-w64-mingw32.cmake |  25 ++
 .../toolchain-x86_64-w64-mingw32.cmake        |  25 ++
 misc/buildsrc/zlib1.rc                        |  40 ++
 misc/tools/all/release.subr                   |  11 +-
 5 files changed, 463 insertions(+), 3 deletions(-)
 create mode 100755 misc/buildsrc/dlls.sh
 create mode 100644 misc/buildsrc/toolchain-i686-w64-mingw32.cmake
 create mode 100644 misc/buildsrc/toolchain-x86_64-w64-mingw32.cmake
 create mode 100644 misc/buildsrc/zlib1.rc

diff --git a/misc/buildsrc/dlls.sh b/misc/buildsrc/dlls.sh
new file mode 100755
index 00000000..5c642508
--- /dev/null
+++ b/misc/buildsrc/dlls.sh
@@ -0,0 +1,365 @@
+#!/bin/bash
+#
+# Xonotic DLL automatic cross-compile script
+# by z411
+
+d0=$(pwd)
+echo "Working directory is $d0"
+
+require () {
+	if ! dpkg -s "$1" >/dev/null 2>&1 ; then
+		echo "$1 package is required. Please install it."
+		exit -1
+	fi
+}
+
+prepare () {
+    if [ -z $out_dir ]; then
+        echo "Out directory not set."
+        exit 1
+    fi
+
+	case $target_arch in
+		win32)	  ARCH="i686" ;;
+		win64)	  ARCH="x86_64" ;;
+		*)        echo "Invalid arch (win32 or win64)." && exit -1 ;;
+	esac
+
+	# Set directories
+	src_dir="$d0/dlls/src"
+	work_dir="$d0/dlls/work/$target_arch"
+	pkg_dir="$d0/dlls/pkg/$target_arch"
+
+	# Set arch vars
+	CHOST="$ARCH-w64-mingw32"
+	toolchain_file="$d0/toolchain-$CHOST.cmake"
+
+	# Fix for Debian package missing the Windows resource file
+	zlib1rc_file="$d0/zlib1.rc"
+
+	export LDFLAGS="-L$pkg_dir/lib"
+	export CPPFLAGS="-I$pkg_dir/include"
+
+	# Check dependencies
+	require libtool
+	require mingw-w64
+	require automake
+	require cmake
+	require nasm
+
+	set -ex
+
+	mkdir -p "$src_dir"
+	mkdir -p "$work_dir"
+	mkdir -p "$pkg_dir"
+}
+
+get_this_src () {
+	dir=$(find . -maxdepth 1 -type d -print | grep -m1 "^\./$1") || return 1
+	this_src="$src_dir/$dir"
+	this_ver="${dir##*-}"
+}
+
+fetch_source () {
+	cd "$src_dir"
+
+	if get_this_src "$1"; then
+		echo "Source for $1 already exists."
+		return 1
+	else
+		echo "Getting source for $1..."
+		apt source "$1"
+		get_this_src "$1"
+		return 0
+	fi
+}
+
+verlte () {
+	printf '%s\n%s' "$1" "$2" | sort -C -V
+}
+
+verlt () {
+	! verlte "$2" "$1"
+}
+
+mkcd () {
+	mkdir -p "$1"
+	cd "$1"
+}
+
+build_zlib () {
+	if fetch_source zlib ; then
+		echo "Fixing zlib prefix..."
+		sed -i '/zlib PROPERTIES SUFFIX/i set_target_properties(zlib PROPERTIES PREFIX "")' "$this_src/CMakeLists.txt"
+
+		# Debian source package is missing the win32 resource file for some reason,
+		# so we add it ourselves.
+		echo "Fixing zlib1.rc..."
+		mkdir -p "$this_src/win32"
+		cp "$zlib1rc_file" "$this_src/win32"
+	fi
+
+	mkcd "$work_dir/zlib"
+	cmake -DCMAKE_TOOLCHAIN_FILE="$toolchain_file"\
+	      -DBUILD_SHARED_LIBS=ON \
+	      -DCMAKE_INSTALL_PREFIX="$pkg_dir" \
+	      -G"Unix Makefiles" "$this_src"
+	make
+	make install
+}	
+
+build_gmp () {
+	fetch_source gmp || true
+
+	mkcd "$work_dir/gmp"
+	"$this_src/configure" --prefix="$pkg_dir" \
+			      --host="$CHOST" \
+			      --with-pic \
+			      --enable-fat \
+			      --disable-static \
+			      --enable-shared
+	make
+	make install
+}
+
+build_libd0 () {
+	if [[ -d "$src_dir/d0_blind_id" ]] ; then
+		echo "Sources already exist."
+	else
+		echo "Getting git sources for libd0..."
+		cd "$src_dir"
+		git clone https://gitlab.com/xonotic/d0_blind_id.git
+		cd d0_blind_id
+		./autogen.sh
+		sed -i '/libd0_blind_id_la_LDFLAGS/ s/$/ -no-undefined/' Makefile.am
+		sed -i '/libd0_rijndael_la_LDFLAGS/ s/$/ -no-undefined/' Makefile.am
+	fi
+
+	mkcd "$work_dir/libd0"
+	"$src_dir/d0_blind_id/configure" --with-pic \
+		                         --prefix="$pkg_dir" \
+					 --host="$CHOST"
+	make
+	make install
+}
+
+build_libogg() {
+	if fetch_source libogg ; then
+		echo "Fixing win32 def files..."
+		sed -i 's/^LIBRARY ogg$/LIBRARY libogg/' "$this_src/win32/ogg.def"
+	fi
+
+	mkcd "$work_dir/libogg"
+	cmake -DCMAKE_TOOLCHAIN_FILE="$toolchain_file" \
+	      -DBUILD_SHARED_LIBS=ON \
+	      -DCMAKE_INSTALL_PREFIX="$pkg_dir" \
+	      -G"Unix Makefiles" "$this_src"
+	make
+	make install
+}
+
+build_libvorbis () {
+	if fetch_source libvorbis ; then
+		echo "Fixing win32 def files..."
+		sed -i 's/^LIBRARY$/LIBRARY libvorbis/' "$this_src/win32/vorbis.def"
+		sed -i 's/^LIBRARY$/LIBRARY libvorbisenc/' "$this_src/win32/vorbisenc.def"
+		sed -i 's/^LIBRARY$/LIBRARY libvorbisfile/' "$this_src/win32/vorbisfile.def"
+	fi
+
+	mkcd "$work_dir/libvorbis"
+	cmake -DCMAKE_TOOLCHAIN_FILE="$toolchain_file" \
+	      -DBUILD_SHARED_LIBS=ON \
+	      -DOGG_INCLUDE_DIR="$pkg_dir/include" \
+	      -DOGG_LIBRARY="$pkg_dir/lib/libogg.dll.a" \
+	      -DCMAKE_INSTALL_PREFIX="$pkg_dir" \
+	      -G"Unix Makefiles" "$this_src"
+	make
+	make install
+}
+
+build_libtheora () {
+	if fetch_source libtheora ; then
+		echo "Fixing mingw32 defs..."
+		sed -i '1iLIBRARY libtheoradec' "$this_src/win32/xmingw32/libtheoradec-all.def"
+		sed -i '1iLIBRARY libtheoraenc' "$this_src/win32/xmingw32/libtheoraenc-all.def"
+		sed -i '/TH_VP31_QUANT_INFO/d' "$this_src/win32/xmingw32/libtheoraenc-all.def"
+		sed -i '/TH_VP31_HUFF_CODES/d' "$this_src/win32/xmingw32/libtheoraenc-all.def"
+	fi
+
+	mkcd "$work_dir/libtheora"
+	"$this_src/autogen.sh"
+	"$this_src/configure" --host="$CHOST" \
+		              --prefix="$pkg_dir" \
+			      --with-ogg="$pkg_dir" \
+			      --with-vorbis="$pkg_dir" \
+			      --enable-shared \
+			      --disable-examples \
+			      --disable-sdltest \
+			      --disable-vorbistest \
+			      --disable-oggtest
+	make
+	make install
+}
+
+build_freetype () {
+	fetch_source freetype || true
+
+	mkcd "$work_dir/freetype"
+	cmake -DCMAKE_TOOLCHAIN_FILE="$toolchain_file" \
+	      -DBUILD_SHARED_LIBS=ON \
+	      -DCMAKE_BUILD_TYPE=Release \
+	      -DCMAKE_INSTALL_PREFIX="$pkg_dir" \
+	      -G"Unix Makefiles" "$this_src"
+	make
+	make install
+}
+
+build_libpng16 () {
+	fetch_source "libpng1.6" || true
+
+	mkcd "$work_dir/libpng1.6"
+	cmake -DCMAKE_TOOLCHAIN_FILE="$toolchain_file" \
+	      -DPNG_STATIC=OFF \
+	      -DPNG_TESTS=OFF \
+	      -DZLIB_INCLUDE_DIR="$pkg_dir/include" \
+	      -DZLIB_LIBRARY="$pkg_dir/lib/libzlib.dll.a" \
+	      -DCMAKE_INSTALL_PREFIX="$pkg_dir" \
+	      -G"Unix Makefiles" "$this_src"
+	make
+	make install
+}
+
+build_libjpeg () {
+	fetch_source libjpeg-turbo || true
+
+	mkcd "$work_dir/libjpeg"
+	cmake -DCMAKE_TOOLCHAIN_FILE="$toolchain_file" \
+	      -DCMAKE_SYSTEM_PROCESSOR="$ARCH" \
+	      -DCMAKE_INSTALL_PREFIX="$pkg_dir" \
+	      -DENABLE_SHARED=ON \
+	      -DENABLE_STATIC=OFF \
+	      -DWITH_TURBOJPEG=OFF \
+	      -G"Unix Makefiles" "$this_src"
+	make
+	make install
+}
+
+build_curl () {
+	fetch_source curl || true
+
+	# curl versions older than 7.81.0 used CMAKE instead of CURL for
+	# private USE identifiers
+	verlt $this_ver 7.81.0 && PARAM="CMAKE" || PARAM="CURL"
+
+	mkcd "$work_dir/curl"
+	cmake -DCMAKE_TOOLCHAIN_FILE="$toolchain_file" \
+	      -DCMAKE_INSTALL_PREFIX="$pkg_dir" \
+	      -DZLIB_INCLUDE_DIR="$pkg_dir/include" \
+	      -DZLIB_LIBRARY="$pkg_dir/lib/libzlib.dll.a" \
+	      -D${PARAM}_USE_SCHANNEL=ON \
+	      -DBUILD_SHARED_LIBS=ON \
+	      -DBUILD_CURL_EXE=OFF \
+	      -DHTTP_ONLY=ON \
+	      -G"Unix Makefiles" "$this_src"
+	make
+	make install
+}
+
+build_all () {
+	build_zlib
+	build_gmp
+	build_libd0
+	build_libogg
+	build_libvorbis
+	build_libtheora
+	build_freetype
+	build_libpng16
+	build_libjpeg
+	build_curl
+}
+
+install () {
+	mkdir -p "$out_dir"
+
+	cp -v "$pkg_dir/bin/libgmp-10.dll" "$out_dir"
+	cp -v "$pkg_dir/bin/libd0_blind_id-0.dll" "$out_dir"
+	cp -v "$pkg_dir/bin/libd0_rijndael-0.dll" "$out_dir"
+	cp -v "$pkg_dir/bin/libogg.dll" "$out_dir"
+	cp -v "$pkg_dir/bin/libvorbis.dll" "$out_dir"
+	cp -v "$pkg_dir/bin/libvorbisenc.dll" "$out_dir"
+	cp -v "$pkg_dir/bin/libvorbisfile.dll" "$out_dir"
+	cp -v "$pkg_dir/bin/libtheora-0.dll" "$out_dir"
+	cp -v "$pkg_dir/bin/libfreetype.dll" "$out_dir/libfreetype-6.dll"
+	cp -v "$pkg_dir/bin/zlib1.dll" "$out_dir"
+	cp -v "$pkg_dir/bin/libpng16.dll" "$out_dir"
+	cp -v "$pkg_dir/bin/libjpeg-62.dll" "$out_dir/libjpeg.dll"
+	cp -v "$pkg_dir/bin/libcurl.dll" "$out_dir/libcurl-4.dll"
+
+	cd "$out_dir"
+	${CHOST}-strip -s *.dll
+}
+
+clean () {
+	rm -rf "$d0/dlls/src"
+	rm -rf "$d0/dlls/work"
+	rm -rf "$d0/dlls/pkg"
+}
+
+list () {
+	echo "Compilable libraries:"
+	echo
+	echo gmp
+	echo libd0
+	echo libogg
+	echo libvorbis
+	echo libtheora
+	echo freetype
+	echo zlib
+	echo libpng16
+	echo libjpeg
+	echo curl
+}
+
+usage () {
+	echo "Experimental Windows DLL cross-compiling for Xonotic"
+	echo "by z411"
+	echo
+	echo "usage: $0 <step> [arch] [out directory]"
+	echo
+	echo "available steps (require arch):"
+	echo "  <library name>: build specified library"
+	echo "  build_all: build all libraries"
+	echo "  install: copy built DLLs into output directory"
+	echo "  all: do all the previous steps in order"
+	echo
+	echo "steps without arch:"
+	echo "  list: list all compilable libraries"
+	echo "  clean: delete all work"
+	echo
+	echo "arch can be:"
+	echo "  win32"
+	echo "  win64"
+}
+
+step=$1
+target_arch=$2
+out_dir=$3
+
+case $step in
+	gmp)           prepare && build_gmp ;;
+	libd0)         prepare && build_libd0 ;;
+	libogg)        prepare && build_libogg ;;
+	libvorbis)     prepare && build_libvorbis ;;
+	libtheora)     prepare && build_libtheora ;;
+	freetype)      prepare && build_freetype ;;
+	zlib)          prepare && build_zlib ;;
+	libpng16)      prepare && build_libpng16 ;;
+	libjpeg)       prepare && build_libjpeg ;;
+	curl)          prepare && build_curl ;;
+	build_all)     prepare && build_all ;;
+	install)       prepare && install ;;
+	all)           prepare && build_all && install ;;
+	clean)         clean ;;
+	list)          list ;;
+	*)             usage ;;
+esac
diff --git a/misc/buildsrc/toolchain-i686-w64-mingw32.cmake b/misc/buildsrc/toolchain-i686-w64-mingw32.cmake
new file mode 100644
index 00000000..3507d720
--- /dev/null
+++ b/misc/buildsrc/toolchain-i686-w64-mingw32.cmake
@@ -0,0 +1,25 @@
+# Sample toolchain file for building for Windows from an Ubuntu Linux system.
+#
+# Typical usage:
+#    *) install cross compiler: `sudo apt-get install mingw-w64 g++-mingw-w64`
+#    *) cd build
+#    *) cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-Ubuntu-mingw32.cmake ..
+
+set(CMAKE_SYSTEM_NAME Windows)
+set(TOOLCHAIN_PREFIX i686-w64-mingw32)
+
+# cross compilers to use for C and C++
+set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
+set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
+set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
+
+# target environment on the build host system
+#   set 1st to dir with the cross compiler's C/C++ headers/libs
+set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
+
+# modify default behavior of FIND_XXX() commands to
+# search for headers/libs in the target environment and
+# search for programs in the build 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)
diff --git a/misc/buildsrc/toolchain-x86_64-w64-mingw32.cmake b/misc/buildsrc/toolchain-x86_64-w64-mingw32.cmake
new file mode 100644
index 00000000..3dbc9b1b
--- /dev/null
+++ b/misc/buildsrc/toolchain-x86_64-w64-mingw32.cmake
@@ -0,0 +1,25 @@
+# Sample toolchain file for building for Windows from an Ubuntu Linux system.
+#
+# Typical usage:
+#    *) install cross compiler: `sudo apt-get install mingw-w64 g++-mingw-w64`
+#    *) cd build
+#    *) cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-Ubuntu-mingw64.cmake ..
+
+set(CMAKE_SYSTEM_NAME Windows)
+set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
+
+# cross compilers to use for C and C++
+set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
+set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
+set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
+
+# target environment on the build host system
+#   set 1st to dir with the cross compiler's C/C++ headers/libs
+set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
+
+# modify default behavior of FIND_XXX() commands to
+# search for headers/libs in the target environment and
+# search for programs in the build 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)
diff --git a/misc/buildsrc/zlib1.rc b/misc/buildsrc/zlib1.rc
new file mode 100644
index 00000000..234e641c
--- /dev/null
+++ b/misc/buildsrc/zlib1.rc
@@ -0,0 +1,40 @@
+#include <winver.h>
+#include "../zlib.h"
+
+#ifdef GCC_WINDRES
+VS_VERSION_INFO		VERSIONINFO
+#else
+VS_VERSION_INFO		VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
+#endif
+  FILEVERSION		ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0
+  PRODUCTVERSION	ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0
+  FILEFLAGSMASK		VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+  FILEFLAGS		1
+#else
+  FILEFLAGS		0
+#endif
+  FILEOS		VOS__WINDOWS32
+  FILETYPE		VFT_DLL
+  FILESUBTYPE		0	// not used
+BEGIN
+  BLOCK "StringFileInfo"
+  BEGIN
+    BLOCK "040904E4"
+    //language ID = U.S. English, char set = Windows, Multilingual
+    BEGIN
+      VALUE "FileDescription",	"zlib data compression library\0"
+      VALUE "FileVersion",	ZLIB_VERSION "\0"
+      VALUE "InternalName",	"zlib1.dll\0"
+      VALUE "LegalCopyright",	"(C) 1995-2017 Jean-loup Gailly & Mark Adler\0"
+      VALUE "OriginalFilename",	"zlib1.dll\0"
+      VALUE "ProductName",	"zlib\0"
+      VALUE "ProductVersion",	ZLIB_VERSION "\0"
+      VALUE "Comments",		"For more information visit http://www.zlib.net/\0"
+    END
+  END
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x0409, 1252
+  END
+END
diff --git a/misc/tools/all/release.subr b/misc/tools/all/release.subr
index f3202c2c..adb2789f 100644
--- a/misc/tools/all/release.subr
+++ b/misc/tools/all/release.subr
@@ -173,9 +173,12 @@ case "$cmd" in
 			verbose cd Xonotic
 			verbose mkdir data source source/darkplaces source/gmqcc source/d0_blind_id mapping
 			verbose rm -rf misc/builddeps
-			verbose mv misc/buildfiles/win32 bin32 || true
-			verbose mv bin32/SDL.dll . || true
-			verbose mv misc/buildfiles/win64 bin64 || true
+			#verbose mv bin32/SDL.dll . || true # Leftover?
+
+			# We're going to be building these later
+			#verbose mv misc/buildfiles/win32 bin32 || true
+			#verbose mv misc/buildfiles/win64 bin64 || true
+
 			verbose mv misc/buildfiles/osx/* . || true
 			verbose rm -rf misc/buildfiles
 			verbose rm -rf misc/pki
@@ -271,6 +274,7 @@ case "$cmd" in
 		#verbose "$SELF" release-getbinary Xonotic/xonotic-x86.exe || good=false
 		#verbose "$SELF" release-getbinary Xonotic/xonotic-x86-dedicated.exe || good=false
 		#$good
+		verbose "$d0/misc/buildsrc/dlls.sh" all win32 Xonotic/bin32
 		verbose "$SELF" release-compile win32 \
 			'STRIP=: D3D=1 DP_MAKE_TARGET=mingw WIN32RELEASE=1 CC="i686-w64-mingw32-gcc -static -g1 -mstackrealign -Wl,--dynamicbase -Wl,--nxcompat -I../../../.deps/include -L../../../.deps/lib -DSUPPORTIPV6" WINDRES="i686-w64-mingw32-windres" SDL_CONFIG="../../../.deps/bin/sdl2-config" DP_LINK_CRYPTO=dlopen DP_LINK_CRYPTO_RIJNDAEL=dlopen DP_LINK_JPEG=dlopen DP_LINK_ODE=dlopen DP_LINK_ZLIB=dlopen' \
 			release 'darkplaces.exe:Xonotic/xonotic-x86-wgl.exe darkplaces-sdl.exe:Xonotic/xonotic-x86.exe darkplaces-dedicated.exe:Xonotic/xonotic-x86-dedicated.exe'
@@ -281,6 +285,7 @@ case "$cmd" in
 		#verbose "$SELF" release-getbinary Xonotic/xonotic.exe || good=false
 		#verbose "$SELF" release-getbinary Xonotic/xonotic-dedicated.exe || good=false
 		#$good
+		verbose "$d0/misc/buildsrc/dlls.sh" all win64 Xonotic/bin64
 		verbose "$SELF" release-compile win64 \
 			'STRIP=: D3D=1 DP_MAKE_TARGET=mingw WIN64RELEASE=1 CC="x86_64-w64-mingw32-gcc -static -g1 -Wl,--dynamicbase -Wl,--nxcompat -I../../../.deps/include -L../../../.deps/lib -DSUPPORTIPV6" WINDRES="x86_64-w64-mingw32-windres" SDL_CONFIG="../../../.deps/bin/sdl2-config" DP_LINK_CRYPTO=dlopen DP_LINK_CRYPTO_RIJNDAEL=dlopen DP_LINK_JPEG=dlopen DP_LINK_ODE=dlopen DP_LINK_ZLIB=dlopen' \
 			release 'darkplaces.exe:Xonotic/xonotic-wgl.exe darkplaces-sdl.exe:Xonotic/xonotic.exe darkplaces-dedicated.exe:Xonotic/xonotic-dedicated.exe'
-- 
2.39.5