diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..ec091dcf59 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,133 @@ +cmake_minimum_required(VERSION 3.25.1...4.0.0) + +project(0ad VERSION 0.29.0) + +# Available Options +option(android "Use non-working Android cross-compiling mode") +option(coverage "Enable code coverage data collection (GCC only)") +option(gles "Use non-working OpenGL ES 2.0 mode") +option(jenkins-tests "Configure CxxTest to use the XmlPrinter runner which produces Jenkins-compatible output") +option(minimal-flags "Only set compiler/linker flags that are really needed. Has no effect on Windows builds") +option(sanitize-address "Enable ASAN if available") +option(sanitize-thread "Enable TSAN if available") +option(sanitize-undefined-behaviour "Enable UBSAN if available") +option(with-system-cxxtest "Search standard paths for cxxtest, instead of using bundled copy") +option(with-lto "Enable Link Time Optimization (LTO)") +option(with-system-mozjs "Search standard paths for libmozjs115, instead of using bundled copy") +option(with-system-nvtt "Search standard paths for nvidia-texture-tools library, instead of using bundled copy") +option(with-valgrind "Enable Valgrind support (non-Windows only)") +option(without-audio "Disable use of OpenAL/Ogg/Vorbis APIs") +option(without-atlas "Disable Atlas scenario/map editor and ActorEditor") +option(without-dap-interface "Disable Dap interface project") +option(without-lobby "Disable the use of gloox and the multiplayer lobby") +option(without-miniupnpc "Disable use of miniupnpc for port forwarding") +option(without-nvtt "Disable use of NVTT") +option(without-pch "Disable generation and usage of precompiled headers") +option(without-tests "Disable generation of test projects") + +# OS X specific options +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + option(macosx-version-min "Set minimum required version of the OS X API, the build will possibly fail if an older SDK is used, while newer API functions will be weakly linked (i.e. resolved at runtime)") + option(sysroot "Set compiler system root path, used for building against a non-system SDK. For example /usr/local becomes SYSROOT/user/local") +endif() + +# Set the default build type if not specified (Only for single configuration generators) +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +# Install options +set(bindir "" CACHE STRING "Directory for executables (typically '/usr/games'); default is to be relocatable") +set(datadir "" CACHE STRING "Directory for data files (typically '/usr/share/games/0ad'); default is ../data/ relative to executable") +set(libdir "" CACHE STRING "Directory for libraries (typically '/usr/lib/games/0ad'); default is ./ relative to executable") + +# +++++++++++++++++++++ General Setup ++++++++++++++++++++ + +# Default Cache variables +# Append to the Modulepath. Allows to make custom cmake modules. +list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +# Set default Arch +set(ARCH "x86" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64") +set(MACOS_ARCH "x86_64" CACHE STRING "Mac OS specific Architecture. Possible values are arm64 and x86_64") +option(link_execinfo "") +option(mozjs_is_debug_build "") + +# Detect CPU architecture (simplistic). The user can target an architecture by setting '-DARCH=arch', but the game still selects some know value. +if(android) + set(ARCH "arm" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64" FORCE) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + if(NOT CMAKE_VS_PLATFORM_NAME) + if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64" OR ENV{PROCESSOR_ARCHITEW6432} STREQUAL "AMD64") + set(ARCH "amd64" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64" FORCE) + endif() + else() + if(CMAKE_VS_PLATFORM_NAME MATCHES "x64") + set(ARCH "amd64" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64" FORCE) + endif() + endif() +else() + # could be parsed from the same command as premakes version + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "(x86_64|x64)") + set(MACOS_ARCH "x86_64" CACHE STRING "Mac OS specific Architecture. Possible values are arm64 and x86_64" FORCE) + elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64") + set(MACOS_ARCH "arm64" CACHE STRING "Mac OS specific Architecture. Possible values are arm64 and x86_64" FORCE) + endif() + elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "(x86_64|x64)") + set(ARCH "amd64" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64" FORCE) + elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "(aarch64|aarch64_be)") + set(ARCH "aarch64" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64" FORCE) + else() + message(WARNING "Cannot determine architecture from GCC, assuming x86") + endif() +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + if(ARCH MATCHES "amd64") + set(0AD_EXT_LIBDIR ${CMAKE_SOURCE_DIR}/libraries/win64 CACHE STRING "Extern libraries directory of 0ad. Can be referenced in other CMakeLists.txt files.") + else() + set(0AD_EXT_LIBDIR ${CMAKE_SOURCE_DIR}/libraries/win32 CACHE STRING "Extern libraries directory of 0ad. Can be referenced in other CMakeLists.txt files.") + endif() +endif() + +# On Windows check if wxWidgets is available, if not disable atlas and emit warning. This is because there are currently no prebuilt binaries provided. +if(NOT without-atlas AND CMAKE_SYSTEM_NAME STREQUAL "Windows") + if(NOT EXISTS "${0AD_EXT_LIBDIR}/wxwidgets/include/wx/wx.h") + message(STATUS "wxWidgets not found, disabling atlas") + set(without-atlas ON CACHE BOOL "Disable Atlas scenario/map editor and ActorEditor" FORCE) + endif() +endif() + +# Test whether we need to link libexecinfo. This is mostly the case on musl systems, as well as on BSD systems : only glibc provides the +# backtrace symbols we require in the libc, for other libcs we use the libexecinfo library. +if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + set(link_execinfo ON CACHE BOOL "" FORCE) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + execute_process( + COMMAND ${CMAKE_C_COMPILER} "${CMAKE_SOURCE_DIR}/build/premake/tests/execinfo.c -o /dev/null" + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + RESULT_VARIABLE link_errorCode + OUTPUT_QUIET + ERROR_QUIET + ) + if(NOT link_errorCode EQUAL 0) + set(link_execinfo ON CACHE BOOL "" FORCE) + endif() +endif() + +# Test whether system mozjs is built with --enable-debug. The pc file doesn't specify the required -DDEBUG needed in that case +if(with-system-mozjs) + execute_process( + COMMAND ${CMAKE_C_COMPILER} " $(pkg-config mozjs-128 --cflags) ${CMAKE_SOURCE_DIR}/build/premake/tests/mozdebug.c -o /dev/null" + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + RESULT_VARIABLE link_errorCode + OUTPUT_QUIET + ERROR_QUIET + ) + if(NOT link_errorCode EQUAL 0) + set(mozjs_is_debug_build ON CACHE BOOL "" FORCE) + endif() +endif() + +# Include the BuildFlags target only once after all setup is finished +include(0ad-BuildFlags) diff --git a/cmake/0ad-BuildFlags.cmake b/cmake/0ad-BuildFlags.cmake new file mode 100644 index 0000000000..f28120ec16 --- /dev/null +++ b/cmake/0ad-BuildFlags.cmake @@ -0,0 +1,303 @@ +cmake_minimum_required(VERSION 3.25.1...4.0.0) + +# Add an interface library with common set of build/linker flags and definitions. + +set(BUILD_FLAGS_TARGET BuildFlags) +add_library(${BUILD_FLAGS_TARGET} INTERFACE) + +# Enable and require C++20 standard. +target_compile_features(${BUILD_FLAGS_TARGET} INTERFACE cxx_std_20) +set_target_properties(${BUILD_FLAGS_TARGET} + PROPERTIES + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF +) + +# Settings for build types +if(with-lto) + include(CheckIPOSupported) + check_ipo_supported(RESULT lto_supported OUTPUT lto_supported_error) + if(lto_supported) + set_target_properties(${BUILD_FLAGS_TARGET} + PROPERTIES + INTERPROCEDURAL_OPTIMIZATION TRUE + ) + else() + message(WARNING "IPO / LTO not supported: <${lto_supported_error}>") + endif() +endif() +target_compile_definitions(${BUILD_FLAGS_TARGET} + INTERFACE + $<$:NDEBUG> + $<$:CONFIG_FINAL=1> + $<$:DEBUG> +) + +if(sanitize-address) + target_compile_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=address) + target_link_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=address) +endif() +if(sanitize-thread) + target_compile_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=thread) + target_link_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=thread) +endif() +if(sanitize-undefined-behaviour) + target_compile_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=undefined) + target_link_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=undefined) +endif() + +if(mozjs_is_debug_build) + target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE DEBUG) +endif() + +if(gles) + target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE CONFIG2_GLES=1) +endif() + +if(without-audio) + target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE CONFIG2_AUDIO=0) +endif() + +if(without-nvtt) + target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE CONFIG2_NVTT=0) +endif() + +if(without-lobby) + target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE CONFIG2_LOBBY=0) +endif() + +if(without-miniupnpc) + target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE CONFIG2_MINIUPNPC=0) +endif() + +if(without-dap-interface) + target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE CONFIG2_DAP_INTERFACE=0) +endif() + +# hide warnings caused by library includes (Nothing to do for gcc/clang) +target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + $<$:/external:W0> +) + +# various platform-specific build flags +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + $<$:/MP> + # Since KB4088875 Windows 7 has a soft requirement for SSE2. + # Windows 8+ and Firefox ESR52 make it hard requirement. + # Finally since VS2012 it's enabled implicitely when not set. + $<$:/arch:SSE2> + # use native wchar_t type (not typedef to unsigned short) + $<$:/Zc:wchar_t> + $<$:/utf-8> + # SpiderMonkey only supports building with MSVC on a best-effort basis, + # and the traditional MSVC preprocessor is incompatible with some headers. + # Use the modern, standard-compliant MSVC preprocessor instead. + $<$:/Zc:preprocessor> + # enable most of the standard warnings + $<$:/W4> + # FIXME: conversion warnings, should add -Wconversion to gcc and clang flags as well + $<$:/wd4267> + $<$,$>:/O2> + ) + + # disable LNK4221 warning, to avoid spending energy ordering projects in linker invocations + target_link_options(${BUILD_FLAGS_TARGET} + INTERFACE + "/ignore:4221" + ) + + # mozilla 115 linked list destructor in debug build + target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE "__PRETTY_FUNCTION__=__FUNCSIG__") + + # disable Windows debug heap, since it makes malloc/free hugely slower when running inside a debugger + set_target_properties(${BUILD_FLAGS_TARGET} + PROPERTIES + VS_DEBUGGER_ENVIRONMENT "_NO_DEBUG_HEAP=1" + ) + +elseif(UNIX) + if(NOT minimal-flags) + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + # most of the standard warnings + $<$:-Wall> + $<$:-Wextra> + $<$:-Wpedantic> + # $<$:-Wconversion> # FIXME: should seriously consider fixing so this warning can be enabled. + # add some other useful warnings that need to be enabled explicitly + $<$:-Wunused-parameter> # (useful for finding some multiply-included header files) + $<$:-Wredundant-decls> + # $<$:-Wformat=2> # (useful sometimes, but a bit noisy, so skip it by default) + # $<$:-Wcast-qual> # (useful for checking const-correctness, but a bit noisy, so skip it by default) + $<$:-Wnon-virtual-dtor> # (sometimes noisy but finds real bugs) + $<$:-Wundef> # (useful for finding macro name typos) + # disable some warnings that currently trigger + $<$:-Wno-missing-field-initializers> # (this is common in external headers we can't fix) + $<$:-Wno-reorder> # order of initialization list in constructors (lots of noise) + # enable security features (stack checking etc) that shouldn't have a significant effect on performance and can catch bugs + $<$:-fstack-protector-strong> + # always enable strict aliasing (useful in debug builds because of the warnings) + $<$:-fstrict-aliasing> + # don't omit frame pointers (for now), because performance will be impacted negatively by the way this breaks profilers more than it will be impacted positively by the optimisation + $<$:-fno-omit-frame-pointer> + # FORTIFY_SOURCE needs optimizations to be enabled + $<$,$>:-U_FORTIFY_SOURCE> # (avoid redefinition warning if already defined) + $<$,$>:-D_FORTIFY_SOURCE=2> + ) + target_link_options(${BUILD_FLAGS_TARGET} + INTERFACE + $<$:-multiply_defined> + $<$:suppress> + ) + + if(NOT without-pch) + # do something (?) so that ccache can handle compilation with PCH enabled (ccache 3.1+ also requires CCACHE_SLOPPINESS=time_macros for this to work) + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + $<$:-fpch-preprocess> + ) + endif() + + if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_NAME MATCHES ".*BSD*") + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + $<$:-fPIC> + ) + target_link_options(${BUILD_FLAGS_TARGET} + INTERFACE + "-Wl,--no-undefined" + "-Wl,--as-needed" + "-Wl,-z,relro" + ) + endif() + + if(ARCH STREQUAL "x86") + # To support intrinsics like __sync_bool_compare_and_swap on x86 we need to set -march to something that supports them (i686). + # We use pentium3 to also enable other features like mmx and sse, while tuning for generic to have good performance on every supported CPU. + # Note that all these features are already supported on amd64. + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + $<$:-march=pentium3> + $<$:-mtune=generic> + # This allows x86 operating systems to handle the 2GB+ INTERFACE mod. + $<$:-mtune=generic-D_FILE_OFFSET_BITS=64> + ) + endif() + + if(ARCH STREQUAL "arm") + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + # disable warnings about va_list ABI change and use compile-time flags for futher configuration. + $<$:-Wno-psabi> + # Android uses softfp, so we should too. + $<$,$>:-mfloat-abi=softfp> + ) + endif() + endif() + + if(coverage) + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + $<$:-fprofile-arcs> + $<$:-ftest-coverage> + ) + target_link_libraries(${BUILD_FLAGS_TARGET} gcov) + endif() + + # MacOS 10.12 only supports intel processors with SSE 4.1, so enable that. + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND ARCH STREQUAL "amd64") + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + "-msse4.1" + ) + endif() + + # Check if SDK path should be used + if(sysroot) + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + "-isysroot ${sysroot}" + ) + target_link_options(${BUILD_FLAGS_TARGET} + INTERFACE + "-Wl,-syslibroot, ${sysroot}" + ) + endif() + + # On OS X, sometimes we need to specify the minimum API version to use + if(macosx-version-min) + # clang and llvm-gcc look at mmacosx-version-min to determine link target and CRT version, and use it to set the macosx_version_min linker flag + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + "-mmacosx-version-min=${macosx-version-min}" + ) + target_link_options(${BUILD_FLAGS_TARGET} + INTERFACE + "-mmacosx-version-min=${macosx-version-min}" + ) + endif() + + # Only libc++ is supported on MacOS + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + -stdlib=libc++ + ) + target_link_options(${BUILD_FLAGS_TARGET} + INTERFACE + -stdlib=libc++ + ) + endif() + + # Hide symbols in dynamic shared objects by default, for efficiency and for equivalence with Windows + # - they should be exported explicitly with __attribute__ ((visibility ("default"))) + target_compile_options(${BUILD_FLAGS_TARGET} + INTERFACE + -fvisibility=hidden + ) + + if(bindir) + target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE INSTALLED_BINDIR=${bindir}) + endif() + + if(datadir) + target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE INSTALLED_DATADIR=${datadir}) + endif() + + if(libdir) + target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE INSTALLED_LIBDIR=${libdir}) + endif() + + if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME MATCHES ".*BSD*") + if(libdir) + # To use our local shared libraries, they need to be found in the runtime dynamic linker path. Add their path to -rpath. + target_link_options(${BUILD_FLAGS_TARGET} + INTERFACE + -Wl,-rpath,${libdir} + ) + else() + # On FreeBSD we need to allow use of $ORIGIN + if(CMAKE_SYSTEM_NAME MATCHES ".*BSD*") + target_link_options(${BUILD_FLAGS_TARGET} + INTERFACE + -Wl,-z,origin + ) + endif() + # Adding the executable path and taking care of correct escaping + if(NOT CMAKE_GENERATOR STREQUAL "Ninja") # Checks if any Makefile generator is selected + target_link_options(${BUILD_FLAGS_TARGET} + INTERFACE + -Wl,-rpath,'$$ORIGIN' + ) + elseif(CMAKE_EXTRA_GENERATOR STREQUAL "CodeBlocks") + target_link_options(${BUILD_FLAGS_TARGET} + INTERFACE + -Wl,-R\\\\$$$ORIGIN + ) + endif() + endif() + endif() +endif() diff --git a/cmake/0ad-Functions.cmake b/cmake/0ad-Functions.cmake new file mode 100644 index 0000000000..70b5f27316 --- /dev/null +++ b/cmake/0ad-Functions.cmake @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.25.1...4.0.0) + +# 0AD Specific Functions \ No newline at end of file