diff options
| author | Přemysl Eric Janouch <p@janouch.name> | 2021-10-22 01:59:09 +0200 | 
|---|---|---|
| committer | Přemysl Eric Janouch <p@janouch.name> | 2021-10-22 01:59:09 +0200 | 
| commit | 89580f2113a190494afd7e9454bad5275beda4c6 (patch) | |
| tree | f943a49b7ae97e0fbd4d5d9c315099190f24e150 | |
| parent | c7b9d657977ae907aeacc40b1eca2cbfcbddb35c (diff) | |
| download | tdv-89580f2113a190494afd7e9454bad5275beda4c6.tar.gz tdv-89580f2113a190494afd7e9454bad5275beda4c6.tar.xz tdv-89580f2113a190494afd7e9454bad5275beda4c6.zip | |
sdgui: cross-compile for Windows
No one bothered to ask whether it /should/ be done.
The hamburger needs to be replaced with a file open dialog there.
| -rw-r--r-- | CMakeLists.txt | 105 | ||||
| -rw-r--r-- | README.adoc | 21 | ||||
| -rw-r--r-- | cmake/FindLibIntl.cmake | 8 | ||||
| -rw-r--r-- | cmake/Win64CrossToolchain.cmake | 15 | ||||
| -rw-r--r-- | cmake/Win64Depends.sh | 74 | ||||
| -rw-r--r-- | src/sdgui.c | 1 | ||||
| -rw-r--r-- | src/utils.c | 9 | 
7 files changed, 203 insertions, 30 deletions
| diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d24172..43bc41e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,25 @@ endif ()  # For custom modules  set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +# Cross-compilation for Windows, as a proof-of-concept pulled in from logdiag +if (WIN32) +	if (NOT CMAKE_CROSSCOMPILING) +		message (FATAL_ERROR "Win32 must be cross-compiled to build sensibly") +	endif () + +	set (WIN32_DEPENDS_PATH ${PROJECT_SOURCE_DIR}/win32-depends) +	list (APPEND CMAKE_PREFIX_PATH ${WIN32_DEPENDS_PATH}) +	list (APPEND CMAKE_INCLUDE_PATH ${WIN32_DEPENDS_PATH}/lib) +	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mms-bitfields") + +	if (CMAKE_CROSSCOMPILING) +		list (APPEND CMAKE_FIND_ROOT_PATH ${WIN32_DEPENDS_PATH}) +	endif (CMAKE_CROSSCOMPILING) + +	set (ENV{PKG_CONFIG_LIBDIR} +		"${WIN32_DEPENDS_PATH}/share/pkgconfig:${WIN32_DEPENDS_PATH}/lib/pkgconfig") +endif (WIN32) +  # Dependencies  find_package (ZLIB REQUIRED)  find_package (Ncursesw REQUIRED) @@ -18,7 +37,7 @@ find_package (PkgConfig REQUIRED)  pkg_check_modules (dependencies REQUIRED glib-2.0>=2.38 gio-2.0 pango)  pkg_check_modules (icu icu-uc icu-i18n) -if (NOT icu_FOUND) +if (NOT icu_FOUND AND NOT WIN32)  	find_program (icu_CONFIG_EXECUTABLE icu-config)  	if (NOT icu_CONFIG_EXECUTABLE)  		message (FATAL_ERROR "ICU not found") @@ -73,9 +92,8 @@ if (WITH_X11)  		message (FATAL_ERROR "XCB not found")  	endif () -	list (APPEND dependencies_INCLUDE_DIRS ${xcb_INCLUDE_DIRS}) -	list (APPEND dependencies_LIBRARY_DIRS ${xcb_LIBRARY_DIRS}) -	list (APPEND dependencies_LIBRARIES ${xcb_LIBRARIES}) +	include_directories (${xcb_INCLUDE_DIRS}) +	link_directories (${xcb_LIBRARY_DIRS})  endif ()  pkg_check_modules (gtk gtk+-3.0) @@ -121,6 +139,10 @@ add_custom_target (docs ALL DEPENDS ${project_MAN_PAGES})  # Project libraries  set (project_common_libraries ${ZLIB_LIBRARIES} ${icu_LIBRARIES}  	${dependencies_LIBRARIES}) +if (WIN32) +	find_package (LibIntl REQUIRED) +	list (APPEND project_common_libraries ${LibIntl_LIBRARIES}) +endif (WIN32)  set (project_common_headers  	${PROJECT_BINARY_DIR}/config.h @@ -152,19 +174,24 @@ set (project_headers  # Build the main executable and link it  add_definitions (-DGLIB_DISABLE_DEPRECATION_WARNINGS) -add_executable (${PROJECT_NAME} -	${project_sources} ${project_headers} ${project_common_sources}) -target_link_libraries (${PROJECT_NAME} ${project_common_libraries} -	${Ncursesw_LIBRARIES} termo-static) +if (NOT WIN32) +	add_executable (${PROJECT_NAME} +		${project_sources} ${project_headers} ${project_common_sources}) +	target_link_libraries (${PROJECT_NAME} ${project_common_libraries} +		${Ncursesw_LIBRARIES} termo-static) +	if (WITH_X11) +		target_link_libraries (${PROJECT_NAME} ${xcb_LIBRARIES}) +	endif () +endif (NOT WIN32)  # The same for the alternative GTK+ UI  if (WITH_GUI) -	add_executable (sdgui +	add_executable (sdgui WIN32  		src/sdgui.c  		src/stardict-view.c  		${project_common_sources})  	target_include_directories (sdgui PUBLIC ${gtk_INCLUDE_DIRS}) -	target_link_libraries (sdgui ${gtk_LIBRARIES} ${project_common_libraries}) +	target_link_libraries (sdgui ${project_common_libraries} ${gtk_LIBRARIES})  endif ()  # Tools @@ -193,22 +220,50 @@ endforeach ()  add_custom_target (dicts DEPENDS ${dicts_targets})  # The files to be installed -include (GNUInstallDirs) -install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) -install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR}) -if (WITH_GUI) -	install (TARGETS sdgui DESTINATION ${CMAKE_INSTALL_BINDIR}) -	install (FILES sdgui.desktop -		DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) -	install (FILES sdgui.xml -		DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages) -endif () +if (NOT WIN32) +	include (GNUInstallDirs) +	install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) +	install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR}) -foreach (page ${project_MAN_PAGES}) -	string (REGEX MATCH "\\.([0-9])$" manpage_suffix "${page}") -	install (FILES "${page}" -		DESTINATION "${CMAKE_INSTALL_MANDIR}/man${CMAKE_MATCH_1}") -endforeach () +	if (WITH_GUI) +		install (TARGETS sdgui DESTINATION ${CMAKE_INSTALL_BINDIR}) +		install (FILES sdgui.desktop +			DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) +		install (FILES sdgui.xml +			DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages) +	endif () + +	foreach (page ${project_MAN_PAGES}) +		string (REGEX MATCH "\\.([0-9])$" manpage_suffix "${page}") +		install (FILES "${page}" +			DESTINATION "${CMAKE_INSTALL_MANDIR}/man${CMAKE_MATCH_1}") +	endforeach () +elseif (WITH_GUI) +	# This rather crude filter has been mostly copied over from logdiag +	install (TARGETS sdgui DESTINATION .) +	install (DIRECTORY +		${WIN32_DEPENDS_PATH}/bin/ +		DESTINATION . +		FILES_MATCHING PATTERN "*.dll" +		PATTERN "libgettext*" EXCLUDE) +	install (DIRECTORY +		${WIN32_DEPENDS_PATH}/etc/ +		DESTINATION etc) +	install (DIRECTORY +		${WIN32_DEPENDS_PATH}/lib/gdk-pixbuf-2.0 +		DESTINATION lib +		FILES_MATCHING PATTERN "*" PATTERN "*.a" EXCLUDE) +	install (DIRECTORY +		${WIN32_DEPENDS_PATH}/share/glib-2.0/schemas +		DESTINATION share/glib-2.0) + +	install (DIRECTORY +		${WIN32_DEPENDS_PATH}/share/icons/Adwaita +		DESTINATION share/icons OPTIONAL) +	install (FILES +		${WIN32_DEPENDS_PATH}/share/icons/hicolor/index.theme +		DESTINATION share/icons/hicolor) +endif ()  # Do some unit tests  option (BUILD_TESTING "Build tests" OFF) diff --git a/README.adoc b/README.adoc index 05d1c9c..e81a4b0 100644 --- a/README.adoc +++ b/README.adoc @@ -12,9 +12,9 @@ software.  image::sdtui.png[align="center"] -With GTK+ 3 development packages installed, an alternative frontend will also be -built and installed.  It shares the default dictionary list with 'sdtui', -but styling will follow your theme, and has to be customized from 'gtk.css'. +As a recent addition, there is now an alternative GTK+ 3 based frontend as well. +It shares its dictionary list with 'sdtui', but styling will follow your theme, +and may be customized from 'gtk.css'.  Packages  -------- @@ -36,7 +36,8 @@ Runtime dependencies: ncursesw, zlib, ICU, termo (included), glib-2.0 >= 2.38,   $ git clone --recursive https://git.janouch.name/p/sdtui.git   $ mkdir sdtui/build   $ cd sdtui/build - $ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DWITH_X11=ON + $ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug \ +   -DWITH_X11=ON -DWITH_GUI=ON   $ make  To install the application, you can do either the usual: @@ -53,6 +54,18 @@ an argument.  It is, however, preferable to  link:docs/sdtui.1.adoc#_configuration[configure it] to load your dictionaries  automatically. +Windows +~~~~~~~ +With the help of Mingw-w64 and WINE, the GUI will successfully cross-compile +for Windows.  It isn't particularly usable on that system, if only because +selection watching is a very X11/Wayland-specific feature.  Beware that build +dependencies take up almost a gigabyte of disk space. + + $ sh cmake/Win64Depends.cmake + $ cmake -DCMAKE_TOOLCHAIN_FILE=cmake/Win64CrossToolchain.cmake \ +   -DCMAKE_BUILD_TYPE=Release -B build + $ cmake --build build -- package +  Dictionaries  ------------  This application is intended for use with specific dictionaries: each line diff --git a/cmake/FindLibIntl.cmake b/cmake/FindLibIntl.cmake new file mode 100644 index 0000000..1a15555 --- /dev/null +++ b/cmake/FindLibIntl.cmake @@ -0,0 +1,8 @@ +# Public Domain + +find_library (LibIntl_LIBRARIES intl) + +include (FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS (LibIntl DEFAULT_MSG LibIntl_LIBRARIES) + +mark_as_advanced (LibIntl_LIBRARIES) diff --git a/cmake/Win64CrossToolchain.cmake b/cmake/Win64CrossToolchain.cmake new file mode 100644 index 0000000..68214ec --- /dev/null +++ b/cmake/Win64CrossToolchain.cmake @@ -0,0 +1,15 @@ +set (CMAKE_SYSTEM_NAME "Windows") +set (CMAKE_SYSTEM_PROCESSOR "x86_64") + +set (CMAKE_C_COMPILER "x86_64-w64-mingw32-gcc") +set (CMAKE_CXX_COMPILER "x86_64-w64-mingw32-g++") +set (CMAKE_RC_COMPILER "x86_64-w64-mingw32-windres") + +# Not needed to crosscompile an installation package +#set (CMAKE_CROSSCOMPILING_EMULATOR "wine64") + +set (CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32") + +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/cmake/Win64Depends.sh b/cmake/Win64Depends.sh new file mode 100644 index 0000000..971517c --- /dev/null +++ b/cmake/Win64Depends.sh @@ -0,0 +1,74 @@ +#!/bin/sh -e +# Win64Depends.sh: download dependencies from MSYS2 for cross-compilation +# Dependencies: AWK, sed, sha256sum, cURL, bsdtar, wine64 +repository=https://repo.msys2.org/mingw/mingw64/ + +status() { +	echo "$(tput bold)-- $*$(tput sgr0)" +} + +dbsync() { +	status Fetching repository DB +	[ -f db.tsv ] || curl -# "$repository/mingw64.db" | bsdtar -xOf- | awk ' +		function flush() { print f["%NAME%"] f["%FILENAME%"] f["%DEPENDS%"] } +		NR > 1 && $0 == "%FILENAME%" { flush(); for (i in f) delete f[i] } +		!/^[^%]/ { field = $0; next } { f[field] = f[field] $0 "\t" } +		field == "%SHA256SUM%" { path = "*packages/" f["%FILENAME%"] +			sub(/\t$/, "", path); print $0, path > "db.sums" } END { flush() } +	' > db.tsv +} + +fetch() { +	status Resolving "$@" +	mkdir -p packages +	awk -F'\t' 'function get(name,    i, a) { +		if (visited[name]++ || !(name in filenames)) return +		print filenames[name]; split(deps[name], a); for (i in a) get(a[i]) +	} BEGIN { while ((getline < "db.tsv") > 0) { +		filenames[$1] = $2; deps[$1] = ""; for (i = 3; i <= NF; i++) { +			gsub(/[<=>].*/, "", $i); deps[$1] = deps[$1] $i FS } +	} for (i = 0; i < ARGC; i++) get(ARGV[i]) }' "$@" | while IFS= read -r name +	do +		status Fetching "$name" +		[ -f "packages/$name" ] || curl -#o "packages/$name" "$repository/$name" +	done +} + +verify() { +	status Verifying checksums +	sha256sum --ignore-missing --quiet -c db.sums +} + +extract() { +	status Extracting packages +	for subdir in * +	do [ -d "$subdir" -a "$subdir" != packages ] && rm -rf -- "$subdir" +	done +	for i in packages/* +	do bsdtar -xf "$i" --strip-components 1 mingw64 +	done +} + +configure() { +	status Configuring packages +	glib-compile-schemas share/glib-2.0/schemas +	wine64 bin/gdk-pixbuf-query-loaders.exe \ +		> lib/gdk-pixbuf-2.0/2.10.0/loaders.cache + +	# pkgconf has a command line option for this, but CMake can't pass it +	sed -i "s|^prefix=/mingw64|prefix=$(pwd)|" {share,lib}/pkgconfig/*.pc +} + +mkdir -p win32-depends +cd win32-depends +dbsync +fetch mingw-w64-x86_64-gtk3 mingw-w64-x86_64-icu \ +	mingw-w64-x86_64-libwinpthread-git # because we don't do "provides"? +verify +extract +configure + +status Success + +# XXX: Why is this override needed to run some GLib-based things under wine64? +export XDG_DATA_DIRS=$(pwd)/share diff --git a/src/sdgui.c b/src/sdgui.c index 127f01b..5b898c7 100644 --- a/src/sdgui.c +++ b/src/sdgui.c @@ -20,6 +20,7 @@  #include <glib/gi18n.h>  #include <locale.h> +#include <stdlib.h>  #include "config.h"  #include "stardict.h" diff --git a/src/utils.c b/src/utils.c index 367c0f5..6a32bda 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,7 +1,7 @@  /*   * utils.c: miscellaneous utilities   * - * Copyright (c) 2013 - 2020, Přemysl Eric Janouch <p@janouch.name> + * Copyright (c) 2013 - 2021, Přemysl Eric Janouch <p@janouch.name>   *   * Permission to use, copy, modify, and/or distribute this software for any   * purpose with or without fee is hereby granted. @@ -25,7 +25,9 @@  #include <errno.h>  #include <stdarg.h> +#ifndef WIN32  #include <pwd.h> +#endif  // ! WIN32  #include "config.h"  #include "utils.h" @@ -161,6 +163,10 @@ try_expand_tilde (const gchar *filename)  	if (!until_slash)  		return g_build_filename (g_get_home_dir () ?: "", filename, NULL); +#ifdef WIN32 +	// TODO: also ensure that path separators are handled sensibly around here +	return NULL; +#else  // ! WIN32  	long buf_len = sysconf (_SC_GETPW_R_SIZE_MAX);  	if (buf_len < 0)  		buf_len = 1024; @@ -177,6 +183,7 @@ try_expand_tilde (const gchar *filename)  		result = g_strdup_printf ("%s%s", pwd.pw_dir, filename + until_slash);  	g_free (buf);  	return result; +#endif  // ! WIN32  }  gchar * | 
