From 5d745add13835719b5cc4e83f5496e0a91adb0b2 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Thu, 20 Jun 2024 09:38:54 +0300 Subject: [PATCH 01/11] Add support for LLVM/MinGW and ARM64 Windows builds. (cherry picked from commit f2353da5a35a5397a02d4fb47250244c988cfaeb) --- tools/common_compiler_flags.py | 2 +- tools/windows.py | 54 +++++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/tools/common_compiler_flags.py b/tools/common_compiler_flags.py index 5bade45e9..6a1fb6931 100644 --- a/tools/common_compiler_flags.py +++ b/tools/common_compiler_flags.py @@ -74,7 +74,7 @@ def generate(env): else: env.Append(CCFLAGS=["-g2"]) else: - if using_clang(env) and not is_vanilla_clang(env): + if using_clang(env) and not is_vanilla_clang(env) and not env["use_mingw"]: # Apple Clang, its linker doesn't like -s. env.Append(LINKFLAGS=["-Wl,-S", "-Wl,-x", "-Wl,-dead_strip"]) else: diff --git a/tools/windows.py b/tools/windows.py index 9e2672a3b..6fd4b0381 100644 --- a/tools/windows.py +++ b/tools/windows.py @@ -1,3 +1,4 @@ +import os import sys import common_compiler_flags @@ -72,10 +73,14 @@ def spawn_capture(sh, escape, cmd, args, env): def options(opts): + mingw = os.getenv("MINGW_PREFIX", "") + opts.Add(BoolVariable("use_mingw", "Use the MinGW compiler instead of MSVC - only effective on Windows", False)) opts.Add(BoolVariable("use_clang_cl", "Use the clang driver instead of MSVC - only effective on Windows", False)) opts.Add(BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True)) opts.Add(BoolVariable("silence_msvc", "Silence MSVC's cl/link stdout bloat, redirecting errors to stderr.", True)) + opts.Add(BoolVariable("use_llvm", "Use the LLVM compiler", False)) + opts.Add("mingw_prefix", "MinGW prefix", mingw) def exists(env): @@ -86,12 +91,22 @@ def generate(env): if not env["use_mingw"] and msvc.exists(env): if env["arch"] == "x86_64": env["TARGET_ARCH"] = "amd64" + elif env["arch"] == "arm64": + env["TARGET_ARCH"] = "arm64" + elif env["arch"] == "arm32": + env["TARGET_ARCH"] = "arm" elif env["arch"] == "x86_32": env["TARGET_ARCH"] = "x86" + + env["MSVC_SETUP_RUN"] = False # Need to set this to re-run the tool + env["MSVS_VERSION"] = None + env["MSVC_VERSION"] = None + env["is_msvc"] = True # MSVC, linker, and archiver. msvc.generate(env) + env.Tool("msvc") env.Tool("mslib") env.Tool("mslink") @@ -111,7 +126,7 @@ def generate(env): if env["silence_msvc"] and not env.GetOption("clean"): silence_msvc(env) - elif sys.platform == "win32" or sys.platform == "msys": + elif (sys.platform == "win32" or sys.platform == "msys") and not env["mingw_prefix"]: env["use_mingw"] = True mingw.generate(env) # Don't want lib prefixes @@ -137,12 +152,32 @@ def generate(env): else: env["use_mingw"] = True # Cross-compilation using MinGW - prefix = "i686" if env["arch"] == "x86_32" else env["arch"] - env["CXX"] = prefix + "-w64-mingw32-g++" - env["CC"] = prefix + "-w64-mingw32-gcc" - env["AR"] = prefix + "-w64-mingw32-ar" - env["RANLIB"] = prefix + "-w64-mingw32-ranlib" - env["LINK"] = prefix + "-w64-mingw32-g++" + prefix = "" + if env["mingw_prefix"]: + prefix = env["mingw_prefix"] + "/bin/" + + if env["arch"] == "x86_64": + prefix += "x86_64" + elif env["arch"] == "arm64": + prefix += "aarch64" + elif env["arch"] == "arm32": + prefix += "armv7" + elif env["arch"] == "x86_32": + prefix += "i686" + + if env["use_llvm"]: + env["CXX"] = prefix + "-w64-mingw32-clang++" + env["CC"] = prefix + "-w64-mingw32-clang" + env["AR"] = prefix + "-w64-mingw32-llvm-ar" + env["RANLIB"] = prefix + "-w64-mingw32-ranlib" + env["LINK"] = prefix + "-w64-mingw32-clang" + else: + env["CXX"] = prefix + "-w64-mingw32-g++" + env["CC"] = prefix + "-w64-mingw32-gcc" + env["AR"] = prefix + "-w64-mingw32-gcc-ar" + env["RANLIB"] = prefix + "-w64-mingw32-ranlib" + env["LINK"] = prefix + "-w64-mingw32-g++" + # Want dll suffix env["SHLIBSUFFIX"] = ".dll" @@ -156,6 +191,11 @@ def generate(env): "-static-libstdc++", ] ) + if env["use_llvm"]: + env.Append(LINKFLAGS=["-lstdc++"]) + + if sys.platform == "win32" or sys.platform == "msys": + my_spawn.configure(env) env.Append(CPPDEFINES=["WINDOWS_ENABLED"]) From 4109e14f1b8144820abce440088931ffda73ca8e Mon Sep 17 00:00:00 2001 From: ytnuf <161308826+ytnuf@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:44:39 +0100 Subject: [PATCH 02/11] Add hot reload support when building with GCC and CMake (cherry picked from commit 05571971cc4b57f34c1fce180c2df20750c5bc90) --- CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 96090611d..af62675ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,10 +124,6 @@ else() endif() endif() -if (GODOT_ENABLE_HOT_RELOAD) - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D HOT_RELOAD_ENABLED") -endif() - # Generate source from the bindings file find_package(Python3 3.4 REQUIRED) # pathlib should be present if(GENERATE_TEMPLATE_GET_NODE) @@ -170,6 +166,11 @@ target_compile_features(${PROJECT_NAME} cxx_std_17 ) +if(GODOT_ENABLE_HOT_RELOAD) + target_compile_definitions(${PROJECT_NAME} PUBLIC HOT_RELOAD_ENABLED) + target_compile_options(${PROJECT_NAME} PUBLIC $<${compiler_is_gnu}:-fno-gnu-unique>) +endif() + target_compile_definitions(${PROJECT_NAME} PUBLIC $<$: DEBUG_ENABLED From 463a0feb287cd57b6f4ee987a6b367a7c2458457 Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Mon, 26 Aug 2024 13:20:26 +0200 Subject: [PATCH 03/11] Add visibility-hidden This should make all symbols that are not marked otherwise have hidden visibility. There still may be exposed symbols if marked with respective attributes. (cherry picked from commit d18fa929fbbf6d886e9122e1de948da94c29f54f) --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index af62675ad..fba65b318 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,10 @@ # Generate the buildfiles in a sub directory to not clutter the root directory with build files: # mkdir build && cd build && cmake -G "Unix Makefiles" .. && cmake --build . # +# Ensure that you avoid exposing godot-cpp symbols - this might lead to hard to debug errors if you ever load multiple +# plugins using difference godot-cpp versions. Use visibility hidden whenever possible: +# set_target_properties( PROPERTIES CXX_VISIBILITY_PRESET hidden) +# # Todo # Test build for Windows, Mac and mingw. @@ -222,6 +226,7 @@ set_target_properties(${PROJECT_NAME} PROPERTIES CXX_EXTENSIONS OFF POSITION_INDEPENDENT_CODE ON + CXX_VISIBILITY_PRESET hidden ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" From d06b0283c2515db90568bf73772aa9e1f356f705 Mon Sep 17 00:00:00 2001 From: Samuel Nicholas Date: Thu, 12 Sep 2024 13:41:18 +0930 Subject: [PATCH 04/11] Add GODOT_SYMBOL_VISIBILITY cache variable to match scons interface. (cherry picked from commit 02bdc6665af45777b4d57120690a829d1c4445fc) --- CMakeLists.txt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fba65b318..d86a07b65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,18 @@ option(GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class option(GODOT_CPP_SYSTEM_HEADERS "Expose headers as SYSTEM." ON) option(GODOT_CPP_WARNING_AS_ERROR "Treat warnings as errors" OFF) +set( GODOT_SYMBOL_VISIBILITY "hidden" CACHE STRING "Symbols visibility on GNU platforms. Use 'auto' to apply the default value. (auto|visible|hidden)") +set_property( CACHE GODOT_SYMBOL_VISIBILITY PROPERTY STRINGS "auto;visible;hidden" ) + +# CXX_VISIBILITY_PRESET supported values are: default, hidden, protected, and internal +# which is inline with the gcc -fvisibility= +# https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html +# To match the scons options we need to change the text to match the -fvisibility flag +# it is probably worth another PR which changes both to use the flag options +if( ${GODOT_SYMBOL_VISIBILITY} STREQUAL "auto" OR ${GODOT_SYMBOL_VISIBILITY} STREQUAL "visible" ) + set( GODOT_SYMBOL_VISIBILITY "default" ) +endif () + # Add path to modules list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) @@ -226,7 +238,7 @@ set_target_properties(${PROJECT_NAME} PROPERTIES CXX_EXTENSIONS OFF POSITION_INDEPENDENT_CODE ON - CXX_VISIBILITY_PRESET hidden + CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY} ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" From f8c258b3fe41bb650a58fd53791c7a24c3072206 Mon Sep 17 00:00:00 2001 From: Samuel Nicholas Date: Fri, 13 Sep 2024 22:06:25 +0930 Subject: [PATCH 05/11] Updated all variable names to use GODOT_ prefix changed cache type for api file and api dir to FILEPATH and PATH respectively. Minor whitespace. docstring parity (cherry picked from commit 390a9a5590c9e162f838fb7ed5a58e45d5b14643) --- CMakeLists.txt | 60 ++++++++++++++++--------------- cmake/GodotCompilerWarnings.cmake | 2 +- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d86a07b65..d0a6547d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,19 +1,19 @@ # cmake arguments -# CMAKE_BUILD_TYPE: Compilation target (Debug or Release defaults to Debug) +# CMAKE_BUILD_TYPE: Compilation target (Debug or Release defaults to Debug) # # godot-cpp cmake arguments -# GODOT_GDEXTENSION_DIR: Path to the directory containing GDExtension interface header and API JSON file -# GODOT_CPP_SYSTEM_HEADERS Mark the header files as SYSTEM. This may be useful to suppress warnings in projects including this one. -# GODOT_CPP_WARNING_AS_ERROR Treat any warnings as errors -# GODOT_ENABLE_HOT_RELOAD Build with hot reload support. Defaults to YES for Debug-builds and NO for Release-builds. -# GODOT_CUSTOM_API_FILE: Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`) -# FLOAT_PRECISION: Floating-point precision level ("single", "double") +# GODOT_GDEXTENSION_DIR: Path to the directory containing GDExtension interface header and API JSON file +# GODOT_SYSTEM_HEADERS: Mark the header files as SYSTEM. This may be useful to suppress warnings in projects including this one. +# GODOT_WARNING_AS_ERROR: Treat any warnings as errors +# GODOT_USE_HOT_RELOAD: Build with hot reload support. Defaults to YES for Debug-builds and NO for Release-builds. +# GODOT_CUSTOM_API_FILE: Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`) +# GODOT_PRECISION: Floating-point precision level ("single", "double") # # Android cmake arguments -# CMAKE_TOOLCHAIN_FILE: The path to the android cmake toolchain ($ANDROID_NDK/build/cmake/android.toolchain.cmake) -# ANDROID_NDK: The path to the android ndk root folder -# ANDROID_TOOLCHAIN_NAME: The android toolchain (arm-linux-androideabi-4.9 or aarch64-linux-android-4.9 or x86-4.9 or x86_64-4.9) -# ANDROID_PLATFORM: The android platform version (android-23) +# CMAKE_TOOLCHAIN_FILE: The path to the android cmake toolchain ($ANDROID_NDK/build/cmake/android.toolchain.cmake) +# ANDROID_NDK: The path to the android ndk root folder +# ANDROID_TOOLCHAIN_NAME: The android toolchain (arm-linux-androideabi-4.9 or aarch64-linux-android-4.9 or x86-4.9 or x86_64-4.9) +# ANDROID_PLATFORM: The android platform version (android-23) # More info here: https://godot.readthedocs.io/en/latest/development/compiling/compiling_for_android.html # # Examples @@ -45,9 +45,9 @@ cmake_minimum_required(VERSION 3.13) project(godot-cpp LANGUAGES CXX) -option(GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class's get_node." ON) -option(GODOT_CPP_SYSTEM_HEADERS "Expose headers as SYSTEM." ON) -option(GODOT_CPP_WARNING_AS_ERROR "Treat warnings as errors" OFF) +option(GODOT_GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class's get_node. (ON|OFF)" ON) +option(GODOT_SYSTEM_HEADERS "Expose headers as SYSTEM." ON) +option(GODOT_WARNING_AS_ERROR "Treat warnings as errors" OFF) set( GODOT_SYMBOL_VISIBILITY "hidden" CACHE STRING "Symbols visibility on GNU platforms. Use 'auto' to apply the default value. (auto|visible|hidden)") set_property( CACHE GODOT_SYMBOL_VISIBILITY PROPERTY STRINGS "auto;visible;hidden" ) @@ -76,9 +76,9 @@ endif() # Hot reload is enabled by default in Debug-builds if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - option(GODOT_ENABLE_HOT_RELOAD "Build with hot reload support" ON) + option(GODOT_USE_HOT_RELOAD "Enable the extra accounting required to support hot reload. (ON|OFF)" ON) else() - option(GODOT_ENABLE_HOT_RELOAD "Build with hot reload support" OFF) + option(GODOT_USE_HOT_RELOAD "Enable the extra accounting required to support hot reload. (ON|OFF)" OFF) endif() if(NOT DEFINED BITS) @@ -89,20 +89,22 @@ if(NOT DEFINED BITS) endif() # Input from user for GDExtension interface header and the API JSON file -set(GODOT_GDEXTENSION_DIR "gdextension" CACHE STRING "") -set(GODOT_CUSTOM_API_FILE "" CACHE STRING "") +set(GODOT_GDEXTENSION_DIR "gdextension" CACHE PATH + "Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )" ) +set(GODOT_CUSTOM_API_FILE "" CACHE FILEPATH + "Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`) ( /path/to/custom_api_file )") set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json") if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override. set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}") endif() -set(FLOAT_PRECISION "single" CACHE STRING "") -if ("${FLOAT_PRECISION}" STREQUAL "double") +set(GODOT_PRECISION "single" CACHE STRING "Set the floating-point precision level (single|double)") +if ("${GODOT_PRECISION}" STREQUAL "double") add_definitions(-DREAL_T_IS_DOUBLE) endif() -set(GODOT_COMPILE_FLAGS ) +set( GODOT_COMPILE_FLAGS ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # using Visual Studio C++ @@ -127,7 +129,7 @@ endif() # Disable exception handling. Godot doesn't use exceptions anywhere, and this # saves around 20% of binary size and very significant build time (GH-80513). -option(GODOT_DISABLE_EXCEPTIONS ON "Force disabling exception handling code") +option(GODOT_DISABLE_EXCEPTIONS "Force disabling exception handling code (ON|OFF)" ON ) if (GODOT_DISABLE_EXCEPTIONS) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0") @@ -142,7 +144,7 @@ endif() # Generate source from the bindings file find_package(Python3 3.4 REQUIRED) # pathlib should be present -if(GENERATE_TEMPLATE_GET_NODE) +if(GODOT_GENERATE_TEMPLATE_GET_NODE) set(GENERATE_BINDING_PARAMETERS "True") else() set(GENERATE_BINDING_PARAMETERS "False") @@ -155,7 +157,7 @@ execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; ) add_custom_command(OUTPUT ${GENERATED_FILES_LIST} - COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings(\"${GODOT_GDEXTENSION_API_FILE}\", \"${GENERATE_BINDING_PARAMETERS}\", \"${BITS}\", \"${FLOAT_PRECISION}\", \"${CMAKE_CURRENT_BINARY_DIR}\")" + COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings(\"${GODOT_GDEXTENSION_API_FILE}\", \"${GENERATE_BINDING_PARAMETERS}\", \"${BITS}\", \"${GODOT_PRECISION}\", \"${CMAKE_CURRENT_BINARY_DIR}\")" VERBATIM WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE} @@ -182,7 +184,7 @@ target_compile_features(${PROJECT_NAME} cxx_std_17 ) -if(GODOT_ENABLE_HOT_RELOAD) +if(GODOT_USE_HOT_RELOAD) target_compile_definitions(${PROJECT_NAME} PUBLIC HOT_RELOAD_ENABLED) target_compile_options(${PROJECT_NAME} PUBLIC $<${compiler_is_gnu}:-fno-gnu-unique>) endif() @@ -206,12 +208,12 @@ target_link_options(${PROJECT_NAME} PRIVATE ) # Optionally mark headers as SYSTEM -set(GODOT_CPP_SYSTEM_HEADERS_ATTRIBUTE "") -if (GODOT_CPP_SYSTEM_HEADERS) - set(GODOT_CPP_SYSTEM_HEADERS_ATTRIBUTE SYSTEM) +set(GODOT_SYSTEM_HEADERS_ATTRIBUTE "") +if (GODOT_SYSTEM_HEADERS) + set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM) endif () -target_include_directories(${PROJECT_NAME} ${GODOT_CPP_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC +target_include_directories(${PROJECT_NAME} ${GODOT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC include ${CMAKE_CURRENT_BINARY_DIR}/gen/include ${GODOT_GDEXTENSION_DIR} diff --git a/cmake/GodotCompilerWarnings.cmake b/cmake/GodotCompilerWarnings.cmake index 423e63663..94556415b 100644 --- a/cmake/GodotCompilerWarnings.cmake +++ b/cmake/GodotCompilerWarnings.cmake @@ -89,6 +89,6 @@ function( set_warning_as_error ) endif() endfunction() -if ( GODOT_CPP_WARNING_AS_ERROR ) +if ( GODOT_WARNING_AS_ERROR ) set_warning_as_error() endif() From 43c66817ea93194634e67cdf90d176b3c35f088f Mon Sep 17 00:00:00 2001 From: Samuel Nicholas Date: Thu, 19 Sep 2024 08:11:03 +0930 Subject: [PATCH 06/11] Re-Structure cmake solution to be closer to the scons solution. This is just a single step, re-arranging the code without actually changing its functionality. new docs/cmake.md moved the block of comments from the start of the CMakeLists.txt into the cmake.md file and converted content to markdown. new cmake/godotcpp.cmake Moved all exposed options into a new function godotcpp_options() Moved configuration and generation code into godotcpp_generate() To get all the options into the godotcpp_options() I changed the logic of GODOT_USE_HOT_RELOAD which I believe is a closer match to scons, that if the options is not set, and the build type is not release, then it defaults to ON. I msvc builds require the default flags to be modified or it will throw errors. I have added the links to articles in the commit, but its about removing the runtime error checks /RTC1 from the CMAKE_CXX_FLAGS_DEBUG variable. This needs to happen before the files are included. https://stackoverflow.com/questions/74426638/how-to-remove-rtc1-from-specific-target-or-file-in-cmake https://discourse.cmake.org/t/how-do-i-remove-compile-options-from-target/5965 Renamed GodotCompilerWarnings.cmake to common_compiler_flags.cmake to match scons Included files explicitly by path, as we dont need to append to the CMAKE_MODULES_PATH which effects the whole build tree. This prevents consumers of the library from clobbering the names of the cmake include files and breaking the build. (cherry picked from commit 2402a044ebc2189f6c725b9a64c66c9bc2e5c616) --- CMakeLists.txt | 254 ++---------------- ...ings.cmake => common_compiler_flags.cmake} | 0 cmake/godotcpp.cmake | 240 +++++++++++++++++ doc/cmake.md | 57 ++++ 4 files changed, 312 insertions(+), 239 deletions(-) rename cmake/{GodotCompilerWarnings.cmake => common_compiler_flags.cmake} (100%) create mode 100644 cmake/godotcpp.cmake create mode 100644 doc/cmake.md diff --git a/CMakeLists.txt b/CMakeLists.txt index d0a6547d1..ff77368ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,248 +1,24 @@ -# cmake arguments -# CMAKE_BUILD_TYPE: Compilation target (Debug or Release defaults to Debug) -# -# godot-cpp cmake arguments -# GODOT_GDEXTENSION_DIR: Path to the directory containing GDExtension interface header and API JSON file -# GODOT_SYSTEM_HEADERS: Mark the header files as SYSTEM. This may be useful to suppress warnings in projects including this one. -# GODOT_WARNING_AS_ERROR: Treat any warnings as errors -# GODOT_USE_HOT_RELOAD: Build with hot reload support. Defaults to YES for Debug-builds and NO for Release-builds. -# GODOT_CUSTOM_API_FILE: Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`) -# GODOT_PRECISION: Floating-point precision level ("single", "double") -# -# Android cmake arguments -# CMAKE_TOOLCHAIN_FILE: The path to the android cmake toolchain ($ANDROID_NDK/build/cmake/android.toolchain.cmake) -# ANDROID_NDK: The path to the android ndk root folder -# ANDROID_TOOLCHAIN_NAME: The android toolchain (arm-linux-androideabi-4.9 or aarch64-linux-android-4.9 or x86-4.9 or x86_64-4.9) -# ANDROID_PLATFORM: The android platform version (android-23) -# More info here: https://godot.readthedocs.io/en/latest/development/compiling/compiling_for_android.html -# -# Examples -# -# Builds a debug version: -# cmake . -# cmake --build . -# -# Builds a release version with clang -# CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" . -# cmake --build . -# -# Builds an android armeabi-v7a debug version: -# cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_NDK=$ANDROID_NDK \ -# -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 -DANDROID_PLATFORM=android-23 -DCMAKE_BUILD_TYPE=Debug . -# cmake --build . -# -# Protip -# Generate the buildfiles in a sub directory to not clutter the root directory with build files: -# mkdir build && cd build && cmake -G "Unix Makefiles" .. && cmake --build . -# -# Ensure that you avoid exposing godot-cpp symbols - this might lead to hard to debug errors if you ever load multiple -# plugins using difference godot-cpp versions. Use visibility hidden whenever possible: -# set_target_properties( PROPERTIES CXX_VISIBILITY_PRESET hidden) -# -# Todo -# Test build for Windows, Mac and mingw. - cmake_minimum_required(VERSION 3.13) project(godot-cpp LANGUAGES CXX) -option(GODOT_GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class's get_node. (ON|OFF)" ON) -option(GODOT_SYSTEM_HEADERS "Expose headers as SYSTEM." ON) -option(GODOT_WARNING_AS_ERROR "Treat warnings as errors" OFF) - -set( GODOT_SYMBOL_VISIBILITY "hidden" CACHE STRING "Symbols visibility on GNU platforms. Use 'auto' to apply the default value. (auto|visible|hidden)") -set_property( CACHE GODOT_SYMBOL_VISIBILITY PROPERTY STRINGS "auto;visible;hidden" ) - -# CXX_VISIBILITY_PRESET supported values are: default, hidden, protected, and internal -# which is inline with the gcc -fvisibility= -# https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html -# To match the scons options we need to change the text to match the -fvisibility flag -# it is probably worth another PR which changes both to use the flag options -if( ${GODOT_SYMBOL_VISIBILITY} STREQUAL "auto" OR ${GODOT_SYMBOL_VISIBILITY} STREQUAL "visible" ) - set( GODOT_SYMBOL_VISIBILITY "default" ) +# Configure CMake +# https://discourse.cmake.org/t/how-do-i-remove-compile-options-from-target/5965 +# https://stackoverflow.com/questions/74426638/how-to-remove-rtc1-from-specific-target-or-file-in-cmake +if(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) + if(NOT CMAKE_BUILD_TYPE MATCHES Debug) + STRING(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) + endif () endif () -# Add path to modules -list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) - -# Set some helper variables for readability -set( compiler_is_clang "$,$>" ) -set( compiler_is_gnu "$" ) -set( compiler_is_msvc "$" ) - -# Default build type is Debug in the SConstruct -if("${CMAKE_BUILD_TYPE}" STREQUAL "") - set(CMAKE_BUILD_TYPE Debug) -endif() - -# Hot reload is enabled by default in Debug-builds -if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - option(GODOT_USE_HOT_RELOAD "Enable the extra accounting required to support hot reload. (ON|OFF)" ON) -else() - option(GODOT_USE_HOT_RELOAD "Enable the extra accounting required to support hot reload. (ON|OFF)" OFF) -endif() - -if(NOT DEFINED BITS) - set(BITS 32) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(BITS 64) - endif(CMAKE_SIZEOF_VOID_P EQUAL 8) -endif() - -# Input from user for GDExtension interface header and the API JSON file -set(GODOT_GDEXTENSION_DIR "gdextension" CACHE PATH - "Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )" ) -set(GODOT_CUSTOM_API_FILE "" CACHE FILEPATH - "Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`) ( /path/to/custom_api_file )") - -set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json") -if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override. - set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}") -endif() - -set(GODOT_PRECISION "single" CACHE STRING "Set the floating-point precision level (single|double)") -if ("${GODOT_PRECISION}" STREQUAL "double") - add_definitions(-DREAL_T_IS_DOUBLE) -endif() - -set( GODOT_COMPILE_FLAGS ) - -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - # using Visual Studio C++ - set(GODOT_COMPILE_FLAGS "/utf-8") # /GF /MP - - if(CMAKE_BUILD_TYPE MATCHES Debug) - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi - else() - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MD /O2") # /Oy /GL /Gy - STRING(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) - endif(CMAKE_BUILD_TYPE MATCHES Debug) - - add_definitions(-DNOMINMAX) -else() # GCC/Clang - if(CMAKE_BUILD_TYPE MATCHES Debug) - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g") - else() - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3") - endif(CMAKE_BUILD_TYPE MATCHES Debug) -endif() - -# Disable exception handling. Godot doesn't use exceptions anywhere, and this -# saves around 20% of binary size and very significant build time (GH-80513). -option(GODOT_DISABLE_EXCEPTIONS "Force disabling exception handling code (ON|OFF)" ON ) -if (GODOT_DISABLE_EXCEPTIONS) - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0") - else() - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions") - endif() -else() - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc") - endif() -endif() - -# Generate source from the bindings file -find_package(Python3 3.4 REQUIRED) # pathlib should be present -if(GODOT_GENERATE_TEMPLATE_GET_NODE) - set(GENERATE_BINDING_PARAMETERS "True") -else() - set(GENERATE_BINDING_PARAMETERS "False") -endif() - -execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_VARIABLE GENERATED_FILES_LIST - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -add_custom_command(OUTPUT ${GENERATED_FILES_LIST} - COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings(\"${GODOT_GDEXTENSION_API_FILE}\", \"${GENERATE_BINDING_PARAMETERS}\", \"${BITS}\", \"${GODOT_PRECISION}\", \"${CMAKE_CURRENT_BINARY_DIR}\")" - VERBATIM - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py - COMMENT "Generating bindings" -) - -# Get Sources -file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.c**) -file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS include/*.h**) - -# Define our godot-cpp library -add_library(${PROJECT_NAME} STATIC - ${SOURCES} - ${HEADERS} - ${GENERATED_FILES_LIST} -) -add_library(godot::cpp ALIAS ${PROJECT_NAME}) - -include(GodotCompilerWarnings) - -target_compile_features(${PROJECT_NAME} - PRIVATE - cxx_std_17 -) - -if(GODOT_USE_HOT_RELOAD) - target_compile_definitions(${PROJECT_NAME} PUBLIC HOT_RELOAD_ENABLED) - target_compile_options(${PROJECT_NAME} PUBLIC $<${compiler_is_gnu}:-fno-gnu-unique>) -endif() - -target_compile_definitions(${PROJECT_NAME} PUBLIC - $<$: - DEBUG_ENABLED - DEBUG_METHODS_ENABLED - > - $<${compiler_is_msvc}: - TYPED_METHOD_BIND - > -) - -target_link_options(${PROJECT_NAME} PRIVATE - $<$: - -static-libgcc - -static-libstdc++ - -Wl,-R,'$$ORIGIN' - > -) - -# Optionally mark headers as SYSTEM -set(GODOT_SYSTEM_HEADERS_ATTRIBUTE "") -if (GODOT_SYSTEM_HEADERS) - set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM) -endif () - -target_include_directories(${PROJECT_NAME} ${GODOT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC - include - ${CMAKE_CURRENT_BINARY_DIR}/gen/include - ${GODOT_GDEXTENSION_DIR} -) - -# Add the compile flags -set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS ${GODOT_COMPILE_FLAGS}) +include( ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake ) -# Create the correct name (godot.os.build_type.system_bits) -string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM_NAME) -string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE) +# I know this doesn't look like a typical CMakeLists.txt, but as we are +# attempting mostly feature parity with SCons, and easy maintenance, the closer +# the two build systems look the easier they will be to keep in lockstep. -if(ANDROID) - # Added the android abi after system name - set(SYSTEM_NAME ${SYSTEM_NAME}.${ANDROID_ABI}) +# The typical target definitions are in ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake - # Android does not have the bits at the end if you look at the main godot repo build - set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}") -else() - set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}.${BITS}") -endif() +godotcpp_options() -set_target_properties(${PROJECT_NAME} - PROPERTIES - CXX_EXTENSIONS OFF - POSITION_INDEPENDENT_CODE ON - CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY} - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" - OUTPUT_NAME "${OUTPUT_NAME}" -) +godotcpp_generate() diff --git a/cmake/GodotCompilerWarnings.cmake b/cmake/common_compiler_flags.cmake similarity index 100% rename from cmake/GodotCompilerWarnings.cmake rename to cmake/common_compiler_flags.cmake diff --git a/cmake/godotcpp.cmake b/cmake/godotcpp.cmake new file mode 100644 index 000000000..a5c667796 --- /dev/null +++ b/cmake/godotcpp.cmake @@ -0,0 +1,240 @@ +function( godotcpp_options ) + + #TODO platform + #TODO target + + # Input from user for GDExtension interface header and the API JSON file + set(GODOT_GDEXTENSION_DIR "gdextension" CACHE PATH + "Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )" ) + set(GODOT_CUSTOM_API_FILE "" CACHE FILEPATH + "Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`) ( /path/to/custom_api_file )") + + #TODO generate_bindings + + option(GODOT_GENERATE_TEMPLATE_GET_NODE + "Generate a template version of the Node class's get_node. (ON|OFF)" ON) + + #TODO build_library + + set(GODOT_PRECISION "single" CACHE STRING + "Set the floating-point precision level (single|double)") + + #TODO arch + #TODO threads + #TODO compiledb + #TODO compiledb_file + #TODO build_profile aka cmake preset + + set(GODOT_USE_HOT_RELOAD "" CACHE BOOL + "Enable the extra accounting required to support hot reload. (ON|OFF)") + + option(GODOT_DISABLE_EXCEPTIONS "Force disabling exception handling code (ON|OFF)" ON ) + + set( GODOT_SYMBOL_VISIBILITY "hidden" CACHE STRING + "Symbols visibility on GNU platforms. Use 'auto' to apply the default value. (auto|visible|hidden)") + set_property( CACHE GODOT_SYMBOL_VISIBILITY PROPERTY STRINGS "auto;visible;hidden" ) + + #TODO optimize + #TODO debug_symbols + #TODO dev_build + + # FIXME These options are not present in SCons, and perhaps should be added there. + option(GODOT_SYSTEM_HEADERS "Expose headers as SYSTEM." ON) + option(GODOT_WARNING_AS_ERROR "Treat warnings as errors" OFF) + + # Run options commands on the following to populate cache for all platforms. + # This type of thing is typically done conditionally + # But as scons shows all options so shall we. + #TODO ios_options() + #TODO linux_options() + #TODO macos_options() + #TODO web_options() + #TODO windows_options() +endfunction() + + +function( godotcpp_generate ) + # Set some helper variables for readability + set( compiler_is_clang "$,$>" ) + set( compiler_is_gnu "$" ) + set( compiler_is_msvc "$" ) + + # CXX_VISIBILITY_PRESET supported values are: default, hidden, protected, and internal + # which is inline with the gcc -fvisibility= + # https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html + # To match the scons options we need to change the text to match the -fvisibility flag + # it is probably worth another PR which changes both to use the flag options + if( ${GODOT_SYMBOL_VISIBILITY} STREQUAL "auto" OR ${GODOT_SYMBOL_VISIBILITY} STREQUAL "visible" ) + set( GODOT_SYMBOL_VISIBILITY "default" ) + endif () + + # Default build type is Debug in the SConstruct + if("${CMAKE_BUILD_TYPE}" STREQUAL "") + set(CMAKE_BUILD_TYPE Debug) + endif() + + # Hot reload is enabled by default in Debug-builds + if( GODOT_USE_HOT_RELOAD STREQUAL "" AND NOT CMAKE_BUILD_TYPE STREQUAL "Release") + set(GODOT_USE_HOT_RELOAD ON) + endif() + + if(NOT DEFINED BITS) + set(BITS 32) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(BITS 64) + endif(CMAKE_SIZEOF_VOID_P EQUAL 8) + endif() + + + set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json") + if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override. + set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}") + endif() + + if ("${GODOT_PRECISION}" STREQUAL "double") + add_definitions(-DREAL_T_IS_DOUBLE) + endif() + + set( GODOT_COMPILE_FLAGS ) + + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + # using Visual Studio C++ + set(GODOT_COMPILE_FLAGS "/utf-8") # /GF /MP + + if(CMAKE_BUILD_TYPE MATCHES Debug) + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi + else() + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MD /O2") # /Oy /GL /Gy + endif(CMAKE_BUILD_TYPE MATCHES Debug) + + add_definitions(-DNOMINMAX) + else() # GCC/Clang + if(CMAKE_BUILD_TYPE MATCHES Debug) + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g") + else() + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3") + endif(CMAKE_BUILD_TYPE MATCHES Debug) + endif() + + # Disable exception handling. Godot doesn't use exceptions anywhere, and this + # saves around 20% of binary size and very significant build time (GH-80513). + if (GODOT_DISABLE_EXCEPTIONS) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0") + else() + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions") + endif() + else() + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc") + endif() + endif() + + # Generate source from the bindings file + find_package(Python3 3.4 REQUIRED) # pathlib should be present + if(GODOT_GENERATE_TEMPLATE_GET_NODE) + set(GENERATE_BINDING_PARAMETERS "True") + else() + set(GENERATE_BINDING_PARAMETERS "False") + endif() + + execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE GENERATED_FILES_LIST + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + add_custom_command(OUTPUT ${GENERATED_FILES_LIST} + COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings(\"${GODOT_GDEXTENSION_API_FILE}\", \"${GENERATE_BINDING_PARAMETERS}\", \"${BITS}\", \"${GODOT_PRECISION}\", \"${CMAKE_CURRENT_BINARY_DIR}\")" + VERBATIM + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py + COMMENT "Generating bindings" + ) + + # Get Sources + # As this cmake file was added using 'include(godotcpp)' from the root CMakeLists.txt, + # the ${CMAKE_CURRENT_SOURCE_DIR} is still the root dir. + file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.c**) + file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS include/*.h**) + + # Define our godot-cpp library + add_library(${PROJECT_NAME} STATIC + ${SOURCES} + ${HEADERS} + ${GENERATED_FILES_LIST} + ) + add_library(godot::cpp ALIAS ${PROJECT_NAME}) + + include(${PROJECT_SOURCE_DIR}/cmake/common_compiler_flags.cmake) + + target_compile_features(${PROJECT_NAME} + PRIVATE + cxx_std_17 + ) + + if(GODOT_USE_HOT_RELOAD) + target_compile_definitions(${PROJECT_NAME} PUBLIC HOT_RELOAD_ENABLED) + target_compile_options(${PROJECT_NAME} PUBLIC $<${compiler_is_gnu}:-fno-gnu-unique>) + endif() + + target_compile_definitions(${PROJECT_NAME} PUBLIC + $<$: + DEBUG_ENABLED + DEBUG_METHODS_ENABLED + > + $<${compiler_is_msvc}: + TYPED_METHOD_BIND + > + ) + + target_link_options(${PROJECT_NAME} PRIVATE + $<$: + -static-libgcc + -static-libstdc++ + -Wl,-R,'$$ORIGIN' + > + ) + + # Optionally mark headers as SYSTEM + set(GODOT_SYSTEM_HEADERS_ATTRIBUTE "") + if (GODOT_SYSTEM_HEADERS) + set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM) + endif () + + target_include_directories(${PROJECT_NAME} ${GODOT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC + include + ${CMAKE_CURRENT_BINARY_DIR}/gen/include + ${GODOT_GDEXTENSION_DIR} + ) + + # Add the compile flags + set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS ${GODOT_COMPILE_FLAGS}) + + # Create the correct name (godot.os.build_type.system_bits) + string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM_NAME) + string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE) + + if(ANDROID) + # Added the android abi after system name + set(SYSTEM_NAME ${SYSTEM_NAME}.${ANDROID_ABI}) + + # Android does not have the bits at the end if you look at the main godot repo build + set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}") + else() + set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}.${BITS}") + endif() + + set_target_properties(${PROJECT_NAME} + PROPERTIES + CXX_EXTENSIONS OFF + POSITION_INDEPENDENT_CODE ON + CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY} + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" + OUTPUT_NAME "${OUTPUT_NAME}" + ) + +endfunction() diff --git a/doc/cmake.md b/doc/cmake.md new file mode 100644 index 000000000..3dd77f58f --- /dev/null +++ b/doc/cmake.md @@ -0,0 +1,57 @@ +## CMake + +### cmake arguments + +`CMAKE_BUILD_TYPE`: Compilation target (Debug or Release defaults to Debug) + +### godot-cpp cmake arguments +- `GODOT_GDEXTENSION_DIR`: Path to the directory containing GDExtension interface header and API JSON file +- `GODOT_SYSTEM_HEADERS`: Mark the header files as SYSTEM. This may be useful to suppress warnings in projects including this one. +- `GODOT_WARNING_AS_ERROR`: Treat any warnings as errors +- `GODOT_USE_HOT_RELOAD`: Build with hot reload support. Defaults to YES for Debug-builds and NO for Release-builds. +- `GODOT_CUSTOM_API_FILE`: Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`) +- `GODOT_PRECISION`: Floating-point precision level ("single", "double") + +### Android cmake arguments +- `CMAKE_TOOLCHAIN_FILE`: The path to the android cmake toolchain ($ANDROID_NDK/build/cmake/android.toolchain.cmake) +- `ANDROID_NDK`: The path to the android ndk root folder +- `ANDROID_TOOLCHAIN_NAME`: The android toolchain (arm-linux-androideabi-4.9 or aarch64-linux-android-4.9 or x86-4.9 or x86_64-4.9) +- `ANDROID_PLATFORM`: The android platform version (android-23) + +- More info [here](https://godot.readthedocs.io/en/latest/development/compiling/compiling_for_android.html) + +## Examples +```shell +Builds a debug version: +cmake . +cmake --build . +``` +Builds a release version with clang + +```shell +CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" . +cmake --build . +``` +Builds an android armeabi-v7a debug version: + +``` shell +cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_NDK=$ANDROID_NDK \ + -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 -DANDROID_PLATFORM=android-23 -DCMAKE_BUILD_TYPE=Debug . +cmake --build . +``` + +## Protip +Generate the buildfiles in a sub directory to not clutter the root directory with build files: + +```shell +mkdir build && cd build && cmake -G "Unix Makefiles" .. && cmake --build . +``` + +Ensure that you avoid exposing godot-cpp symbols - this might lead to hard to debug errors if you ever load multiple +plugins using difference godot-cpp versions. Use visibility hidden whenever possible: +```cmake +set_target_properties( PROPERTIES CXX_VISIBILITY_PRESET hidden) +``` + +## Todo +Test build for Windows, Mac and mingw. From 6cb5eb9bca1cf13d6528a5ebe07689bc19beeb90 Mon Sep 17 00:00:00 2001 From: Samuel Nicholas Date: Thu, 19 Sep 2024 21:38:35 +0930 Subject: [PATCH 07/11] update .gitignore to add .idea for the Jetbrains CLion IDE and also the default cmake build directory when building in clion cmake-build-* (cherry picked from commit 9f5daa2d904c8acae0540c11ee35cd1f78724429) --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 4183b24fc..ee9a3f756 100644 --- a/.gitignore +++ b/.gitignore @@ -195,3 +195,7 @@ compile_commands.json # Python development .venv venv + +# Clion Configuration +.idea/ +cmake-build-* From 5e7d2472ddbe75b875b1871217aaf4e30f5108ff Mon Sep 17 00:00:00 2001 From: Samuel Nicholas Date: Sat, 21 Sep 2024 22:38:07 +0930 Subject: [PATCH 08/11] VSProj Configure type on build command - to resolve #1582 Visual Studio projects are multi-config projects like Ninja-MultiConfig which means you can't set the configuration at configure time as there are multiple, it always chooses the first one by default when not specified in the build command. Instead of this: cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 17 2022" . cmake --build . --verbose It should be this cmake -G"Visual Studio 17 2022" . cmake --build . --verbose --config Release Update ci.yml Because the current build system doesnt use generator expressions for multi config builds, both the CMAKE_BUILD_TYPE and the build --config options need to be set (cherry picked from commit 07704f8f48308b83fc99c67b33a10027aa5a7846) --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02ee1dd65..a9238fed4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -264,9 +264,9 @@ jobs: - name: Build godot-cpp run: | cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 16 2019" . - cmake --build . --verbose + cmake --build . --verbose --config Release - name: Build test GDExtension library run: | cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -G"Visual Studio 16 2019" . - cmake --build . --verbose + cmake --build . --verbose --config Release From a2a336546ac4fa60028bf50c16e2594c538c79c7 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Sun, 22 Sep 2024 13:39:06 +0200 Subject: [PATCH 09/11] [SCons] Remove use_clang_cl windows flag in favor of generic use_llvm This is consistent with Godot upstream. (cherry picked from commit 4717a781445d9d1e9044602925cd9640b73a1b28) --- tools/windows.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/windows.py b/tools/windows.py index 6fd4b0381..2e8d609ea 100644 --- a/tools/windows.py +++ b/tools/windows.py @@ -76,10 +76,9 @@ def options(opts): mingw = os.getenv("MINGW_PREFIX", "") opts.Add(BoolVariable("use_mingw", "Use the MinGW compiler instead of MSVC - only effective on Windows", False)) - opts.Add(BoolVariable("use_clang_cl", "Use the clang driver instead of MSVC - only effective on Windows", False)) opts.Add(BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True)) opts.Add(BoolVariable("silence_msvc", "Silence MSVC's cl/link stdout bloat, redirecting errors to stderr.", True)) - opts.Add(BoolVariable("use_llvm", "Use the LLVM compiler", False)) + opts.Add(BoolVariable("use_llvm", "Use the LLVM compiler (MVSC or MinGW depending on the use_mingw flag)", False)) opts.Add("mingw_prefix", "MinGW prefix", mingw) @@ -114,7 +113,7 @@ def generate(env): env.Append(CCFLAGS=["/utf-8"]) env.Append(LINKFLAGS=["/WX"]) - if env["use_clang_cl"]: + if env["use_llvm"]: env["CC"] = "clang-cl" env["CXX"] = "clang-cl" From 810b0ce13e9925fe98042d0aed65b7a866583aed Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Mon, 30 Sep 2024 11:26:06 -0500 Subject: [PATCH 10/11] SCons: Don't cache librarys (cherry picked from commit 83c0f15ab95d608f2c39eda942ee4a51cc1f0456) --- test/SConstruct | 1 + tools/godotcpp.py | 1 + 2 files changed, 2 insertions(+) diff --git a/test/SConstruct b/test/SConstruct index fc385b9b0..601d59c15 100644 --- a/test/SConstruct +++ b/test/SConstruct @@ -38,4 +38,5 @@ else: source=sources, ) +env.NoCache(library) Default(library) diff --git a/tools/godotcpp.py b/tools/godotcpp.py index c2af52677..5773660de 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -506,6 +506,7 @@ def _godot_cpp(env): if env["build_library"]: library = env.StaticLibrary(target=env.File("bin/%s" % library_name), source=sources) + env.NoCache(library) default_args = [library] # Add compiledb if the option is set From 5f3a66a326d3c4e12cdc4455ed7c0204532aec34 Mon Sep 17 00:00:00 2001 From: Florent Guiocheau Date: Mon, 14 Oct 2024 21:45:17 +0200 Subject: [PATCH 11/11] Add p_use_model_front to Basis::looking_at() (cherry picked from commit 02fd535454773edb1a8c4b52d5b851e863660246) --- include/godot_cpp/variant/basis.hpp | 2 +- src/variant/basis.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/godot_cpp/variant/basis.hpp b/include/godot_cpp/variant/basis.hpp index e740a64a7..f3ebe15fe 100644 --- a/include/godot_cpp/variant/basis.hpp +++ b/include/godot_cpp/variant/basis.hpp @@ -224,7 +224,7 @@ struct _NO_DISCARD_ Basis { operator Quaternion() const { return get_quaternion(); } - static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)); + static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false); Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); } Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); } diff --git a/src/variant/basis.cpp b/src/variant/basis.cpp index 200cd0686..d8a991917 100644 --- a/src/variant/basis.cpp +++ b/src/variant/basis.cpp @@ -1037,12 +1037,15 @@ void Basis::rotate_sh(real_t *p_values) { p_values[8] = d4 * s_scale_dst4; } -Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up) { +Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(p_target.is_zero_approx(), Basis(), "The target vector can't be zero."); ERR_FAIL_COND_V_MSG(p_up.is_zero_approx(), Basis(), "The up vector can't be zero."); #endif - Vector3 v_z = -p_target.normalized(); + Vector3 v_z = p_target.normalized(); + if (!p_use_model_front) { + v_z = -v_z; + } Vector3 v_x = p_up.cross(v_z); #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(v_x.is_zero_approx(), Basis(), "The target vector and up vector can't be parallel to each other.");