Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/cmake
diff options
context:
space:
mode:
Diffstat (limited to 'cmake')
-rw-r--r--cmake/cmake.h.in60
-rw-r--r--cmake/gitcommit.cmake63
-rw-r--r--cmake/gtk.cmake89
-rw-r--r--cmake/licence.cmake39
-rw-r--r--cmake/platforms/unix.cmake234
-rw-r--r--cmake/platforms/windows.cmake202
-rw-r--r--cmake/setup.cmake113
-rw-r--r--cmake/toolchain-mingw.cmake12
-rw-r--r--cmake/toolchain-winegcc.cmake33
-rwxr-xr-xcmake/winegcc29
10 files changed, 874 insertions, 0 deletions
diff --git a/cmake/cmake.h.in b/cmake/cmake.h.in
new file mode 100644
index 00000000..5ad32515
--- /dev/null
+++ b/cmake/cmake.h.in
@@ -0,0 +1,60 @@
+#cmakedefine NO_IPV6
+#cmakedefine NO_GSSAPI
+#cmakedefine STATIC_GSSAPI
+
+#cmakedefine NO_MULTIMON
+
+#cmakedefine01 HAVE_WINRESRC_H
+#cmakedefine01 HAVE_WINRES_H
+#cmakedefine01 HAVE_WIN_H
+#cmakedefine01 HAVE_NO_STDINT_H
+#cmakedefine01 HAVE_AFUNIX_H
+#cmakedefine01 HAVE_GCP_RESULTSW
+#cmakedefine01 HAVE_ADDDLLDIRECTORY
+#cmakedefine01 HAVE_GETNAMEDPIPECLIENTPROCESSID
+#cmakedefine01 HAVE_SETDEFAULTDLLDIRECTORIES
+#cmakedefine01 HAVE_STRTOUMAX
+#cmakedefine01 HAVE_DWMAPI_H
+
+#cmakedefine NOT_X_WINDOWS
+#cmakedefine OMIT_UTMP
+
+#cmakedefine01 HAVE_ASM_HWCAP_H
+#cmakedefine01 HAVE_SYS_AUXV_H
+#cmakedefine01 HAVE_SYS_SYSCTL_H
+#cmakedefine01 HAVE_SYS_TYPES_H
+#cmakedefine01 HAVE_GLOB_H
+#cmakedefine01 HAVE_UTMP_H
+#cmakedefine01 HAVE_FUTIMES
+#cmakedefine01 HAVE_GETADDRINFO
+#cmakedefine01 HAVE_POSIX_OPENPT
+#cmakedefine01 HAVE_PTSNAME
+#cmakedefine01 HAVE_SETRESUID
+#cmakedefine01 HAVE_SETRESGID
+#cmakedefine01 HAVE_STRSIGNAL
+#cmakedefine01 HAVE_UPDWTMPX
+#cmakedefine01 HAVE_FSTATAT
+#cmakedefine01 HAVE_DIRFD
+#cmakedefine01 HAVE_SETPWENT
+#cmakedefine01 HAVE_ENDPWENT
+#cmakedefine01 HAVE_GETAUXVAL
+#cmakedefine01 HAVE_ELF_AUX_INFO
+#cmakedefine01 HAVE_SYSCTLBYNAME
+#cmakedefine01 HAVE_CLOCK_MONOTONIC
+#cmakedefine01 HAVE_CLOCK_GETTIME
+#cmakedefine01 HAVE_SO_PEERCRED
+#cmakedefine01 HAVE_NULLARY_SETPGRP
+#cmakedefine01 HAVE_BINARY_SETPGRP
+#cmakedefine01 HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
+#cmakedefine01 HAVE_PANGO_FONT_MAP_LIST_FAMILIES
+
+#cmakedefine01 HAVE_AES_NI
+#cmakedefine01 HAVE_SHA_NI
+#cmakedefine01 HAVE_SHAINTRIN_H
+#cmakedefine01 HAVE_CLMUL
+#cmakedefine01 HAVE_NEON_CRYPTO
+#cmakedefine01 HAVE_NEON_PMULL
+#cmakedefine01 HAVE_NEON_VADDQ_P128
+#cmakedefine01 HAVE_NEON_SHA512
+#cmakedefine01 HAVE_NEON_SHA512_INTRINSICS
+#cmakedefine01 USE_ARM64_NEON_H
diff --git a/cmake/gitcommit.cmake b/cmake/gitcommit.cmake
new file mode 100644
index 00000000..0aa8a095
--- /dev/null
+++ b/cmake/gitcommit.cmake
@@ -0,0 +1,63 @@
+# Pure cmake script to write out cmake_commit.c and cmake_version.but
+
+set(DEFAULT_COMMIT "unavailable")
+set(commit "${DEFAULT_COMMIT}")
+
+set(TOPLEVEL_SOURCE_DIR ${CMAKE_SOURCE_DIR})
+
+execute_process(
+ COMMAND ${GIT_EXECUTABLE} rev-parse --show-toplevel
+ OUTPUT_VARIABLE git_worktree
+ ERROR_VARIABLE stderr
+ RESULT_VARIABLE status)
+string(REGEX REPLACE "\n$" "" git_worktree "${git_worktree}")
+
+if(status EQUAL 0)
+ if(git_worktree STREQUAL CMAKE_SOURCE_DIR)
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
+ OUTPUT_VARIABLE git_commit
+ ERROR_VARIABLE stderr
+ RESULT_VARIABLE status)
+ if(status EQUAL 0)
+ string(REGEX REPLACE "\n$" "" commit "${git_commit}")
+ else()
+ if(commit STREQUAL "unavailable")
+ message("Unable to determine git commit: 'git rev-parse HEAD' returned status ${status} and error output:\n${stderr}\n")
+ endif()
+ endif()
+ else()
+ if(commit STREQUAL "unavailable")
+ message("Unable to determine git commit: top-level source dir ${CMAKE_SOURCE_DIR} is not the root of a repository")
+ endif()
+ endif()
+else()
+ if(commit STREQUAL "unavailable")
+ message("Unable to determine git commit: 'git rev-parse --show-toplevel' returned status ${status} and error output:\n${stderr}\n")
+ endif()
+endif()
+
+if(OUTPUT_TYPE STREQUAL header)
+ file(WRITE "${OUTPUT_FILE}" "\
+/*
+ * cmake_commit.c - string literal giving the source git commit, if known.
+ *
+ * Generated by cmake/gitcommit.cmake.
+ */
+
+#include \"putty.h\"
+const char commitid[] = \"${commit}\";
+")
+elseif(OUTPUT_TYPE STREQUAL halibut)
+ if(commit STREQUAL "unavailable")
+ file(WRITE "${OUTPUT_FILE}" "\
+\\versionid no version information available
+")
+ else()
+ file(WRITE "${OUTPUT_FILE}" "\
+\\versionid built from git commit ${commit}
+")
+ endif()
+else()
+ message(FATAL_ERROR "Set OUTPUT_TYPE when running this script")
+endif()
diff --git a/cmake/gtk.cmake b/cmake/gtk.cmake
new file mode 100644
index 00000000..13ff7705
--- /dev/null
+++ b/cmake/gtk.cmake
@@ -0,0 +1,89 @@
+# Look for GTK, of any version.
+
+set(PUTTY_GTK_VERSION "ANY"
+ CACHE STRING "Which major version of GTK to build with")
+set_property(CACHE PUTTY_GTK_VERSION
+ PROPERTY STRINGS ANY 3 2 1 NONE)
+
+set(GTK_FOUND FALSE)
+
+macro(try_pkg_config_gtk VER PACKAGENAME)
+ if(NOT GTK_FOUND AND
+ (PUTTY_GTK_VERSION STREQUAL ANY OR PUTTY_GTK_VERSION STREQUAL ${VER}))
+ find_package(PkgConfig)
+ pkg_check_modules(GTK ${PACKAGENAME})
+ if(GTK_FOUND)
+ set(GTK_VERSION ${VER})
+ endif()
+ endif()
+endmacro()
+try_pkg_config_gtk(3 gtk+-3.0)
+try_pkg_config_gtk(2 gtk+-2.0)
+
+if(NOT GTK_FOUND AND
+ (PUTTY_GTK_VERSION STREQUAL ANY OR PUTTY_GTK_VERSION STREQUAL 1))
+ message("-- Checking for GTK1 (via gtk-config)")
+ find_program(GTK_CONFIG gtk-config)
+ if(GTK_CONFIG)
+ execute_process(COMMAND ${GTK_CONFIG} --cflags
+ OUTPUT_VARIABLE gtk_config_cflags
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE gtk_config_cflags_result)
+ execute_process(COMMAND ${GTK_CONFIG} --libs
+ OUTPUT_VARIABLE gtk_config_libs
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE gtk_config_libs_result)
+
+ if(gtk_config_cflags_result EQUAL 0 AND gtk_config_libs_result EQUAL 0)
+
+ set(GTK_INCLUDE_DIRS)
+ set(GTK_LIBRARY_DIRS)
+ set(GTK_LIBRARIES)
+
+ separate_arguments(gtk_config_cflags NATIVE_COMMAND
+ ${gtk_config_cflags})
+ foreach(opt ${gtk_config_cflags})
+ string(REGEX MATCH "^-I" ok ${opt})
+ if(ok)
+ string(REGEX REPLACE "^-I" "" optval ${opt})
+ list(APPEND GTK_INCLUDE_DIRS ${optval})
+ endif()
+ endforeach()
+
+ separate_arguments(gtk_config_libs NATIVE_COMMAND
+ ${gtk_config_libs})
+ foreach(opt ${gtk_config_libs})
+ string(REGEX MATCH "^-l" ok ${opt})
+ if(ok)
+ list(APPEND GTK_LIBRARIES ${opt})
+ endif()
+ string(REGEX MATCH "^-L" ok ${opt})
+ if(ok)
+ string(REGEX REPLACE "^-L" "" optval ${opt})
+ list(APPEND GTK_LIBRARY_DIRS ${optval})
+ endif()
+ endforeach()
+
+ message("-- Found GTK1")
+ set(GTK_FOUND TRUE)
+ endif()
+ endif()
+endif()
+
+if(GTK_FOUND)
+ # Check for some particular Pango functions.
+ function(pango_check_subscope)
+ set(CMAKE_REQUIRED_INCLUDES ${GTK_INCLUDE_DIRS})
+ set(CMAKE_REQUIRED_LINK_OPTIONS ${GTK_LDFLAGS})
+ set(CMAKE_REQUIRED_LIBRARIES ${GTK_LIBRARIES})
+ check_symbol_exists(pango_font_family_is_monospace "pango/pango.h"
+ HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
+ check_symbol_exists(pango_font_map_list_families "pango/pango.h"
+ HAVE_PANGO_FONT_MAP_LIST_FAMILIES)
+ set(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
+ ${HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE} PARENT_SCOPE)
+ set(HAVE_PANGO_FONT_MAP_LIST_FAMILIES
+ ${HAVE_PANGO_FONT_MAP_LIST_FAMILIES} PARENT_SCOPE)
+ endfunction()
+ pango_check_subscope()
+endif()
diff --git a/cmake/licence.cmake b/cmake/licence.cmake
new file mode 100644
index 00000000..e356ae93
--- /dev/null
+++ b/cmake/licence.cmake
@@ -0,0 +1,39 @@
+# Pure cmake script to generate licence.h from LICENCE
+
+file(READ "${LICENCE_FILE}" LICENCE_TEXT)
+
+function(c_string_escape outvar value)
+ string(REPLACE "\\" "\\\\" value "${value}")
+ string(REPLACE "\"" "\\\"" value "${value}")
+ set("${outvar}" "${value}" PARENT_SCOPE)
+endfunction()
+
+set(copyright_regex "PuTTY is copyright ([0-9]+-[0-9]+ [^\n]*[^\n.])\\.?\n")
+string(REGEX MATCH "${copyright_regex}" COPYRIGHT_NOTICE "${LICENCE_TEXT}")
+string(REGEX REPLACE "${copyright_regex}" "\\1"
+ COPYRIGHT_NOTICE "${COPYRIGHT_NOTICE}")
+c_string_escape(COPYRIGHT_NOTICE "${COPYRIGHT_NOTICE}")
+
+string(REGEX REPLACE "\n$" "" LICENCE_TEXT "${LICENCE_TEXT}")
+string(REPLACE "\r" "" LICENCE_TEXT "${LICENCE_TEXT}")
+string(REPLACE "\n\n" "\r" LICENCE_TEXT "${LICENCE_TEXT}")
+string(REPLACE "\n" " " LICENCE_TEXT "${LICENCE_TEXT}")
+string(REPLACE "\r" "\n" LICENCE_TEXT "${LICENCE_TEXT}")
+
+c_string_escape(LICENCE_TEXT "${LICENCE_TEXT}")
+string(REPLACE "\n" "\" \\\n parsep \\\n \""
+ LICENCE_TEXT "${LICENCE_TEXT}")
+
+file(WRITE "${OUTPUT_FILE}" "\
+/*
+ * licence.h - macro definitions for the PuTTY licence.
+ *
+ * Generated by cmake/licence.cmake from ./LICENCE.
+ * You should edit those files rather than editing this one.
+ */
+
+#define LICENCE_TEXT(parsep) \\
+ \"${LICENCE_TEXT}\"
+
+#define SHORT_COPYRIGHT_DETAILS \"${COPYRIGHT_NOTICE}\"
+")
diff --git a/cmake/platforms/unix.cmake b/cmake/platforms/unix.cmake
new file mode 100644
index 00000000..4d056d0a
--- /dev/null
+++ b/cmake/platforms/unix.cmake
@@ -0,0 +1,234 @@
+set(PUTTY_GSSAPI DYNAMIC
+ CACHE STRING "Build PuTTY with dynamically or statically linked \
+Kerberos / GSSAPI support, if possible")
+set_property(CACHE PUTTY_GSSAPI
+ PROPERTY STRINGS DYNAMIC STATIC OFF)
+
+include(CheckIncludeFile)
+include(CheckLibraryExists)
+include(CheckSymbolExists)
+include(CheckCSourceCompiles)
+include(GNUInstallDirs)
+
+set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ -D_DEFAULT_SOURCE -D_GNU_SOURCE)
+
+check_include_file(sys/auxv.h HAVE_SYS_AUXV_H)
+check_include_file(asm/hwcap.h HAVE_ASM_HWCAP_H)
+check_include_file(sys/sysctl.h HAVE_SYS_SYSCTL_H)
+check_include_file(sys/types.h HAVE_SYS_TYPES_H)
+check_include_file(glob.h HAVE_GLOB_H)
+check_include_file(utmp.h HAVE_UTMP_H)
+check_include_file(utmpx.h HAVE_UTMPX_H)
+
+check_symbol_exists(futimes "sys/time.h" HAVE_FUTIMES)
+check_symbol_exists(getaddrinfo "sys/types.h;sys/socket.h;netdb.h"
+ HAVE_GETADDRINFO)
+check_symbol_exists(posix_openpt "stdlib.h;fcntl.h" HAVE_POSIX_OPENPT)
+check_symbol_exists(ptsname "stdlib.h" HAVE_PTSNAME)
+check_symbol_exists(setresuid "unistd.h" HAVE_SETRESUID)
+check_symbol_exists(setresgid "unistd.h" HAVE_SETRESGID)
+check_symbol_exists(strsignal "string.h" HAVE_STRSIGNAL)
+check_symbol_exists(updwtmpx "utmpx.h" HAVE_UPDWTMPX)
+check_symbol_exists(fstatat "sys/types.h;sys/stat.h;unistd.h" HAVE_FSTATAT)
+check_symbol_exists(dirfd "sys/types.h;dirent.h" HAVE_DIRFD)
+check_symbol_exists(setpwent "sys/types.h;pwd.h" HAVE_SETPWENT)
+check_symbol_exists(endpwent "sys/types.h;pwd.h" HAVE_ENDPWENT)
+check_symbol_exists(getauxval "sys/auxv.h" HAVE_GETAUXVAL)
+check_symbol_exists(elf_aux_info "sys/auxv.h" HAVE_ELF_AUX_INFO)
+check_symbol_exists(sysctlbyname "sys/types.h;sys/sysctl.h" HAVE_SYSCTLBYNAME)
+check_symbol_exists(CLOCK_MONOTONIC "time.h" HAVE_CLOCK_MONOTONIC)
+check_symbol_exists(clock_gettime "time.h" HAVE_CLOCK_GETTIME)
+
+check_c_source_compiles("
+#define _GNU_SOURCE
+#include <features.h>
+#include <sys/socket.h>
+int main(int argc, char **argv) {
+ struct ucred cr;
+ socklen_t crlen = sizeof(cr);
+ return getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cr, &crlen) +
+ cr.pid + cr.uid + cr.gid;
+}" HAVE_SO_PEERCRED)
+
+check_c_source_compiles("
+#include <sys/types.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ setpgrp();
+}" HAVE_NULLARY_SETPGRP)
+check_c_source_compiles("
+#include <sys/types.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ setpgrp(0, 0);
+}" HAVE_BINARY_SETPGRP)
+
+if(HAVE_GETADDRINFO AND PUTTY_IPV6)
+ set(NO_IPV6 OFF)
+else()
+ set(NO_IPV6 ON)
+endif()
+
+if(HAVE_UTMPX_H)
+ set(OMIT_UTMP OFF)
+else()
+ set(OMIT_UTMP ON)
+endif()
+
+include(cmake/gtk.cmake)
+
+if(GTK_FOUND)
+ # See if we have X11 available. This requires libX11 itself, and also
+ # the GDK integration to X11.
+ find_package(X11)
+
+ function(check_x11)
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${GTK_INCLUDE_DIRS})
+ check_include_file(gdk/gdkx.h HAVE_GDK_GDKX_H)
+
+ if(X11_FOUND AND HAVE_GDK_GDKX_H)
+ set(NOT_X_WINDOWS OFF PARENT_SCOPE)
+ else()
+ set(NOT_X_WINDOWS ON PARENT_SCOPE)
+ endif()
+ endfunction()
+ check_x11()
+else()
+ # If we didn't even have GTK, behave as if X11 is not available.
+ # (There's nothing useful we could do with it even if there was.)
+ set(NOT_X_WINDOWS ON)
+endif()
+
+include_directories(${CMAKE_SOURCE_DIR}/charset ${GTK_INCLUDE_DIRS} ${X11_INCLUDE_DIR})
+link_directories(${GTK_LIBRARY_DIRS})
+
+function(add_optional_system_lib library testfn)
+ check_library_exists(${library} ${testfn} "" HAVE_LIB${library})
+ if (HAVE_LIB${library})
+ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES};-l${library})
+ link_libraries(-l${library})
+ endif()
+endfunction()
+
+add_optional_system_lib(m pow)
+add_optional_system_lib(rt clock_gettime)
+add_optional_system_lib(xnet socket)
+
+set(extra_dirs charset)
+
+if(PUTTY_GSSAPI STREQUAL DYNAMIC)
+ add_optional_system_lib(dl dlopen)
+ if(HAVE_NO_LIBdl)
+ message(WARNING
+ "Could not find libdl -- cannot provide dynamic GSSAPI support")
+ set(NO_GSSAPI ON)
+ endif()
+endif()
+
+if(PUTTY_GSSAPI STREQUAL STATIC)
+ set(KRB5_CFLAGS)
+ set(KRB5_LDFLAGS)
+
+ # First try using pkg-config
+ find_package(PkgConfig)
+ pkg_check_modules(KRB5 krb5-gssapi)
+
+ # Failing that, try the dedicated krb5-config
+ if(NOT KRB5_FOUND)
+ find_program(KRB5_CONFIG krb5-config)
+ if(KRB5_CONFIG)
+ execute_process(COMMAND ${KRB5_CONFIG} --cflags gssapi
+ OUTPUT_VARIABLE krb5_config_cflags
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE krb5_config_cflags_result)
+ execute_process(COMMAND ${KRB5_CONFIG} --libs gssapi
+ OUTPUT_VARIABLE krb5_config_libs
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE krb5_config_libs_result)
+
+ if(krb5_config_cflags_result EQUAL 0 AND krb5_config_libs_result EQUAL 0)
+ set(KRB5_INCLUDE_DIRS)
+ set(KRB5_LIBRARY_DIRS)
+ set(KRB5_LIBRARIES)
+
+ # We can safely put krb5-config's cflags directly into cmake's
+ # cflags, without bothering to extract the include directories.
+ set(KRB5_CFLAGS ${krb5_config_cflags})
+
+ # But krb5-config --libs isn't so simple. It will actually
+ # deliver a mix of libraries and other linker options. We have
+ # to separate them for cmake purposes, because if we pass the
+ # whole lot to add_link_options then they'll appear too early
+ # in the command line (so that by the time our own code refers
+ # to GSSAPI functions it'll be too late to search these
+ # libraries for them), and if we pass the whole lot to
+ # link_libraries then it'll get confused about options that
+ # aren't libraries.
+ separate_arguments(krb5_config_libs NATIVE_COMMAND
+ ${krb5_config_libs})
+ foreach(opt ${krb5_config_libs})
+ string(REGEX MATCH "^-l" ok ${opt})
+ if(ok)
+ list(APPEND KRB5_LIBRARIES ${opt})
+ continue()
+ endif()
+ string(REGEX MATCH "^-L" ok ${opt})
+ if(ok)
+ string(REGEX REPLACE "^-L" "" optval ${opt})
+ list(APPEND KRB5_LIBRARY_DIRS ${optval})
+ continue()
+ endif()
+ list(APPEND KRB5_LDFLAGS ${opt})
+ endforeach()
+
+ message(STATUS "Found Kerberos via krb5-config")
+ set(KRB5_FOUND YES)
+ endif()
+ endif()
+ endif()
+
+ if(KRB5_FOUND)
+ include_directories(${KRB5_INCLUDE_DIRS})
+ link_directories(${KRB5_LIBRARY_DIRS})
+ link_libraries(${KRB5_LIBRARIES})
+ add_compile_options(${KRB5_CFLAGS})
+ add_link_options(${KRB5_LDFLAGS})
+ set(STATIC_GSSAPI ON)
+ else()
+ message(WARNING
+ "Could not find krb5 via pkg-config or krb5-config -- \
+cannot provide static GSSAPI support")
+ set(NO_GSSAPI ON)
+ endif()
+endif()
+
+if(PUTTY_GSSAPI STREQUAL OFF)
+ set(NO_GSSAPI ON)
+endif()
+
+if(STRICT AND (CMAKE_C_COMPILER_ID MATCHES "GNU" OR
+ CMAKE_C_COMPILER_ID MATCHES "Clang"))
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wpointer-arith -Wvla")
+endif()
+
+function(installed_program target)
+ if(CMAKE_VERSION VERSION_LESS 3.14)
+ # CMake 3.13 and earlier required an explicit install destination.
+ install(TARGETS ${target} RUNTIME DESTINATION bin)
+ else()
+ # 3.14 and above selects a sensible default, which we should avoid
+ # overriding here so that end users can override it using
+ # CMAKE_INSTALL_BINDIR.
+ install(TARGETS ${target})
+ endif()
+
+ if(HAVE_MANPAGE_${target}_1)
+ install(FILES ${CMAKE_BINARY_DIR}/doc/${target}.1
+ DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+ else()
+ message(WARNING "Could not build man page ${target}.1")
+ endif()
+endfunction()
diff --git a/cmake/platforms/windows.cmake b/cmake/platforms/windows.cmake
new file mode 100644
index 00000000..a7ed7c7c
--- /dev/null
+++ b/cmake/platforms/windows.cmake
@@ -0,0 +1,202 @@
+set(PUTTY_MINEFIELD OFF
+ CACHE BOOL "Build PuTTY with its built-in memory debugger 'Minefield'")
+set(PUTTY_GSSAPI ON
+ CACHE BOOL "Build PuTTY with GSSAPI support")
+set(PUTTY_LINK_MAPS OFF
+ CACHE BOOL "Attempt to generate link maps")
+set(PUTTY_EMBEDDED_CHM_FILE ""
+ CACHE FILEPATH "Path to a .chm help file to embed in the binaries")
+
+if(PUTTY_SUBSYSTEM_VERSION)
+ string(REPLACE
+ "subsystem:windows" "subsystem:windows,${PUTTY_SUBSYSTEM_VERSION}"
+ CMAKE_C_CREATE_WIN32_EXE ${CMAKE_C_CREATE_WIN32_EXE})
+ string(REPLACE
+ "subsystem:console" "subsystem:console,${PUTTY_SUBSYSTEM_VERSION}"
+ CMAKE_C_CREATE_CONSOLE_EXE ${CMAKE_C_CREATE_CONSOLE_EXE})
+endif()
+
+function(define_negation newvar oldvar)
+ if(${oldvar})
+ set(${newvar} OFF PARENT_SCOPE)
+ else()
+ set(${newvar} ON PARENT_SCOPE)
+ endif()
+endfunction()
+
+include(CheckIncludeFiles)
+include(CheckSymbolExists)
+include(CheckCSourceCompiles)
+
+# Still needed for AArch32 Windows builds
+set(CMAKE_REQUIRED_DEFINITIONS -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE)
+
+check_include_files("windows.h;winresrc.h" HAVE_WINRESRC_H)
+if(NOT HAVE_WINRESRC_H)
+ # A couple of fallback names for the header file you can include in
+ # .rc files. We conditionalise even these checks, to save effort at
+ # cmake time.
+ check_include_files("windows.h;winres.h" HAVE_WINRES_H)
+ if(NOT HAVE_WINRES_H)
+ check_include_files("windows.h;win.h" HAVE_WIN_H)
+ endif()
+endif()
+check_include_files("stdint.h" HAVE_STDINT_H)
+define_negation(HAVE_NO_STDINT_H HAVE_STDINT_H)
+
+check_include_files("windows.h;multimon.h" HAVE_MULTIMON_H)
+define_negation(NO_MULTIMON HAVE_MULTIMON_H)
+
+check_include_files("windows.h;htmlhelp.h" HAVE_HTMLHELP_H)
+define_negation(NO_HTMLHELP HAVE_HTMLHELP_H)
+
+check_include_files("winsock2.h;afunix.h" HAVE_AFUNIX_H)
+
+check_symbol_exists(strtoumax "inttypes.h" HAVE_STRTOUMAX)
+check_symbol_exists(AddDllDirectory "windows.h" HAVE_ADDDLLDIRECTORY)
+check_symbol_exists(SetDefaultDllDirectories "windows.h"
+ HAVE_SETDEFAULTDLLDIRECTORIES)
+check_symbol_exists(GetNamedPipeClientProcessId "windows.h"
+ HAVE_GETNAMEDPIPECLIENTPROCESSID)
+check_symbol_exists(CreatePseudoConsole "windows.h" HAVE_CONPTY)
+
+check_c_source_compiles("
+#include <windows.h>
+GCP_RESULTSW gcpw;
+int main(void) { return 0; }
+" HAVE_GCP_RESULTSW)
+
+function(dwmapi_test_wrapper)
+ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dwmapi.lib)
+ check_c_source_compiles("
+#include <windows.h>
+#include <dwmapi.h>
+volatile HWND hwnd;
+int main(void) {
+ RECT r;
+ DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(r));
+}
+" HAVE_DWMAPI_H)
+ set(HAVE_DWMAPI_H ${HAVE_DWMAPI_H} PARENT_SCOPE)
+endfunction()
+dwmapi_test_wrapper()
+
+set(NO_SECURITY ${PUTTY_NO_SECURITY})
+
+add_compile_definitions(
+ _WINDOWS
+ _CRT_SECURE_NO_WARNINGS
+ _WINSOCK_DEPRECATED_NO_WARNINGS
+ _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE)
+
+if(PUTTY_MINEFIELD)
+ add_compile_definitions(MINEFIELD)
+endif()
+if(NOT PUTTY_GSSAPI)
+ add_compile_definitions(NO_GSSAPI)
+endif()
+if(PUTTY_EMBEDDED_CHM_FILE)
+ add_compile_definitions("EMBEDDED_CHM_FILE=\"${PUTTY_EMBEDDED_CHM_FILE}\"")
+endif()
+
+if(WINELIB)
+ enable_language(RC)
+ set(LFLAG_MANIFEST_NO "")
+elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC" OR
+ CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")
+ set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} /nologo /C1252")
+ set(LFLAG_MANIFEST_NO "/manifest:no")
+else()
+ set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -c1252")
+ set(LFLAG_MANIFEST_NO "")
+endif()
+
+if(STRICT)
+ if(CMAKE_C_COMPILER_ID MATCHES "GNU")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wpointer-arith -Wvla")
+ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wpointer-arith -Wvla")
+ endif()
+endif()
+
+if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ # Switch back from MSVC-style error message format
+ # "file.c(line,col)" to clang's native style "file.c:line:col:". I
+ # find the latter more convenient because it matches other Unixy
+ # tools like grep, and I have tooling to parse that format and jump
+ # to the sites of error messages.
+ set(CMAKE_C_FLAGS
+ "${CMAKE_C_FLAGS} -Xclang -fdiagnostics-format -Xclang clang")
+endif()
+
+if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
+ # Turn off some warnings that I've just found too noisy.
+ #
+ # - 4244, 4267: "possible loss of data" when narrowing an integer
+ # type (separate warning numbers for initialisers and
+ # assignments). Every time I spot-check instances of this, they
+ # turn out to be sensible (e.g. something was already checked, or
+ # was assigned from a previous variable that must have been in
+ # range). I don't think putting a warning-suppression idiom at
+ # every one of these sites would improve code legibility.
+ #
+ # - 4018: "signed/unsigned mismatch" in integer comparison. Again,
+ # comes up a lot, and generally my spot checks make it look as if
+ # it's OK.
+ #
+ # - 4146: applying unary '-' to an unsigned type. We do that all
+ # the time in deliberate bit-twiddling code like mpint.c or
+ # crypto implementations.
+ #
+ # - 4293: warning about undefined behaviour if a shift count is too
+ # big. We often do this inside a ?: clause which doesn't evaluate
+ # the overlong shift unless the shift count _isn't_ too big. When
+ # the shift count is constant, MSVC spots the potential problem
+ # in one branch of the ?:, but doesn't also spot that that branch
+ # isn't ever taken, so it complains about a thing that's already
+ # guarded.
+ #
+ # - 4090: different 'const' qualifiers. It's a shame to suppress
+ # this one, because const mismatches really are a thing I'd
+ # normally like to be warned about. But MSVC (as of 2017 at
+ # least) seems to have a bug in which assigning a 'void *' into a
+ # 'const char **' thinks there's a const-qualifier mismatch.
+ # There isn't! Both are pointers to modifiable objects. The fact
+ # that in one case, the modifiable object is a pointer to
+ # something _else_ const should make no difference.
+
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
+/wd4244 /wd4267 /wd4018 /wd4146 /wd4293 /wd4090")
+endif()
+
+if(CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")
+ set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} /dynamicbase /nxcompat")
+endif()
+
+set(platform_libraries
+ advapi32.lib comdlg32.lib gdi32.lib imm32.lib
+ ole32.lib shell32.lib user32.lib ws2_32.lib kernel32.lib)
+
+# Generate link maps
+if(PUTTY_LINK_MAPS)
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND
+ "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
+ set(CMAKE_C_LINK_EXECUTABLE
+ "${CMAKE_C_LINK_EXECUTABLE} /lldmap:<TARGET>.map")
+ elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC")
+ set(CMAKE_C_LINK_EXECUTABLE
+ "${CMAKE_C_LINK_EXECUTABLE} /map:<TARGET>.map")
+ else()
+ message(WARNING
+ "Don't know how to generate link maps on this toolchain")
+ endif()
+endif()
+
+# Write out a file in the cmake output directory listing the
+# executables that are 'official' enough to want to code-sign and
+# ship.
+file(WRITE ${CMAKE_BINARY_DIR}/shipped.txt "")
+function(installed_program target)
+ file(APPEND ${CMAKE_BINARY_DIR}/shipped.txt
+ "${target}${CMAKE_EXECUTABLE_SUFFIX}\n")
+endfunction()
diff --git a/cmake/setup.cmake b/cmake/setup.cmake
new file mode 100644
index 00000000..7a650771
--- /dev/null
+++ b/cmake/setup.cmake
@@ -0,0 +1,113 @@
+# Forcibly re-enable assertions, even if we're building in release
+# mode. This is a security project - assertions may be enforcing
+# security-critical constraints. A backstop #ifdef in defs.h should
+# give a #error if this manoeuvre doesn't do what it needs to.
+string(REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
+string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
+string(REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
+string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
+
+set(PUTTY_IPV6 ON
+ CACHE BOOL "Build PuTTY with IPv6 support if possible")
+set(PUTTY_DEBUG OFF
+ CACHE BOOL "Build PuTTY with debug() statements enabled")
+set(PUTTY_FUZZING OFF
+ CACHE BOOL "Build PuTTY binaries suitable for fuzzing, NOT FOR REAL USE")
+set(PUTTY_COVERAGE OFF
+ CACHE BOOL "Build PuTTY binaries suitable for code coverage analysis")
+
+set(STRICT OFF
+ CACHE BOOL "Enable extra compiler warnings and make them errors")
+
+include(FindGit)
+
+set(GENERATED_SOURCES_DIR ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY})
+
+set(GENERATED_LICENCE_H ${GENERATED_SOURCES_DIR}/licence.h)
+set(INTERMEDIATE_LICENCE_H ${GENERATED_LICENCE_H}.tmp)
+add_custom_command(OUTPUT ${INTERMEDIATE_LICENCE_H}
+ COMMAND ${CMAKE_COMMAND}
+ -DLICENCE_FILE=${CMAKE_SOURCE_DIR}/LICENCE
+ -DOUTPUT_FILE=${INTERMEDIATE_LICENCE_H}
+ -P ${CMAKE_SOURCE_DIR}/cmake/licence.cmake
+ DEPENDS ${CMAKE_SOURCE_DIR}/cmake/licence.cmake ${CMAKE_SOURCE_DIR}/LICENCE)
+add_custom_target(generated_licence_h
+ BYPRODUCTS ${GENERATED_LICENCE_H}
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${INTERMEDIATE_LICENCE_H} ${GENERATED_LICENCE_H}
+ DEPENDS ${INTERMEDIATE_LICENCE_H}
+ COMMENT "Updating licence.h")
+
+set(GENERATED_COMMIT_C ${GENERATED_SOURCES_DIR}/cmake_commit.c)
+set(INTERMEDIATE_COMMIT_C ${GENERATED_COMMIT_C}.tmp)
+add_custom_target(check_git_commit
+ BYPRODUCTS ${INTERMEDIATE_COMMIT_C}
+ COMMAND ${CMAKE_COMMAND}
+ -DGIT_EXECUTABLE=${GIT_EXECUTABLE}
+ -DOUTPUT_FILE=${INTERMEDIATE_COMMIT_C}
+ -DOUTPUT_TYPE=header
+ -P ${CMAKE_SOURCE_DIR}/cmake/gitcommit.cmake
+ DEPENDS ${CMAKE_SOURCE_DIR}/cmake/gitcommit.cmake
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMENT "Checking current git commit")
+add_custom_target(cmake_commit_c
+ BYPRODUCTS ${GENERATED_COMMIT_C}
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${INTERMEDIATE_COMMIT_C} ${GENERATED_COMMIT_C}
+ DEPENDS check_git_commit ${INTERMEDIATE_COMMIT_C}
+ COMMENT "Updating cmake_commit.c")
+
+if(CMAKE_VERSION VERSION_LESS 3.12)
+ function(add_compile_definitions)
+ foreach(i ${ARGN})
+ add_compile_options(-D${i})
+ endforeach()
+ endfunction()
+endif()
+
+function(add_sources_from_current_dir target)
+ set(sources)
+ foreach(i ${ARGN})
+ set(sources ${sources} ${CMAKE_CURRENT_SOURCE_DIR}/${i})
+ endforeach()
+ target_sources(${target} PRIVATE ${sources})
+endfunction()
+
+set(extra_dirs)
+if(CMAKE_SYSTEM_NAME MATCHES "Windows" OR WINELIB)
+ set(platform windows)
+else()
+ set(platform unix)
+endif()
+
+function(be_list TARGET NAME)
+ cmake_parse_arguments(OPT "SSH;SERIAL;OTHERBACKENDS" "" "" "${ARGN}")
+ add_library(${TARGET}-be-list OBJECT ${CMAKE_SOURCE_DIR}/be_list.c)
+ foreach(setting SSH SERIAL OTHERBACKENDS)
+ if(OPT_${setting})
+ target_compile_definitions(${TARGET}-be-list PRIVATE ${setting}=1)
+ else()
+ target_compile_definitions(${TARGET}-be-list PRIVATE ${setting}=0)
+ endif()
+ endforeach()
+ target_compile_definitions(${TARGET}-be-list PRIVATE APPNAME=${NAME})
+ target_sources(${TARGET} PRIVATE $<TARGET_OBJECTS:${TARGET}-be-list>)
+endfunction()
+
+include(cmake/platforms/${platform}.cmake)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${GENERATED_SOURCES_DIR}
+ ${platform}
+ ${extra_dirs})
+
+if(PUTTY_DEBUG)
+ add_compile_definitions(DEBUG)
+endif()
+if(PUTTY_FUZZING)
+ add_compile_definitions(FUZZING)
+endif()
+if(PUTTY_COVERAGE)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage -g ")
+endif()
diff --git a/cmake/toolchain-mingw.cmake b/cmake/toolchain-mingw.cmake
new file mode 100644
index 00000000..2e0bc669
--- /dev/null
+++ b/cmake/toolchain-mingw.cmake
@@ -0,0 +1,12 @@
+# Simple toolchain file for cross-building Windows PuTTY on Linux
+# using MinGW (tested on Ubuntu).
+
+set(CMAKE_SYSTEM_NAME Windows)
+set(CMAKE_SYSTEM_PROCESSOR x86_64)
+
+set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
+set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
+set(CMAKE_AR x86_64-w64-mingw32-ar)
+set(CMAKE_RANLIB x86_64-w64-mingw32-ranlib)
+
+add_compile_definitions(__USE_MINGW_ANSI_STDIO)
diff --git a/cmake/toolchain-winegcc.cmake b/cmake/toolchain-winegcc.cmake
new file mode 100644
index 00000000..73a9e53e
--- /dev/null
+++ b/cmake/toolchain-winegcc.cmake
@@ -0,0 +1,33 @@
+# Toolchain file for cross-building a Winelib version of Windows PuTTY
+# on Linux, using winegcc (tested on Ubuntu).
+
+# Winelib is weird because it's basically compiling ordinary Linux
+# objects and executables, but we want to pretend to be Windows for
+# purposes of (a) having resource files, and (b) selecting the Windows
+# platform subdirectory.
+#
+# So, do we tag this as a weird kind of Windows build, or a weird kind
+# of Linux build? Either way we have to do _something_ out of the
+# ordinary.
+#
+# After some experimentation, it seems to make more sense to treat
+# Winelib builds as basically Linux, and set a flag WINELIB that
+# PuTTY's main build scripts will detect and handle specially.
+# Specifically, that flag will cause cmake/setup.cmake to select the
+# Windows platform (overriding the usual check of CMAKE_SYSTEM_NAME),
+# and also trigger a call to enable_language(RC), which for some kind
+# of cmake re-entrancy reason we can't do in this toolchain file
+# itself.
+set(CMAKE_SYSTEM_NAME Linux)
+set(WINELIB ON)
+
+# We need a wrapper script around winegcc proper, because cmake's link
+# command lines will refer to system libraries as "-lkernel32.lib"
+# rather than the required "-lkernel32". The winegcc script alongside
+# this toolchain file bodges that command-line translation.
+set(CMAKE_C_COMPILER ${CMAKE_SOURCE_DIR}/cmake/winegcc)
+
+set(CMAKE_RC_COMPILER wrc)
+set(CMAKE_RC_OUTPUT_EXTENSION .res.o)
+set(CMAKE_RC_COMPILE_OBJECT
+ "<CMAKE_RC_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
diff --git a/cmake/winegcc b/cmake/winegcc
new file mode 100755
index 00000000..fb298ad1
--- /dev/null
+++ b/cmake/winegcc
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Wrapper for winegcc that allows it to be used in a build generated
+# from PuTTY's CMakeLists.txt, by bodging around the command-line
+# options that CMake gets wrong.
+
+init=true
+for arg in init "$@"; do
+ if $init; then
+ set --
+ init=false
+ continue
+ fi
+
+ case "$arg" in
+ # The Windows build definition for PuTTY specifies all the
+ # system API libraries by names like kernel32.lib. When CMake
+ # reads that file and thinks it's compiling for Linux, it will
+ # generate link options such as -lkernel32.lib. But in fact
+ # winegcc expects -lkernel32, so we need to strip the ".lib"
+ # suffix.
+ -l*.lib) set -- "$@" "${arg%.lib}";;
+
+ # Anything else, we leave unchanged.
+ *) set -- "$@" "$arg";;
+ esac
+done
+
+exec winegcc "$@"