From 75222ccef804a2e1e1d43eb6ed8b60ba93c03cc5 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Mon, 6 Dec 2021 20:52:59 +0000 Subject: [PATCH] Overhaul dependency options Changes how dependency options are handled and moves them out of `CMakeLists.txt`. Major changes: 1. The static default now takes `TARGET_SUPPORTS_SHARED_LIBS` into account 2. The `DIST` setting no longer affects the static default. 3. The static option is now visible for system dependencies as well. (it was previously hidden by `cmake_dependent_option`). 4. The auto-detection mechanism for `libfmt` and `SDL_image` only applies if the setting has not been set. 5. SDL2 on Android is now also linked statically, resulting in a 1.1 MiB smaller APK. When using non-system dependencies, the default should always be static, as there are 2 main use cases for these: 1. Dependencies that we must currently vendor because our forks have significant changes that are not yet merged/released upstream. 2. Platforms that have no system packages, such as Android and iOS. In both cases, static linking is the most appropriate default. --- 3rdParty/PKWare/CMakeLists.txt | 4 + 3rdParty/SDL_image/CMakeLists.txt | 22 +- 3rdParty/asio/CMakeLists.txt | 4 + CMake/Dependencies.cmake | 153 +++++++++++ CMake/Platforms.cmake | 66 +++++ CMake/VcPkgManifestFeatures.cmake | 15 ++ CMake/android_defs.cmake | 6 +- CMake/ctr/asio_defs.cmake | 6 + CMake/ctr/n3ds_defs.cmake | 2 +- CMake/dependency_options.cmake | 40 +++ CMake/ios_defs.cmake | 6 - CMake/platforms/switch/asio_defs.cmake | 5 + CMake/switch/asio_defs.cmake | 10 +- CMakeLists.txt | 352 +++++-------------------- Source/encrypt.cpp | 2 +- 15 files changed, 387 insertions(+), 306 deletions(-) create mode 100644 3rdParty/PKWare/CMakeLists.txt create mode 100644 CMake/Dependencies.cmake create mode 100644 CMake/Platforms.cmake create mode 100644 CMake/VcPkgManifestFeatures.cmake create mode 100644 CMake/ctr/asio_defs.cmake create mode 100644 CMake/dependency_options.cmake create mode 100644 CMake/platforms/switch/asio_defs.cmake diff --git a/3rdParty/PKWare/CMakeLists.txt b/3rdParty/PKWare/CMakeLists.txt new file mode 100644 index 000000000..99f9783b2 --- /dev/null +++ b/3rdParty/PKWare/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(PKWare STATIC + explode.cpp + implode.cpp) +target_include_directories(PKWare PUBLIC .) diff --git a/3rdParty/SDL_image/CMakeLists.txt b/3rdParty/SDL_image/CMakeLists.txt index 8f4ae7536..f5c18ec11 100644 --- a/3rdParty/SDL_image/CMakeLists.txt +++ b/3rdParty/SDL_image/CMakeLists.txt @@ -1,16 +1,28 @@ -option(DEVILUTIONX_SYSTEM_LIBPNG "Use system-provided libpng" ON) -cmake_dependent_option(DEVILUTIONX_STATIC_LIBPNG "Link static libpng" OFF - "DEVILUTIONX_SYSTEM_LIBPNG AND NOT DIST" ON) +include(dependency_options) -if(DEVILUTIONX_SYSTEM_LIBPNG) +if(NOT DEFINED DEVILUTIONX_SYSTEM_LIBPNG) find_package(PNG QUIET) if(PNG_FOUND) message("-- Found png ${PNG_VERSION_STRING}") else() message("-- Suitable system png package not found, will use png from source") + set(DEVILUTIONX_SYSTEM_LIBPNG OFF) + endif() +elseif(DEVILUTIONX_SYSTEM_LIBPNG) + # In previous versions of DevilutionX, libpng could be built from + # source even if `DEVILUTIONX_SYSTEM_LIBPNG` was true. + # Detect the older CMake cache and update to the new behaviour. + # + # This is a temporary upgrade path that will be removed one week from commit date. + find_package(PNG QUIET) + if(NOT PNG_FOUND) + set(DEVILUTIONX_SYSTEM_LIBPNG OFF CACHE BOOL "" FORCE) endif() endif() -if(NOT PNG_FOUND) +dependency_options("libpng" DEVILUTIONX_SYSTEM_LIBPNG ON DEVILUTIONX_STATIC_LIBPNG) +if(DEVILUTIONX_SYSTEM_LIBPNG) + find_package(PNG REQUIRED) +else() add_subdirectory(../libpng libpng) endif() diff --git a/3rdParty/asio/CMakeLists.txt b/3rdParty/asio/CMakeLists.txt index 321f56ca8..0b9e027e4 100644 --- a/3rdParty/asio/CMakeLists.txt +++ b/3rdParty/asio/CMakeLists.txt @@ -9,3 +9,7 @@ FetchContent_MakeAvailableExcludeFromAll(asio) add_library(asio INTERFACE) target_include_directories(asio INTERFACE ${asio_SOURCE_DIR}/asio/include) + +if(NINTENDO_3DS OR NINTENDO_SWITCH) + include(asio_defs REQUIRED) +endif() diff --git a/CMake/Dependencies.cmake b/CMake/Dependencies.cmake new file mode 100644 index 000000000..7e740e4a4 --- /dev/null +++ b/CMake/Dependencies.cmake @@ -0,0 +1,153 @@ +# Options that control whether to use system dependencies or build them from source, +# and whether to link them statically. +include(dependency_options) + +if(USE_SDL1) + find_package(SDL REQUIRED) + include_directories(${SDL_INCLUDE_DIR}) +else() + dependency_options("SDL2" DEVILUTIONX_SYSTEM_SDL2 ON DEVILUTIONX_STATIC_SDL2) + if(DEVILUTIONX_SYSTEM_SDL2) + find_package(SDL2 REQUIRED) + if(TARGET SDL2::SDL2) + set(SDL2_MAIN SDL2::SDL2main) + elseif(TARGET SDL2::SDL2-static) + # On some distros, such as vitasdk, only the SDL2::SDL2-static target is available. + # Alias to SDL2::SDL2 because some finder scripts may refer to SDL2::SDL2. + if(CMAKE_VERSION VERSION_LESS "3.18") + # Aliasing local targets is not supported on CMake < 3.18, so make it global. + set_target_properties(SDL2::SDL2-static PROPERTIES IMPORTED_GLOBAL TRUE) + endif() + add_library(SDL2::SDL2 ALIAS SDL2::SDL2-static) + set(SDL2_MAIN SDL2::SDL2main) + else() + # Assume an older Debian derivate that comes with an sdl2-config.cmake + # that only defines `SDL2_LIBRARIES` (as -lSDL2) and `SDL2_INCLUDE_DIRS`. + add_library(SDL2_lib INTERFACE) + target_link_libraries(SDL2_lib INTERFACE ${SDL2_LIBRARIES}) + target_include_directories(SDL2_lib INTERFACE ${SDL2_INCLUDE_DIRS}) + # Can't define an INTERFACE target with ::, so alias instead + add_library(SDL2::SDL2 ALIAS SDL2_lib) + endif() + else() + add_subdirectory(3rdParty/SDL2) + set(SDL2_MAIN SDL2::SDL2main) + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/SDL2/CMake") + endif() +endif() + +macro(_find_SDL_image QUIET_OR_REQUIRED) + if(USE_SDL1) + find_package(SDL_image ${QUIET_OR_REQUIRED}) + else() + # vcpkg uses sdl2-image as the package name + find_package(sdl2-image QUIET) + set(SDL_image_FOUND ${sdl2-image_FOUND}) + + if(NOT SDL_image_FOUND) + # Fall back on PkgConfig via FindSDL2_image.cmake + find_package(SDL2_image ${QUIET_OR_REQUIRED}) + set(SDL_image_FOUND ${SDL2_image_FOUND}) + endif() + endif() +endmacro() + +if(NOT DEFINED DEVILUTIONX_SYSTEM_SDL_IMAGE) + _find_SDL_image(QUIET) + if(SDL_image_FOUND) + message("-- Found SDL_image") + else() + message("-- Suitable system SDL_image package not found, will use SDL_image from source") + set(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF) + endif() +elseif(DEVILUTIONX_SYSTEM_SDL_IMAGE) + # In previous versions of DevilutionX, SDL_image could be built from + # source even if `DEVILUTIONX_SYSTEM_SDL_IMAGE` was true. + # Detect the older CMake cache and update to the new behaviour. + # + # This is a temporary upgrade path that will be removed one week from commit date. + _find_SDL_image(QUIET) + if (NOT SDL_image_FOUND) + set(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF CACHE BOOL "" FORCE) + endif() +endif() +dependency_options("SDL_image" DEVILUTIONX_SYSTEM_SDL_IMAGE ON DEVILUTIONX_STATIC_SDL_IMAGE) +if(DEVILUTIONX_SYSTEM_SDL_IMAGE) + _find_SDL_image(REQUIRED) +else() + add_subdirectory(3rdParty/SDL_image) +endif() + +if(NOT NOSOUND) + dependency_options("SDL_audiolib" DEVILUTIONX_SYSTEM_SDL_AUDIOLIB OFF DEVILUTIONX_STATIC_SDL_AUDIOLIB) + if(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB) + find_package(SDL_audiolib REQUIRED) + else() + add_subdirectory(3rdParty/SDL_audiolib) + endif() +endif() + +if(PACKET_ENCRYPTION) + dependency_options("libsodium" DEVILUTIONX_SYSTEM_LIBSODIUM ON DEVILUTIONX_STATIC_LIBSODIUM) + if(DEVILUTIONX_SYSTEM_LIBSODIUM) + set(sodium_USE_STATIC_LIBS ${DEVILUTIONX_STATIC_LIBSODIUM}) + find_package(sodium REQUIRED) + else() + add_subdirectory(3rdParty/libsodium) + endif() +endif() + +if(NOT DEFINED DEVILUTIONX_SYSTEM_LIBFMT) + find_package(fmt 7.0.0 QUIET) + if(fmt_FOUND) + message("-- Found fmt ${fmt_VERSION}") + else() + message("-- Suitable system fmt package not found, will use fmt from source") + set(DEVILUTIONX_SYSTEM_LIBFMT OFF) + endif() +elseif(DEVILUTIONX_SYSTEM_LIBFMT) + # In previous versions of DevilutionX, libfmt could be built from + # source even if `DEVILUTIONX_SYSTEM_LIBFMT` was true. + # Detect the older CMake cache and update to the new behaviour. + # + # This is a temporary upgrade path that will be removed one week from commit date. + find_package(fmt 7.0.0 QUIET) + if (NOT fmt_FOUND) + set(DEVILUTIONX_SYSTEM_LIBFMT OFF CACHE BOOL "" FORCE) + endif() +endif() +dependency_options("libfmt" DEVILUTIONX_SYSTEM_LIBFMT ON DEVILUTIONX_STATIC_LIBFMT) +if(DEVILUTIONX_SYSTEM_LIBFMT) + find_package(fmt 7.0.0 REQUIRED) +else() + add_subdirectory(3rdParty/libfmt) +endif() + +dependency_options("bzip2" DEVILUTIONX_SYSTEM_BZIP2 ON DEVILUTIONX_STATIC_BZIP2) +if(DEVILUTIONX_SYSTEM_BZIP2) + find_package(BZip2 REQUIRED) +else() + add_subdirectory(3rdParty/bzip2) +endif() + +add_subdirectory(3rdParty/libsmackerdec) + +if(WIN32) + add_subdirectory(3rdParty/find_steam_game) +endif() + +add_subdirectory(3rdParty/simpleini) + +add_subdirectory(3rdParty/libmpq) + +add_subdirectory(3rdParty/hoehrmann_utf8) + +add_subdirectory(3rdParty/PKWare) + +if(NOT NONET AND NOT DISABLE_TCP) + add_subdirectory(3rdParty/asio) +endif() + +if(NOT NONET AND NOT DISABLE_ZERO_TIER) + add_subdirectory(3rdParty/libzt) +endif() diff --git a/CMake/Platforms.cmake b/CMake/Platforms.cmake new file mode 100644 index 000000000..842eabd43 --- /dev/null +++ b/CMake/Platforms.cmake @@ -0,0 +1,66 @@ +if(NINTENDO_SWITCH) + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/switch") + include(switch_defs) +endif() + +if(VITA) + # Work around a missing setting in the toolchain file. + # Fix sent upstream: https://github.com/vitasdk/vita-toolchain/pull/182 + set(PKG_CONFIG_EXECUTABLE "$ENV{VITASDK}/bin/arm-vita-eabi-pkg-config") + + include("$ENV{VITASDK}/share/vita.cmake" REQUIRED) + include(vita_defs) +endif() + +set(TARGET_PLATFORM host CACHE STRING "Target platform") +set_property(CACHE TARGET_PLATFORM PROPERTY STRINGS host retrofw rg350 gkd350h cpigamesh) +if(TARGET_PLATFORM STREQUAL "lepus") + include(lepus_defs) +elseif(TARGET_PLATFORM STREQUAL "retrofw") + include(retrofw_defs) +elseif(TARGET_PLATFORM STREQUAL "rg350") + include(rg350_defs) +elseif(TARGET_PLATFORM STREQUAL "gkd350h") + include(gkd350h_defs) +elseif(TARGET_PLATFORM STREQUAL "cpigamesh") + include(cpigamesh_defs) +endif() + +if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD|NetBSD|OpenBSD|DragonFly") + if(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD") + add_definitions(-D_NETBSD_SOURCE) + else() + add_definitions(-D_BSD_SOURCE) + set(UBSAN OFF) + endif() + set(ASAN OFF) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DO_LARGEFILE=0 -Dstat64=stat -Dlstat64=lstat -Dlseek64=lseek -Doff64_t=off_t -Dfstat64=fstat -Dftruncate64=ftruncate") +endif() + +if(WIN32) + set(ASAN OFF) + set(UBSAN OFF) + set(DIST ON) +endif() + +if(HAIKU) + set(ASAN OFF) + set(UBSAN OFF) +endif() + +if(AMIGA) + include(amiga_defs) +endif() + +if(NINTENDO_3DS) + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake/ctr") + include(n3ds_defs) +endif() + +if(ANDROID) + include(android_defs) +endif() + +if(IOS) + include(ios_defs) +endif() diff --git a/CMake/VcPkgManifestFeatures.cmake b/CMake/VcPkgManifestFeatures.cmake new file mode 100644 index 000000000..bc78e039a --- /dev/null +++ b/CMake/VcPkgManifestFeatures.cmake @@ -0,0 +1,15 @@ +# See https://vcpkg.readthedocs.io/en/latest/users/manifests/ +if(USE_SDL1) + list(APPEND VCPKG_MANIFEST_FEATURES "sdl1") +else() + list(APPEND VCPKG_MANIFEST_FEATURES "sdl2") +endif() +if(PACKET_ENCRYPTION) + list(APPEND VCPKG_MANIFEST_FEATURES "encryption") +endif() +if(USE_GETTEXT_FROM_VCPKG) + list(APPEND VCPKG_MANIFEST_FEATURES "translations") +endif() +if(RUN_TESTS) + list(APPEND VCPKG_MANIFEST_FEATURES "tests") +endif() diff --git a/CMake/android_defs.cmake b/CMake/android_defs.cmake index ca42f7239..aae4a8042 100644 --- a/CMake/android_defs.cmake +++ b/CMake/android_defs.cmake @@ -4,6 +4,10 @@ set(VIRTUAL_GAMEPAD ON) # Disable all system dependencies. # All of these will be fetched via FetchContent and linked statically. set(DEVILUTIONX_SYSTEM_SDL2 OFF) + +# Static SDL2 on Android requires Position Independent Code. +set(SDL_STATIC_PIC ON) + set(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF) set(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB OFF) set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) @@ -13,7 +17,7 @@ set(DEVILUTIONX_SYSTEM_BZIP2 OFF) # Package the assets with the APK. set(BUILD_ASSETS_MPQ OFF) -set(DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY "${DevilutionX_SOURCE_DIR}/android-project/app/src/main/assets") +set(DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/android-project/app/src/main/assets") # Disable sanitizers. They're not supported out-of-the-box. set(ASAN OFF) diff --git a/CMake/ctr/asio_defs.cmake b/CMake/ctr/asio_defs.cmake new file mode 100644 index 000000000..e778bdfa7 --- /dev/null +++ b/CMake/ctr/asio_defs.cmake @@ -0,0 +1,6 @@ +target_compile_definitions(asio INTERFACE + ASIO_DISABLE_THREADS=ON + ASIO_HAS_UNISTD_H=ON) + +# Missing headers and declarations provided by DevilutionX +target_include_directories(asio BEFORE INTERFACE ${CMAKE_CURRENT_LIST_DIR}/asio/include) diff --git a/CMake/ctr/n3ds_defs.cmake b/CMake/ctr/n3ds_defs.cmake index b6cd35a5a..4cea9f5c6 100644 --- a/CMake/ctr/n3ds_defs.cmake +++ b/CMake/ctr/n3ds_defs.cmake @@ -11,7 +11,7 @@ set(USE_SDL1 ON) set(PREFILL_PLAYER_NAME ON) #3DS libraries -list(APPEND CMAKE_MODULE_PATH "${DevilutionX_SOURCE_DIR}/CMake/ctr/modules") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake/ctr/modules") find_package(CITRO3D REQUIRED) #additional compilation definitions diff --git a/CMake/dependency_options.cmake b/CMake/dependency_options.cmake new file mode 100644 index 000000000..66295f65d --- /dev/null +++ b/CMake/dependency_options.cmake @@ -0,0 +1,40 @@ +# This function defines 2 options for finding and linking a dependency: +# +# 1. ${SYSTEM_OPTION_NAME}: whether to use the system version of the dependency (default: ${DEFAULT_SYSTEM_VALUE}) +# 2. ${STATIC_OPTION_NAME}: whether to link the dependency statically. +# The default is ON if ${SYSTEM_OPTION_NAME} is OFF or if target does not support shared libraries. +# +# The ${LIB_NAME} argument is a human-readable library name only used in option description strings. +function(dependency_options LIB_NAME SYSTEM_OPTION_NAME DEFAULT_SYSTEM_VALUE STATIC_OPTION_NAME) + option(${SYSTEM_OPTION_NAME} "Use system-provided ${LIB_NAME}" ${DEFAULT_SYSTEM_VALUE}) + get_property(_supports_shared_libs GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) + if(_supports_shared_libs) + if(${SYSTEM_OPTION_NAME}) + set(_static_default OFF) + else() + set(_static_default ON) + + # In previous versions of DevilutionX, the default could be OFF even for non-system libraries. + # Detect the older CMake cache and update to the new behaviour. + # + # This is a temporary upgrade path that will be removed one week from commit date. + set(${STATIC_OPTION_NAME} ON CACHE BOOL "" FORCE) + endif() + option(${STATIC_OPTION_NAME} "Link ${LIB_NAME} statically" ${_static_default}) + else() + set(${STATIC_OPTION_NAME} ON) + set(${STATIC_OPTION_NAME} ON PARENT_SCOPE) + endif() + + if(${STATIC_OPTION_NAME}) + set(_msg_type "static") + else() + set(_msg_type "dynamic") + endif() + if(${SYSTEM_OPTION_NAME}) + set(_msg_source "system library") + else() + set(_msg_source "library from source") + endif() + message("-- 📚 ${LIB_NAME}: ${_msg_type} ${_msg_source}") +endfunction() diff --git a/CMake/ios_defs.cmake b/CMake/ios_defs.cmake index 52af56045..558661583 100644 --- a/CMake/ios_defs.cmake +++ b/CMake/ios_defs.cmake @@ -4,17 +4,11 @@ set(VIRTUAL_GAMEPAD ON) # Disable all system dependencies. # All of these will be fetched via FetchContent and linked statically. set(DEVILUTIONX_SYSTEM_SDL2 OFF) -set(DEVILUTIONX_STATIC_SDL2 ON) set(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF) -set(DEVILUTIONX_STATIC_SDL_IMAGE ON) set(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB OFF) -set(DEVILUTIONX_STATIC_SDL_AUDIOLIB ON) set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) -set(DEVILUTIONX_STATIC_LIBSODIUM ON) set(DEVILUTIONX_SYSTEM_LIBPNG OFF) -set(DEVILUTIONX_STATIC_LIBPNG ON) set(DEVILUTIONX_SYSTEM_LIBFMT OFF) -set(DEVILUTIONX_STATIC_LIBFMT ON) set(DISABLE_ZERO_TIER ON) diff --git a/CMake/platforms/switch/asio_defs.cmake b/CMake/platforms/switch/asio_defs.cmake new file mode 100644 index 000000000..a96bc496a --- /dev/null +++ b/CMake/platforms/switch/asio_defs.cmake @@ -0,0 +1,5 @@ +# Enables a number of header file definitions required by ASIO +target_compile_definitions(asio INTERFACE _DEFAULT_SOURCE=ON) + +# Missing headers and declarations provided by DevilutionX +target_include_directories(asio BEFORE INTERFACE ${CMAKE_CURRENT_LIST_DIR}/asio/include) diff --git a/CMake/switch/asio_defs.cmake b/CMake/switch/asio_defs.cmake index 50451a2d2..a96bc496a 100644 --- a/CMake/switch/asio_defs.cmake +++ b/CMake/switch/asio_defs.cmake @@ -1,5 +1,5 @@ -# Enables a number of header file definitions required by ASIO -target_compile_definitions(asio INTERFACE _DEFAULT_SOURCE=ON) - -# Missing headers and declarations provided by DevilutionX -target_include_directories(asio BEFORE INTERFACE CMake/switch/asio/include) +# Enables a number of header file definitions required by ASIO +target_compile_definitions(asio INTERFACE _DEFAULT_SOURCE=ON) + +# Missing headers and declarations provided by DevilutionX +target_include_directories(asio BEFORE INTERFACE ${CMAKE_CURRENT_LIST_DIR}/asio/include) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c1dfd8de..dbb0733a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,8 +23,10 @@ if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dist") endif() include(CMakeDependentOption) -include(CMake/out_of_tree.cmake) -include(CMake/genex.cmake) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake") +include(out_of_tree) +include(genex) DEBUG_OPTION(ASAN "Enable address sanitizer") DEBUG_OPTION(UBSAN "Enable undefined behaviour sanitizer") @@ -53,6 +55,18 @@ mark_as_advanced(DISABLE_STREAMING_SOUNDS) option(STREAM_ALL_AUDIO "Stream all the audio. For extremely RAM-constrained platforms.") mark_as_advanced(STREAM_ALL_AUDIO) +if(PIE) + set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) +endif() + +if(TSAN) + set(ASAN OFF) +endif() + +if(USE_SDL1) + set(VIRTUAL_GAMEPAD OFF) +endif() + # By default, devilutionx.mpq is built only if smpq is installed. if(NOT DEFINED BUILD_ASSETS_MPQ AND NOT SRC_DIST) find_program(SMPQ smpq) @@ -73,6 +87,43 @@ endif() RELEASE_OPTION(CPACK "Configure CPack") +# These must be included after the options above but before the `project` call. +include(VcPkgManifestFeatures) + +# Set up the `project` early so that properties such as `TARGET_SUPPORTS_SHARED_LIBS` are defined. +if(NOT VERSION_NUM) + include(CMake/git.cmake) + get_git_tag(VERSION_NUM) + if (NOT "${VERSION_NUM}" STREQUAL "") + string(REGEX MATCH "([0-9]+\\.[0-9]+\\.[0-9]+)" VERSION_NUM ${VERSION_NUM} ) + endif() + get_git_commit_hash(GIT_COMMIT_HASH) + if(NOT VERSION_SUFFIX) + set(VERSION_SUFFIX "$<$>:-${GIT_COMMIT_HASH}>") + endif() +endif() +if(VERSION_NUM MATCHES untagged) + project(DevilutionX LANGUAGES C CXX) +else() + project(DevilutionX + VERSION ${VERSION_NUM} + LANGUAGES C CXX) +endif() + +# Platform definitions can override options and we want `cmake_dependent_option` to see the effects, +# so ideally we would include Platforms.cmake before definining the options. +# +# However, `Platforms` require `project` to have been called (to get access to toolchain defs), +# but `project` must be called after `VcPkgManifestFeatures`, and `VcPkgManifestFeatures` need +# to be after the options. +include(Platforms) + +# Recalculate the dependent options after including the Platforms: +if(NONET) + set(DISABLE_TCP ON) + set(DISABLE_ZERO_TIER ON) + set(PACKET_ENCRYPTION OFF) +endif() if(BINARY_RELEASE OR CMAKE_BUILD_TYPE STREQUAL "Release") set(BINARY_RELEASE ON) @@ -88,77 +139,11 @@ if(NIGHTLY_BUILD OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") set(CPACK ON) endif() -if(USE_SDL1) - list(APPEND VCPKG_MANIFEST_FEATURES "sdl1") -else() - list(APPEND VCPKG_MANIFEST_FEATURES "sdl2") -endif() -if(PACKET_ENCRYPTION) - list(APPEND VCPKG_MANIFEST_FEATURES "encryption") -endif() -if(USE_GETTEXT_FROM_VCPKG) - list(APPEND VCPKG_MANIFEST_FEATURES "translations") -endif() -if(RUN_TESTS) - list(APPEND VCPKG_MANIFEST_FEATURES "tests") -endif() - -if(NOT NOSOUND) - option(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB "Use system-provided SDL_audiolib" OFF) - cmake_dependent_option(DEVILUTIONX_STATIC_SDL_AUDIOLIB "Link static SDL_audiolib" OFF - "DEVILUTIONX_SYSTEM_SDL_AUDIOLIB AND NOT DIST" ON) -endif() - -if(PACKET_ENCRYPTION) - option(DEVILUTIONX_SYSTEM_LIBSODIUM "Use system-provided libsodium" ON) - cmake_dependent_option(DEVILUTIONX_STATIC_LIBSODIUM "Link static libsodium" OFF - "DEVILUTIONX_SYSTEM_LIBSODIUM AND NOT DIST" ON) -endif() - -option(DEVILUTIONX_SYSTEM_LIBFMT "Use system-provided libfmt" ON) -cmake_dependent_option(DEVILUTIONX_STATIC_LIBFMT "Link static libfmt" OFF - "DEVILUTIONX_SYSTEM_LIBFMT AND NOT DIST" ON) - -if (NOT USE_SDL1) - option(DEVILUTIONX_SYSTEM_SDL2 "Use system-provided SDL2" ON) - cmake_dependent_option(DEVILUTIONX_STATIC_SDL2 "Link static SDL2" OFF - "DEVILUTIONX_SYSTEM_SDL2 AND NOT DIST" ON) -endif() - -option(DEVILUTIONX_SYSTEM_SDL_IMAGE "Use system-provided SDL_image" ON) -cmake_dependent_option(DEVILUTIONX_STATIC_SDL_IMAGE "Link static SDL_image" OFF - "DEVILUTIONX_SYSTEM_SDL_IMAGE AND NOT DIST" ON) - -option(DEVILUTIONX_SYSTEM_BZIP2 "Use system-provided bzip2" ON) -cmake_dependent_option(DEVILUTIONX_STATIC_BZIP2 "Link static bzip2" OFF - "DEVILUTIONX_SYSTEM_BZIP2 AND NOT DIST" ON) - -if(NOT VERSION_NUM) - include(CMake/git.cmake) - get_git_tag(VERSION_NUM) - if (NOT "${VERSION_NUM}" STREQUAL "") - string(REGEX MATCH "([0-9]+\\.[0-9]+\\.[0-9]+)" VERSION_NUM ${VERSION_NUM} ) - endif() - get_git_commit_hash(GIT_COMMIT_HASH) - if(NOT VERSION_SUFFIX) - set(VERSION_SUFFIX "$<$>:-${GIT_COMMIT_HASH}>") - endif() -endif() - find_program(CCACHE_PROGRAM ccache) if(CCACHE_PROGRAM) set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") endif() -if(VERSION_NUM MATCHES untagged) - project(DevilutionX - LANGUAGES C CXX) -else() - project(DevilutionX - VERSION ${VERSION_NUM} - LANGUAGES C CXX) -endif() - # Not a genexp because CMake doesn't support it # https://gitlab.kitware.com/cmake/cmake/-/issues/20546 if(NOT DISABLE_LTO) @@ -172,12 +157,6 @@ if(NOT DISABLE_LTO) endif() endif() -if(TSAN) - set(ASAN OFF) -endif() - -list(APPEND CMAKE_MODULE_PATH "${DevilutionX_SOURCE_DIR}/CMake") - if(GPERF) if(GPERF_HEAP_FIRST_GAME_ITERATION) set(GPERF_HEAP_MAIN ON) @@ -193,218 +172,18 @@ if(GPERF) endif() endif() -if(NINTENDO_SWITCH) - list(APPEND CMAKE_MODULE_PATH "${DevilutionX_SOURCE_DIR}/CMake/switch") - include(switch_defs) -endif() - -if(VITA) - # Work around a missing setting in the toolchain file. - # Fix sent upstream: https://github.com/vitasdk/vita-toolchain/pull/182 - set(PKG_CONFIG_EXECUTABLE "$ENV{VITASDK}/bin/arm-vita-eabi-pkg-config") - - include("$ENV{VITASDK}/share/vita.cmake" REQUIRED) - include(vita_defs) -endif() - -set(TARGET_PLATFORM host CACHE STRING "Target platform") -set_property(CACHE TARGET_PLATFORM PROPERTY STRINGS host retrofw rg350 gkd350h cpigamesh) -if(TARGET_PLATFORM STREQUAL "lepus") - include(lepus_defs) -elseif(TARGET_PLATFORM STREQUAL "retrofw") - include(retrofw_defs) -elseif(TARGET_PLATFORM STREQUAL "rg350") - include(rg350_defs) -elseif(TARGET_PLATFORM STREQUAL "gkd350h") - include(gkd350h_defs) -elseif(TARGET_PLATFORM STREQUAL "cpigamesh") - include(cpigamesh_defs) -endif() - -if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD|NetBSD|OpenBSD|DragonFly") - if(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD") - add_definitions(-D_NETBSD_SOURCE) - else() - add_definitions(-D_BSD_SOURCE) - set(UBSAN OFF) - endif() - set(ASAN OFF) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DO_LARGEFILE=0 -Dstat64=stat -Dlstat64=lstat -Dlseek64=lseek -Doff64_t=off_t -Dfstat64=fstat -Dftruncate64=ftruncate") -endif() - -if(WIN32) - set(ASAN OFF) - set(UBSAN OFF) - set(DIST ON) -endif() - -if(HAIKU) - set(ASAN OFF) - set(UBSAN OFF) -endif() - -if(AMIGA) - include(amiga_defs) -endif() - -if(NINTENDO_3DS) - list(APPEND CMAKE_MODULE_PATH "${DevilutionX_SOURCE_DIR}/CMake/ctr") - include(n3ds_defs) -endif() - -if(ANDROID) - include(android_defs) -endif() - -if(IOS) - include(ios_defs) -endif() - -if(PIE) - set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) -endif() - -if(USE_SDL1) - set(VIRTUAL_GAMEPAD OFF) -endif() - -if(NONET) - # Fix dependent options if platform defs disable network - set(DISABLE_TCP ON) - set(DISABLE_ZERO_TIER ON) - set(PACKET_ENCRYPTION OFF) -endif() - set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # for clang-tidy set(CMAKE_THREAD_PREFER_PTHREAD ON) set(THREADS_PREFER_PTHREAD_FLAG ON) - if(NOT NINTENDO_3DS) find_package(Threads REQUIRED) endif() -if(PACKET_ENCRYPTION) - if(DEVILUTIONX_SYSTEM_LIBSODIUM) - set(sodium_USE_STATIC_LIBS ${DEVILUTIONX_STATIC_LIBSODIUM}) - find_package(sodium REQUIRED) - else() - add_subdirectory(3rdParty/libsodium) - endif() -endif() - -if(DEVILUTIONX_SYSTEM_LIBFMT) - find_package(fmt 7.0.0 QUIET) - if(fmt_FOUND) - message("-- Found fmt ${fmt_VERSION}") - else() - message("-- Suitable system fmt package not found, will use fmt from source") - endif() -endif() -if(NOT fmt_FOUND) - add_subdirectory(3rdParty/libfmt) -endif() - -if(NOT DEVILUTIONX_SYSTEM_BZIP2) - add_subdirectory(3rdParty/bzip2) -endif() - -if(USE_SDL1) - find_package(SDL REQUIRED) - include_directories(${SDL_INCLUDE_DIR}) -else() - if(DEVILUTIONX_SYSTEM_SDL2) - find_package(SDL2 REQUIRED) - if(TARGET SDL2::SDL2) - set(SDL2_MAIN SDL2::SDL2main) - elseif(TARGET SDL2::SDL2-static) - # On some distros, such as vitasdk, only the SDL2::SDL2-static target is available. - # Alias to SDL2::SDL2 because some finder scripts may refer to SDL2::SDL2. - if(CMAKE_VERSION VERSION_LESS "3.18") - # Aliasing local targets is not supported on CMake < 3.18, so make it global. - set_target_properties(SDL2::SDL2-static PROPERTIES IMPORTED_GLOBAL TRUE) - endif() - add_library(SDL2::SDL2 ALIAS SDL2::SDL2-static) - set(SDL2_MAIN SDL2::SDL2main) - else() - # Assume an older Debian derivate that comes with an sdl2-config.cmake - # that only defines `SDL2_LIBRARIES` (as -lSDL2) and `SDL2_INCLUDE_DIRS`. - add_library(SDL2_lib INTERFACE) - target_link_libraries(SDL2_lib INTERFACE ${SDL2_LIBRARIES}) - target_include_directories(SDL2_lib INTERFACE ${SDL2_INCLUDE_DIRS}) - # Can't define an INTERFACE target with ::, so alias instead - add_library(SDL2::SDL2 ALIAS SDL2_lib) - endif() - else() - add_subdirectory(3rdParty/SDL2) - set(SDL2_MAIN SDL2::SDL2main) - list(APPEND CMAKE_MODULE_PATH "${DevilutionX_SOURCE_DIR}/3rdParty/SDL2/CMake") - endif() -endif() - -if(NOT NONET AND NOT DISABLE_TCP) - add_subdirectory(3rdParty/asio) - if(NINTENDO_3DS) - target_compile_definitions(asio INTERFACE - ASIO_DISABLE_THREADS=ON - ASIO_HAS_UNISTD_H=ON) - - target_include_directories(asio BEFORE INTERFACE CMake/ctr/asio/include) - elseif(NINTENDO_SWITCH) - include(asio_defs) - endif() -endif() - -if(DEVILUTIONX_SYSTEM_SDL_IMAGE) - if(USE_SDL1) - find_package(SDL_image QUIET) - else() - # vcpkg uses sdl2-image as the package name - find_package(sdl2-image QUIET) - set(SDL_image_FOUND ${sdl2-image_FOUND}) - - if(NOT SDL_image_FOUND) - # Fall back on PkgConfig via FindSDL2_image.cmake - find_package(SDL2_image QUIET) - set(SDL_image_FOUND ${SDL2_image_FOUND}) - endif() - endif() - if(SDL_image_FOUND) - message("-- Found SDL_image") - else() - message("-- Suitable system SDL_image package not found, will use SDL_image from source") - endif() -endif() -if(NOT SDL_image_FOUND) - add_subdirectory(3rdParty/SDL_image) -endif() - -if(NOT NOSOUND) - if(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB) - find_package(SDL_audiolib REQUIRED) - else() - add_subdirectory(3rdParty/SDL_audiolib) - endif() -endif() - -add_subdirectory(3rdParty/libsmackerdec) - -if(WIN32) -add_subdirectory(3rdParty/find_steam_game) -endif() - -add_subdirectory(3rdParty/simpleini) - -add_subdirectory(3rdParty/libmpq) - -add_subdirectory(3rdParty/hoehrmann_utf8) - -add_library(PKWare STATIC - 3rdParty/PKWare/explode.cpp - 3rdParty/PKWare/implode.cpp) -target_include_directories(PKWare PUBLIC 3rdParty/PKWare) +# Dependencies must be included after Platforms. +include(Dependencies) set(libdevilutionx_SRCS Source/appfat.cpp @@ -665,7 +444,7 @@ if(RUN_TESTS) endif() add_library(libdevilutionx OBJECT ${libdevilutionx_SRCS}) -if (ANDROID) +if(ANDROID) add_library(${BIN_TARGET} SHARED Source/main.cpp) else() add_executable(${BIN_TARGET} @@ -739,7 +518,7 @@ find_package(Gettext) if (Gettext_FOUND) file(MAKE_DIRECTORY "${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}") foreach(lang ${devilutionx_langs}) - set(_po_file "${DevilutionX_SOURCE_DIR}/Translations/${lang}.po") + set(_po_file "${CMAKE_CURRENT_SOURCE_DIR}/Translations/${lang}.po") set(_gmo_file "${DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY}/${lang}.gmo") set(_lang_target devilutionx_lang_${lang}) add_custom_command( @@ -1087,6 +866,14 @@ if(NOT NOSOUND) target_link_libraries(libdevilutionx PUBLIC SDL_audiolib) endif() +if(NOT NONET AND NOT DISABLE_ZERO_TIER) + if(NOT ANDROID) + target_link_libraries(libdevilutionx PUBLIC zt-static) + else() + target_link_libraries(libdevilutionx PUBLIC zt-shared) + endif() +endif() + if(AMIGA) target_link_libraries(libdevilutionx PUBLIC ${ZLIB_LIBRARY}) @@ -1391,12 +1178,3 @@ if(CPACK AND (APPLE OR BUILD_ASSETS_MPQ OR SRC_DIST)) set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) include(CPack) endif() - -if(NOT NONET AND NOT DISABLE_ZERO_TIER) - add_subdirectory(3rdParty/libzt) - if(NOT ANDROID) - target_link_libraries(libdevilutionx PUBLIC zt-static) - else() - target_link_libraries(libdevilutionx PUBLIC zt-shared) - endif() -endif() diff --git a/Source/encrypt.cpp b/Source/encrypt.cpp index 533ed5e4d..3c167ea34 100644 --- a/Source/encrypt.cpp +++ b/Source/encrypt.cpp @@ -9,9 +9,9 @@ #include #include +#include #include "encrypt.h" -#include "pkware.h" namespace devilution {