cmake_minimum_required(VERSION 3.16) include(CheckIPOSupported) include(CPM.cmake) project(pkmnLib) # We like new stuff, so set the c++ standard to c++20. set(CMAKE_CXX_STANDARD 20) set(CMAKE_POSITION_INDEPENDENT_CODE ON) option(WINDOWS "Whether the build target is Windows or not." OFF) option(SHARED "Whether we should build a shared library, instead of a static one." ON) option(PKMNLIB_TESTS "Whether the test executable should be build as well." OFF) option(SANITIZER_TESTS "Whether the test executable should be built using address sanitizer." ON) option(STATICC "Whether gcc and stdc++ should be linked statically to the library." OFF) option(ANGELSCRIPT_DEBUGGER "Include the angelscript debug server in the build." OFF) set(SCRIPT_PROVIDER "angelscript" CACHE STRING "Which script provider to use.") set(LEVEL_SIZE "8" CACHE STRING "Number of bits to store the level as. Can be 8") if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") add_compile_options(-fconcepts) endif () if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") if (EXISTS /usr/bin/mold) message(STATUS "Mold found, using as linker") add_link_options(-fuse-ld=mold -flto) else() add_link_options(-fuse-ld=lld) endif() # Only warn for unknown sanitizers. This error is not major enough to error on. add_compile_options(-Wno-error=unknown-sanitizers) # Ignore pedantic nullability extension warning, as we only use this for clang specifically add_compile_options(-Wno-nullability-extension) # As far as I can tell this is an invalid pedantic warning since C++ 20. Empty variadic macro arguments is completely legal. add_compile_options(-Wno-gnu-zero-variadic-macro-arguments) endif () execute_process(COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/include) CPMAddPackage( NAME Arbutils GIT_REPOSITORY https://git.p-epsilon.com/Deukhoofd/Arbutils.git GIT_TAG master OPTIONS "SHARED=${SHARED}" "WINDOWS=${WINDOWS}" "STATICC=${STATICC}" ) execute_process(COMMAND ln -sf ${Arbutils_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/include/Arbutils) CPMAddPackage( NAME CreatureLib GIT_REPOSITORY https://git.p-epsilon.com/Deukhoofd/CreatureLib.git GIT_TAG master OPTIONS "SHARED=${SHARED}" "WINDOWS=${WINDOWS}" "STATICC=${STATICC}" ) execute_process(COMMAND ln -sf ${CreatureLib_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/include/CreatureLib) if (SCRIPT_PROVIDER STREQUAL "angelscript") CPMAddPackage( NAME Angelscript GIT_REPOSITORY https://git.p-epsilon.com/Deukhoofd/Angelscript.git GIT_TAG master DOWNLOAD_ONLY YES ) if (Angelscript_ADDED) execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . -B ${Angelscript_BINARY_DIR} -DBUILD_SHARED_LIBS=${SHARED} -DMSVC=${WINDOWS} -DLINK_STD_STATICALLY=${STATICC} -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON RESULT_VARIABLE result WORKING_DIRECTORY ${Angelscript_SOURCE_DIR}/angelscript/projects/cmake) execute_process(COMMAND ${CMAKE_COMMAND} --build ${Angelscript_BINARY_DIR} RESULT_VARIABLE result WORKING_DIRECTORY ${Angelscript_SOURCE_DIR}/angelscript/projects/cmake) endif () include_directories(${Angelscript_SOURCE_DIR}/angelscript/include) include_directories(${Angelscript_SOURCE_DIR}/add_on) elseif (SCRIPT_PROVIDER STREQUAL "wasm") message(STATUS "Installing wasmer") execute_process(COMMAND bash -c "curl https://get.wasmer.io -sSfL | WASMER_INSTALL_LOG=0 sh") include_directories($ENV{WASMER_DIR}/include) endif () include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) if (WINDOWS) SET(CMAKE_SYSTEM_NAME Windows) ADD_DEFINITIONS(-D WINDOWS=1) endif (WINDOWS) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # The angelscript libraries break these warnings extensively. Turn them off. add_compile_options(-Wno-error=cast-function-type -Wno-cast-function-type) add_compile_options(-Wno-error=type-limits -Wno-type-limits) endif () message(STATUS "Using: \t C ${CMAKE_C_COMPILER} \t C++ ${CMAKE_CXX_COMPILER} \t CXX ABI ${CMAKE_CXX_COMPILER_ABI} \t C++ Version ${CMAKE_CXX_STANDARD}") if (LEVEL_SIZE STREQUAL "8") add_definitions(-DLEVEL_U8) message(STATUS "Using level size of 8") elseif (LEVEL_SIZE STREQUAL "16") add_definitions(-DLEVEL_U16) message(STATUS "Using level size of 16") elseif (LEVEL_SIZE STREQUAL "32") add_definitions(-DLEVEL_U32) message(STATUS "Using level size of 32") elseif (LEVEL_SIZE STREQUAL "64") add_definitions(-DLEVEL_U64) message(STATUS "Using level size of 64") else () message(FATAL_ERROR, "Invalid level size was given.") endif () if (CMAKE_BUILD_TYPE MATCHES Release AND NOT WINDOWS) # Include debug symbols in all linux builds message(STATUS "Including debug symbols") add_compile_options(-g -gline-tables-only) endif () # Set whether we want a static or shared library. set(LIBTYPE STATIC) if (SHARED) set(LIBTYPE SHARED) endif (SHARED) SET(FILE_SOURCE "src/Battling/*.cpp" "src/Battling/*.hpp" "src/Library/*.cpp" "src/Library/*.hpp" "CInterface/Core.*" "CInterface/Library/*.cpp" "CInterface/Library/*.hpp" "CInterface/Battling/*.cpp" "CInterface/Battling/*.hpp" ) if (SCRIPT_PROVIDER STREQUAL "angelscript") SET(FILE_SOURCE ${FILE_SOURCE} "src/ScriptResolving/AngelScript/*.cpp" "src/ScriptResolving/AngelScript/*.hpp" "${Angelscript_SOURCE_DIR}/add_on/scriptbuilder/scriptbuilder.cpp" "${Angelscript_SOURCE_DIR}/add_on/scripthelper/scripthelper.cpp" "${Angelscript_SOURCE_DIR}/add_on/scripthandle/scripthandle.cpp" "${Angelscript_SOURCE_DIR}/add_on/scriptstdstring/scriptstdstring.cpp" "${Angelscript_SOURCE_DIR}/add_on/scriptdictionary/scriptdictionary.cpp" "${Angelscript_SOURCE_DIR}/add_on/scriptarray/scriptarray.cpp" "${Angelscript_SOURCE_DIR}/add_on/scriptmath/scriptmath.cpp" "CInterface/AngelScript/*.cpp" "CInterface/AngelScript/*.hpp" ) if (ANGELSCRIPT_DEBUGGER) CPMAddPackage( NAME AngelscriptDebugger GIT_REPOSITORY https://git.p-epsilon.com/Deukhoofd/AngelscriptDebuggerServer.git GIT_TAG master ) execute_process(COMMAND ln -sf ${AngelscriptDebugger_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/include/AngelscriptDebuggerServer) set(_LINKS ${_LINKS} AngelscriptDebugger) set(_TESTLINKS ${_TESTLINKS} AngelscriptDebugger) endif () ADD_DEFINITIONS(-D AS_USE_ACCESSORS=1) elseif(SCRIPT_PROVIDER STREQUAL "wasm") SET(FILE_SOURCE ${FILE_SOURCE} "src/ScriptResolving/WASM/*.cpp" "src/ScriptResolving/WASM/*.hpp") # FIXME: Add C Interface endif () file(GLOB_RECURSE CORE_SRC_FILES ${FILE_SOURCE}) add_library(pkmnLib ${LIBTYPE} ${CORE_SRC_FILES}) # Enable all warnings, and make them error when occurring. target_compile_options(pkmnLib PRIVATE -Wall -Wextra -Werror -pedantic-errors) # If interprocedural optimization is available, apply it check_ipo_supported(RESULT IPO_SUPPORTED) if (IPO_SUPPORTED) message(STATUS "IPO / LTO enabled") set_property(TARGET pkmnLib PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) endif () SET(_LINKS ${_LINKS} CreatureLib Arbutils) SET(_TESTLINKS ${_TESTLINKS} pkmnLib CreatureLib Arbutils) if (SCRIPT_PROVIDER STREQUAL "angelscript") message(STATUS "Using Angelscript as script provider.") target_link_directories(pkmnLib PUBLIC ${Angelscript_BINARY_DIR}) ADD_DEFINITIONS(-D ANGELSCRIPT=1) SET(_LINKS ${_LINKS} angelscript) SET(_TESTLINKS ${_TESTLINKS} angelscript) if (ANGELSCRIPT_DEBUGGER) ADD_DEFINITIONS(-D ANGELSCRIPT_DEBUGGER=1) endif () elseif (SCRIPT_PROVIDER STREQUAL "wasm") message(STATUS "Using WebAssembly as script provider.") target_link_directories(pkmnLib PUBLIC $ENV{WASMER_DIR}/lib) ADD_DEFINITIONS(-D WASM=1) SET(_LINKS ${_LINKS} -Wl,-Bstatic wasmer -Wl,-Bdynamic) SET(_TESTLINKS ${_TESTLINKS} -Wl,-Bstatic wasmer -Wl,-Bdynamic) endif () # If we are building for Windows we need to set some specific variables. if (WINDOWS) MESSAGE(WARNING, "Using Windows Build.") # Add a definition for the compiler, so we can use it in C++ as well. ADD_DEFINITIONS(-D WINDOWS=1) # -m64: Build a 64 bit library add_compile_options(-m64) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-allow-multiple-definition") if (SHARED) set_target_properties(pkmnLib PROPERTIES SUFFIX ".dll") endif (SHARED) set(_LINKS ${_LINKS} -Wl,-Bstatic -lws2_32 -lstdc++ -lpthread -Wl,-Bdynamic) set(_TESTLINKS ${_TESTLINKS} -Wl,-Bstatic -lws2_32 -lstdc++ -lpthread -Wl,-Bdynamic) endif (WINDOWS) if (STATICC) set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed") message(STATUS "Linking C library statically") set(_LINKS ${_LINKS} -static-libstdc++) SET(_TESTLINKS ${_TESTLINKS}) endif () target_link_libraries(pkmnLib PUBLIC ${_LINKS}) if (PKMNLIB_TESTS) CPMAddPackage( NAME doctest GITHUB_REPOSITORY doctest/doctest GIT_TAG v2.4.8 DOWNLOAD_ONLY YES ) # Create Test executable file(GLOB_RECURSE TEST_FILES "tests/*.cpp" "tests/*.hpp") add_executable(pkmnLibTests ${TEST_FILES}) # Enable all warnings, and make them error when occurring. target_compile_options(pkmnLibTests PRIVATE -Wall -Wextra -Werror -pedantic-errors) message(STATUS "${_TESTLINKS}") target_link_libraries(pkmnLibTests PUBLIC ${_TESTLINKS}) target_include_directories(pkmnLibTests PUBLIC ${doctest_SOURCE_DIR}/doctest) # Add a definition for the test library target_compile_definitions(pkmnLibTests PRIVATE TESTS_BUILD) if (SANITIZER_TESTS AND NOT WINDOWS) # Turn on a set of standard sanitizers # We don't want to recover from any sanitizer error # Except unsigned overflows (often used in standard libraries etc) # Except alignment (Angelscript aligns data wrong when allocating, and I don't have the time to fix Angelscripts allocation.) SET(SANITIZER_OPTS -fsanitize=address,undefined,leak,integer,nullability -fno-sanitize-recover=all -fno-sanitize=unsigned-integer-overflow -fsanitize-recover=alignment) target_compile_options(pkmnLib PRIVATE ${SANITIZER_OPTS}) target_compile_options(pkmnLibTests PRIVATE ${SANITIZER_OPTS}) target_link_options(pkmnLibTests PRIVATE ${SANITIZER_OPTS}) endif () endif () if (SCRIPT_PROVIDER STREQUAL "angelscript") if (ANGELSCRIPT_DEBUGGER) include_directories(extern/AngelscriptDebuggerServer/extern/asio-1.18.2/include) endif () endif()