Merge pull request #1598 from enetheru/modernise

Modernise existing cmake options
master
David Snopek 2024-11-22 08:23:46 -06:00 committed by GitHub
commit a42b3634d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 1147 additions and 490 deletions

View File

@ -207,30 +207,6 @@ jobs:
path: ${{ matrix.artifact-path }} path: ${{ matrix.artifact-path }}
if-no-files-found: error if-no-files-found: error
linux-cmake:
name: 🐧 Build (Linux, GCC, CMake)
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -qqq build-essential pkg-config cmake
- name: Build godot-cpp
run: |
cmake -DCMAKE_BUILD_TYPE=Release .
make -j $(nproc) VERBOSE=1
- name: Build test GDExtension library
run: |
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." .
make -j $(nproc) VERBOSE=1
linux-cmake-ninja: linux-cmake-ninja:
name: 🐧 Build (Linux, GCC, CMake Ninja) name: 🐧 Build (Linux, GCC, CMake Ninja)
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
@ -245,15 +221,12 @@ jobs:
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -qqq build-essential pkg-config cmake ninja-build sudo apt-get install -qqq build-essential pkg-config cmake ninja-build
- name: Build godot-cpp
run: |
cmake -DCMAKE_BUILD_TYPE=Release -GNinja .
cmake --build . -j $(nproc) --verbose
- name: Build test GDExtension library - name: Build test GDExtension library
run: | run: |
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -GNinja . mkdir cmake-build
cmake --build . -j $(nproc) --verbose cd cmake-build
cmake ../ -DTEST_TARGET=template_release
cmake --build . --verbose -j $(nproc) -t godot-cpp-test --config Release
windows-msvc-cmake: windows-msvc-cmake:
name: 🏁 Build (Windows, MSVC, CMake) name: 🏁 Build (Windows, MSVC, CMake)
@ -264,12 +237,9 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: Build godot-cpp
run: |
cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 16 2019" .
cmake --build . --verbose --config Release
- name: Build test GDExtension library - name: Build test GDExtension library
run: | run: |
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -G"Visual Studio 16 2019" . mkdir cmake-build
cmake --build . --verbose --config Release cd cmake-build
cmake ../ -DTEST_TARGET=template_release
cmake --build . --verbose -t godot-cpp-test --config Release

5
.gitignore vendored
View File

@ -198,4 +198,7 @@ venv
# Clion Configuration # Clion Configuration
.idea/ .idea/
cmake-build-* cmake-build*/
# CMake related
CMakeUserPresets.json

View File

@ -1,24 +1,98 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.17)
project(godot-cpp LANGUAGES CXX)
# Configure CMake #[=======================================================================[.rst:
# 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 ()
include( ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake ) CMake Version requirements
--------------------------
# I know this doesn't look like a typical CMakeLists.txt, but as we are To enable use of the emscripten emsdk hack for pseudo shared library support
# attempting mostly feature parity with SCons, and easy maintenance, the closer without polluting options for consumers we need to use the
# the two build systems look the easier they will be to keep in lockstep. CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE which was introduced in version 3.17
# The typical target definitions are in ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake Scons Compatibility
-------------------
As we are attempting to maintain feature parity, and ease of maintenance, these
CMake scripts are built to resemble the SCons build system.
The file structure and file content are made to match, if not in content then
in spirit. The closer the two build systems look the easier they will be to
maintain.
Where the SCons additional scripts in the tools directory, The CMake scripts
are in the cmake directory.
For example, the tools/godotcpp.py is sourced into SCons, and the 'options'
function is run.
.. highlight:: python
cpp_tool = Tool("godotcpp", toolpath=["tools"])
cpp_tool.options(opts, env)
The CMake equivalent is below.
]=======================================================================]
include( cmake/godotcpp.cmake )
godotcpp_options() godotcpp_options()
#[=======================================================================[.rst:
Configurations
--------------
There are two build main configurations, 'Debug' and 'Release', these are not
related to godot's DEBUG_FEATURES flag. Build configurations change the default
compiler and linker flags present when building the library, things like debug
symbols, optimization.
The Scons build scripts don't have this concept, you can think of it like the
SCons solution has a single default configuration. In both cases overriding the
defaults is controlled by options on the command line, or in preset files.
Because of this added configuration and that it can be undefined, it becomes
important to set a default, considering the SCons solution that does not enable
debug symbols by default, it seemed appropriate to set the default to 'Release'
if unspecified. This can always be overridden like below.
.. highlight:: shell
cmake <source> -DCMAKE_BUILD_TYPE:STRING=Debug
.. caution::
A complication arises from `Multi-Config Generators`_ that cannot have
their configuration set at configure time. This means that the configuration
must be set on the build command. This is especially important for Visual
Studio Generators which default to 'Debug'
.. highlight:: shell
cmake --build . --config Release
.. _Multi-Config Generators:https://cmake.org/cmake/help/latest/prop_gbl/GENERATOR_IS_MULTI_CONFIG.html
]=======================================================================]
get_property( IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG )
if( NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE )
if( GODOT_DEV_BUILD )
set( CMAKE_BUILD_TYPE Debug )
else ()
set( CMAKE_BUILD_TYPE Release )
endif ()
endif ()
#[[ Python is required for code generation ]]
find_package(Python3 3.4 REQUIRED) # pathlib should be present
# Define our project.
project( godot-cpp
VERSION 4.4
DESCRIPTION "C++ bindings for the Godot Engine's GDExtensions API."
HOMEPAGE_URL "https://github.com/godotengine/godot-cpp"
LANGUAGES CXX)
godotcpp_generate() godotcpp_generate()
# Test Example
add_subdirectory( test )

41
cmake/android.cmake Normal file
View File

@ -0,0 +1,41 @@
#[=======================================================================[.rst:
Android
-------
This file contains functions for options and configuration for targeting the
Android platform
Configuration of the Android toolchain is done using toolchain files,
CMakePresets, or variables on the command line.
The `Android SDK`_ provides toolchain files to help with configuration.
CMake has its own `built-in support`_ for cross compiling to the
Android platforms.
.. warning::
Android does not support or test the CMake built-in workflow, recommend
using their toolchain file.
.. _Android SDK:https://developer.android.com/ndk/guides/cmake
.. _built-in support:https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android
There is further information and examples in the doc/cmake.rst file.
]=======================================================================]
function( android_options )
# Android Options
endfunction()
function( android_generate TARGET_NAME )
target_compile_definitions(${TARGET_NAME}
PUBLIC
ANDROID_ENABLED
UNIX_ENABLED
)
common_compiler_flags( ${TARGET_NAME} )
endfunction()

View File

@ -1,15 +1,76 @@
# Add warnings based on compiler & version #[=======================================================================[.rst:
# Set some helper variables for readability Common Compiler Flags
set( compiler_less_than_v8 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,8>" ) ---------------------
set( compiler_greater_than_or_equal_v9 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,9>" )
set( compiler_greater_than_or_equal_v11 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,11>" ) This file contains a single function to configure platform agnostic compiler
set( compiler_less_than_v11 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,11>" ) flags like optimization levels, warnings, and features. For platform specific
set( compiler_greater_than_or_equal_v12 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,12>" ) flags look to each of the ``cmake/<platform>.cmake`` files.
]=======================================================================]
#Generator Expression Helpers
set( IS_CLANG "$<CXX_COMPILER_ID:Clang>" )
set( IS_APPLECLANG "$<CXX_COMPILER_ID:AppleClang>" )
set( IS_GNU "$<CXX_COMPILER_ID:GNU>" )
set( IS_MSVC "$<CXX_COMPILER_ID:MSVC>" )
set( NOT_MSVC "$<NOT:$<CXX_COMPILER_ID:MSVC>>" )
set( GNU_LT_V8 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,8>" )
set( GNU_GE_V9 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,9>" )
set( GNU_GT_V11 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,11>" )
set( GNU_LT_V11 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,11>" )
set( GNU_GE_V12 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,12>" )
set( HOT_RELOAD-UNSET "$<STREQUAL:${GODOT_USE_HOT_RELOAD},>")
set( DISABLE_EXCEPTIONS "$<BOOL:${GODOT_DISABLE_EXCEPTIONS}>")
function( common_compiler_flags TARGET_NAME )
set( IS_RELEASE "$<STREQUAL:${TARGET_NAME},template_release>")
set( DEBUG_FEATURES "$<OR:$<STREQUAL:${TARGET_NAME},template_debug>,$<STREQUAL:${TARGET_NAME},editor>>" )
set( HOT_RELOAD "$<IF:${HOT_RELOAD-UNSET},$<NOT:${IS_RELEASE}>,$<BOOL:${GODOT_USE_HOT_RELOAD}>>" )
set( DEBUG_SYMBOLS "$<BOOL:${GODOT_DEBUG_SYMBOLS}>" )
target_compile_features(${TARGET_NAME}
PUBLIC
cxx_std_17
)
# These compiler options reflect what is in godot/SConstruct. # These compiler options reflect what is in godot/SConstruct.
target_compile_options( ${PROJECT_NAME} PRIVATE target_compile_options( ${TARGET_NAME}
PUBLIC
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
# saves around 20% of binary size and very significant build time.
$<${DISABLE_EXCEPTIONS}:
$<${NOT_MSVC}:-fno-exceptions>
>
$<$<NOT:${DISABLE_EXCEPTIONS}>:
$<${IS_MSVC}:/EHsc>
>
# Enabling Debug Symbols
$<${DEBUG_SYMBOLS}:
$<${IS_MSVC}: /Zi /FS>
# Adding dwarf-4 explicitly makes stacktraces work with clang builds,
# otherwise addr2line doesn't understand them.
$<${NOT_MSVC}:
-gdwarf-4
$<IF:${IS_DEV},-g3,-g2>
>
>
$<${IS_DEV}:
$<${NOT_MSVC}:-fno-omit-frame-pointer -O0 -g>
>
$<${HOT_RELOAD}:
$<${IS_GNU}:-fno-gnu-unique>
>
# MSVC only # MSVC only
$<${compiler_is_msvc}: $<${IS_MSVC}:
"/MP ${PROC_N}"
/W4 /W4
# Disable warnings which we don't plan to fix. # Disable warnings which we don't plan to fix.
@ -23,10 +84,12 @@ target_compile_options( ${PROJECT_NAME} PRIVATE
/wd4514 # C4514 (unreferenced inline function has been removed) /wd4514 # C4514 (unreferenced inline function has been removed)
/wd4714 # C4714 (function marked as __forceinline not inlined) /wd4714 # C4714 (function marked as __forceinline not inlined)
/wd4820 # C4820 (padding added after construct) /wd4820 # C4820 (padding added after construct)
/utf-8
> >
# Clang and GNU common options # Clang and GNU common options
$<$<OR:${compiler_is_clang},${compiler_is_gnu}>: $<$<OR:${IS_CLANG},${IS_GNU}>:
-Wall -Wall
-Wctor-dtor-privacy -Wctor-dtor-privacy
-Wextra -Wextra
@ -36,13 +99,13 @@ target_compile_options( ${PROJECT_NAME} PRIVATE
> >
# Clang only # Clang only
$<${compiler_is_clang}: $<${IS_CLANG}:
-Wimplicit-fallthrough -Wimplicit-fallthrough
-Wno-ordered-compare-function-pointers -Wno-ordered-compare-function-pointers
> >
# GNU only # GNU only
$<${compiler_is_gnu}: $<${IS_GNU}:
-Walloc-zero -Walloc-zero
-Wduplicated-branches -Wduplicated-branches
-Wduplicated-cond -Wduplicated-cond
@ -50,45 +113,50 @@ target_compile_options( ${PROJECT_NAME} PRIVATE
-Wplacement-new=1 -Wplacement-new=1
-Wshadow-local -Wshadow-local
-Wstringop-overflow=4 -Wstringop-overflow=4
>
$<$<AND:${compiler_is_gnu},${compiler_less_than_v8}>:
# Bogus warning fixed in 8+. # Bogus warning fixed in 8+.
-Wno-strict-overflow $<${GNU_LT_V8}:-Wno-strict-overflow>
>
$<$<AND:${compiler_is_gnu},${compiler_greater_than_or_equal_v9}>: $<${GNU_GE_V9}:-Wattribute-alias=2>
-Wattribute-alias=2
>
$<$<AND:${compiler_is_gnu},${compiler_greater_than_or_equal_v11}>:
# Broke on MethodBind templates before GCC 11. # Broke on MethodBind templates before GCC 11.
-Wlogical-op $<${GNU_GT_V11}:-Wlogical-op>
>
$<$<AND:${compiler_is_gnu},${compiler_less_than_v11}>:
# Regression in GCC 9/10, spams so much in our variadic templates that we need to outright disable it. # Regression in GCC 9/10, spams so much in our variadic templates that we need to outright disable it.
-Wno-type-limits $<${GNU_LT_V11}:-Wno-type-limits>
>
$<$<AND:${compiler_is_gnu},${compiler_greater_than_or_equal_v12}>:
# False positives in our error macros, see GH-58747. # False positives in our error macros, see GH-58747.
-Wno-return-type $<${GNU_GE_V12}:-Wno-return-type>
> >
) )
# Treat warnings as errors target_compile_definitions(${TARGET_NAME}
function( set_warning_as_error ) PUBLIC
message( STATUS "[${PROJECT_NAME}] Treating warnings as errors") GDEXTENSION
if ( CMAKE_VERSION VERSION_GREATER_EQUAL "3.24" )
set_target_properties( ${PROJECT_NAME}
PROPERTIES
COMPILE_WARNING_AS_ERROR ON
)
else()
target_compile_options( ${PROJECT_NAME}
PRIVATE
$<${compiler_is_msvc}:/WX>
$<$<OR:${compiler_is_clang},${compiler_is_gnu}>:-Werror>
)
endif()
endfunction()
if ( GODOT_WARNING_AS_ERROR ) # features
set_warning_as_error() $<${DEBUG_FEATURES}:DEBUG_ENABLED DEBUG_METHODS_ENABLED>
endif()
$<${HOT_RELOAD}:HOT_RELOAD_ENABLED>
$<$<STREQUAL:${GODOT_PRECISION},double>:REAL_T_IS_DOUBLE>
$<${IS_MSVC}:$<${DISABLE_EXCEPTIONS}:_HAS_EXCEPTIONS=0>>
)
target_link_options( ${TARGET_NAME}
PUBLIC
$<${IS_MSVC}:
/WX # treat link warnings as errors.
/MANIFEST:NO # We dont need a manifest
>
$<${DEBUG_SYMBOLS}:$<${IS_MSVC}:/DEBUG:FULL>>
$<$<NOT:${DEBUG_SYMBOLS}>:
$<${IS_GNU}:-s>
$<${IS_CLANG}:-s>
$<${IS_APPLECLANG}:-Wl,-S -Wl,-x -Wl,-dead_strip>
>
)
endfunction()

40
cmake/emsdkHack.cmake Normal file
View File

@ -0,0 +1,40 @@
#[=======================================================================[.rst:
emsdkHack
---------
The Emscripten platform doesn't support the use of shared libraries as known by cmake.
* https://github.com/emscripten-core/emscripten/issues/15276
* https://github.com/emscripten-core/emscripten/issues/17804
This workaround only works due to the way the cmake scripts are loaded.
Prior to the use of ``project( ... )`` directive we need to set
``CMAKE_PROJECT_INCLUDE=cmake/emscripten.cmake``.
This file will be loaded after the toolchain overriding the settings that
prevent shared library building.
CMAKE_PROJECT_INCLUDE was Added in version 3.15.
``CMAKE_PROJECT_<projectName>_INCLUDE`` was Added in version 3.17:
More information on cmake's `code injection`_
.. _code injection:https://cmake.org/cmake/help/latest/command/project.html#code-injection
Overwrite Shared Library Properties to allow shared libs to be generated.
]=======================================================================]
if( EMSCRIPTEN )
set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-sSIDE_MODULE=1")
set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-sSIDE_MODULE=1")
set(CMAKE_SHARED_LIBRARY_SUFFIX) # remove the suffix from the shared lib
set(CMAKE_STRIP FALSE) # used by default in pybind11 on .so modules
# The Emscripten toolchain sets the default value for EMSCRIPTEN_SYSTEM_PROCESSOR to x86
# and CMAKE_SYSTEM_PROCESSOR to this value. I don't want that.
set(CMAKE_SYSTEM_PROCESSOR "wasm32" )
# the above prevents the need for logic like:
#if( ${CMAKE_SYSTEM_NAME} STREQUAL Emscripten )
# set( SYSTEM_ARCH wasm32 )
#endif ()
endif ()

View File

@ -1,13 +1,85 @@
function( godotcpp_options ) #[=======================================================================[.rst:
godotcpp.cmake
--------------
#TODO platform Because these files are included into the top level CMakelists.txt before the
#TODO target project directive, it means that
* ``CMAKE_CURRENT_SOURCE_DIR`` is the location of godot-cpp's CMakeLists.txt
* ``CMAKE_SOURCE_DIR`` is the location where any prior ``project(...)``
directive was
]=======================================================================]
include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/common_compiler_flags.cmake)
include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/android.cmake)
include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/ios.cmake)
include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/linux.cmake)
include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos.cmake)
include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/web.cmake)
include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows.cmake)
#Silence warning from unused CMAKE_C_COMPILER from toolchain
if( CMAKE_C_COMPILER )
endif ()
include(ProcessorCount)
ProcessorCount(PROC_MAX)
message( "Auto-detected ${PROC_MAX} CPU cores available for build parallelism." )
# List of known platforms
set( PLATFORM_LIST linux macos windows android ios web )
# List of known architectures
set( ARCH_LIST universal x86_32 x86_64 arm32 arm64 rv64 ppc32 ppc64 wasm32 )
# Function to map processors to known architectures
function( godot_arch_map ALIAS PROC )
string( TOLOWER "${PROC}" PROC )
if( "${PROC}" IN_LIST ARCH_LIST )
set( ${ALIAS} "${PROC}" PARENT_SCOPE)
return()
endif()
set( x86_64 "w64;amd64" )
set( arm32 "armv7" )
set( arm64 "armv8;arm64v8;aarch64" )
set( rv64 "rv;riscv;riscv64" )
set( ppc32 "ppcle;ppc" )
set( ppc64 "ppc64le" )
if( PROC IN_LIST x86_64 )
set(${ALIAS} "x86_64" PARENT_SCOPE )
elseif( PROC IN_LIST arm32 )
set(${ALIAS} "arm32" PARENT_SCOPE )
elseif( PROC IN_LIST arm64 )
set(${ALIAS} "arm64" PARENT_SCOPE )
elseif( PROC IN_LIST rv64 )
set(${ALIAS} "rv64" PARENT_SCOPE )
elseif( PROC IN_LIST ppc32 )
set(${ALIAS} "ppc32" PARENT_SCOPE )
elseif( PROC IN_LIST ppc64 )
set(${ALIAS} "ppc64" PARENT_SCOPE )
else()
set(${ALIAS} "unknown" PARENT_SCOPE )
endif ()
endfunction()
# Function to define all the options.
function( godotcpp_options )
#NOTE: platform is managed using toolchain files.
# Input from user for GDExtension interface header and the API JSON file # Input from user for GDExtension interface header and the API JSON file
set(GODOT_GDEXTENSION_DIR "gdextension" CACHE PATH set(GODOT_GDEXTENSION_DIR "gdextension" CACHE PATH
"Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )" ) "Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )" )
set(GODOT_CUSTOM_API_FILE "" CACHE FILEPATH 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 )") "Path to a custom GDExtension API JSON file (takes precedence over `GODOT_GDEXTENSION_DIR`) ( /path/to/custom_api_file )")
#TODO generate_bindings #TODO generate_bindings
@ -19,15 +91,22 @@ function( godotcpp_options )
set(GODOT_PRECISION "single" CACHE STRING set(GODOT_PRECISION "single" CACHE STRING
"Set the floating-point precision level (single|double)") "Set the floating-point precision level (single|double)")
#TODO arch # The arch is typically set by the toolchain
# however for Apple multi-arch setting it here will override.
set( GODOT_ARCH "" CACHE STRING "Target CPU Architecture")
set_property( CACHE GODOT_ARCH PROPERTY STRINGS ${ARCH_LIST} )
#TODO threads #TODO threads
#TODO compiledb #TODO compiledb
#TODO compiledb_file #TODO compiledb_file
#TODO build_profile aka cmake preset
#NOTE: build_profile's equivalent in cmake is CMakePresets.json
set(GODOT_USE_HOT_RELOAD "" CACHE BOOL set(GODOT_USE_HOT_RELOAD "" CACHE BOOL
"Enable the extra accounting required to support hot reload. (ON|OFF)") "Enable the extra accounting required to support hot reload. (ON|OFF)")
# 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 ) option(GODOT_DISABLE_EXCEPTIONS "Force disabling exception handling code (ON|OFF)" ON )
set( GODOT_SYMBOL_VISIBILITY "hidden" CACHE STRING set( GODOT_SYMBOL_VISIBILITY "hidden" CACHE STRING
@ -36,48 +115,67 @@ function( godotcpp_options )
#TODO optimize #TODO optimize
#TODO debug_symbols #TODO debug_symbols
#TODO dev_build option( GODOT_DEBUG_SYMBOLS "" OFF )
option( GODOT_DEV_BUILD "Developer build with dev-only debugging code (DEV_ENABLED)" OFF )
# FIXME These options are not present in SCons, and perhaps should be added there. # 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_SYSTEM_HEADERS "Expose headers as SYSTEM." OFF )
option( GODOT_WARNING_AS_ERROR "Treat warnings as errors" OFF ) option( GODOT_WARNING_AS_ERROR "Treat warnings as errors" OFF )
# Run options commands on the following to populate cache for all platforms. # Run options commands on the following to populate cache for all
# This type of thing is typically done conditionally # platforms. This type of thing is typically done conditionally But as
# But as scons shows all options so shall we. # scons shows all options so shall we.
#TODO ios_options() android_options()
#TODO linux_options() ios_options()
#TODO macos_options() linux_options()
#TODO web_options() macos_options()
#TODO windows_options() web_options()
windows_options()
endfunction() endfunction()
# Function to configure and generate the targets
function( godotcpp_generate ) function( godotcpp_generate )
# Set some helper variables for readability #[[ Multi-Threaded MSVC Compilation
set( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" )
set( compiler_is_msvc "$<CXX_COMPILER_ID:MSVC>" )
# CXX_VISIBILITY_PRESET supported values are: default, hidden, protected, and internal When using the MSVC compiler the build command -j <n> only specifies
# which is inline with the gcc -fvisibility= parallel jobs or targets, and not multi-threaded compilation To speed up
# https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html compile times on msvc, the /MP <n> flag can be set. But we need to set it
# To match the scons options we need to change the text to match the -fvisibility flag at configure time.
# it is probably worth another PR which changes both to use the flag options
MSVC is true when the compiler is some version of Microsoft Visual C++ or
another compiler simulating the Visual C++ cl command-line syntax. ]]
if( MSVC )
math( EXPR PROC_N "(${PROC_MAX}-1) | (${X}-2)>>31 & 1" )
message( "Using ${PROC_N} cores for multi-threaded compilation.")
# TODO You can override it at configure time with ...." )
else ()
message( "Using ${CMAKE_BUILD_PARALLEL_LEVEL} cores, You can override"
" it at configure time by using -j <n> or --parallel <n> on the build"
" command.")
message( " eg. cmake --build . -j 7 ...")
endif ()
#[[ GODOT_SYMBOL_VISIBLITY
To match the SCons options, the allowed values are "auto", "visible", and "hidden"
This effects the compiler flag -fvisibility=[default|internal|hidden|protected]
The corresponding CMake option CXX_VISIBILITY_PRESET accepts the compiler values.
TODO: It is probably worth a pull request which changes both to use the compiler values
https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fvisibility
This performs the necessary conversion
]]
if( ${GODOT_SYMBOL_VISIBILITY} STREQUAL "auto" OR ${GODOT_SYMBOL_VISIBILITY} STREQUAL "visible" ) if( ${GODOT_SYMBOL_VISIBILITY} STREQUAL "auto" OR ${GODOT_SYMBOL_VISIBILITY} STREQUAL "visible" )
set( GODOT_SYMBOL_VISIBILITY "default" ) set( GODOT_SYMBOL_VISIBILITY "default" )
endif () endif ()
# Default build type is Debug in the SConstruct # Setup variable to optionally mark headers as SYSTEM
if("${CMAKE_BUILD_TYPE}" STREQUAL "") set(GODOT_SYSTEM_HEADERS_ATTRIBUTE "")
set(CMAKE_BUILD_TYPE Debug) if (GODOT_SYSTEM_HEADERS)
endif() set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM)
# 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 () endif ()
#[[ Generate Bindings ]]
if(NOT DEFINED BITS) if(NOT DEFINED BITS)
set(BITS 32) set(BITS 32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8) if(CMAKE_SIZEOF_VOID_P EQUAL 8)
@ -85,67 +183,26 @@ function( godotcpp_generate )
endif(CMAKE_SIZEOF_VOID_P EQUAL 8) endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
endif() endif()
set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json") set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json")
if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override. if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override.
set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}") set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}")
endif() endif()
if ("${GODOT_PRECISION}" STREQUAL "double") # Code Generation option
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) if(GODOT_GENERATE_TEMPLATE_GET_NODE)
set(GENERATE_BINDING_PARAMETERS "True") set(GENERATE_BINDING_PARAMETERS "True")
else() else()
set(GENERATE_BINDING_PARAMETERS "False") set(GENERATE_BINDING_PARAMETERS "False")
endif() 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)" 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} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GENERATED_FILES_LIST OUTPUT_VARIABLE GENERATED_FILES_LIST
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
) )
add_custom_command(OUTPUT ${GENERATED_FILES_LIST} 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}\")" 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 VERBATIM
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE} MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE}
@ -153,88 +210,87 @@ function( godotcpp_generate )
COMMENT "Generating bindings" COMMENT "Generating bindings"
) )
# Get Sources ### Platform is derived from the toolchain target
# As this cmake file was added using 'include(godotcpp)' from the root CMakeLists.txt, # See GeneratorExpressions PLATFORM_ID and CMAKE_SYSTEM_NAME
# the ${CMAKE_CURRENT_SOURCE_DIR} is still the root dir. set( SYSTEM_NAME
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.c**) $<$<PLATFORM_ID:Android>:android.${ANDROID_ABI}>
file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS include/*.h**) $<$<PLATFORM_ID:iOS>:ios>
$<$<PLATFORM_ID:Linux>:linux>
$<$<PLATFORM_ID:Darwin>:macos>
$<$<PLATFORM_ID:Emscripten>:web>
$<$<PLATFORM_ID:Windows>:windows>
$<$<PLATFORM_ID:Msys>:windows>
)
string(REPLACE ";" "" SYSTEM_NAME "${SYSTEM_NAME}")
# Define our godot-cpp library ### Use the arch from the toolchain if it isn't set manually
add_library(${PROJECT_NAME} STATIC if( GODOT_ARCH )
${SOURCES} set(SYSTEM_ARCH ${GODOT_ARCH})
${HEADERS} else()
godot_arch_map( SYSTEM_ARCH ${CMAKE_SYSTEM_PROCESSOR} )
endif()
### Define our godot-cpp library targets
foreach ( TARGET_NAME template_debug template_release editor )
# Useful genex snippits used in subsequent genex's
set( IS_RELEASE "$<STREQUAL:${TARGET_NAME},template_release>")
set( IS_DEV "$<BOOL:${GODOT_DEV_BUILD}>")
set( DEBUG_FEATURES "$<OR:$<STREQUAL:${TARGET_NAME},template_debug>,$<STREQUAL:${TARGET_NAME},editor>>" )
set( HOT_RELOAD "$<IF:${HOT_RELOAD-UNSET},$<NOT:${IS_RELEASE}>,$<BOOL:${GODOT_USE_HOT_RELOAD}>>" )
# the godot-cpp.* library targets
add_library( ${TARGET_NAME} STATIC ${EXCLUDE} )
add_library( godot-cpp::${TARGET_NAME} ALIAS ${TARGET_NAME} )
file( GLOB_RECURSE GODOTCPP_SOURCES LIST_DIRECTORIES NO CONFIGURE_DEPENDS src/*.cpp )
target_sources( ${TARGET_NAME}
PRIVATE
${GODOTCPP_SOURCES}
${GENERATED_FILES_LIST} ${GENERATED_FILES_LIST}
) )
add_library(godot::cpp ALIAS ${PROJECT_NAME})
include(${PROJECT_SOURCE_DIR}/cmake/common_compiler_flags.cmake) target_include_directories( ${TARGET_NAME} ${GODOT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC
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
$<$<CONFIG:Debug>:
DEBUG_ENABLED
DEBUG_METHODS_ENABLED
>
$<${compiler_is_msvc}:
TYPED_METHOD_BIND
>
)
target_link_options(${PROJECT_NAME} PRIVATE
$<$<NOT:${compiler_is_msvc}>:
-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 include
${CMAKE_CURRENT_BINARY_DIR}/gen/include ${CMAKE_CURRENT_BINARY_DIR}/gen/include
${GODOT_GDEXTENSION_DIR} ${GODOT_GDEXTENSION_DIR}
) )
# Add the compile flags set_target_properties( ${TARGET_NAME}
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 PROPERTIES
CXX_STANDARD 17
CXX_EXTENSIONS OFF CXX_EXTENSIONS OFF
POSITION_INDEPENDENT_CODE ON
CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY} CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY}
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" COMPILE_WARNING_AS_ERROR ${GODOT_WARNING_AS_ERROR}
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" POSITION_INDEPENDENT_CODE ON
OUTPUT_NAME "${OUTPUT_NAME}" BUILD_RPATH_USE_ORIGIN ON
PREFIX lib
OUTPUT_NAME "${PROJECT_NAME}.${SYSTEM_NAME}.${TARGET_NAME}.${SYSTEM_ARCH}"
ARCHIVE_OUTPUT_DIRECTORY "$<1:${CMAKE_BINARY_DIR}/bin>"
# Things that are handy to know for dependent targets
GODOT_PLATFORM "${SYSTEM_NAME}"
GODOT_TARGET "${TARGET_NAME}"
GODOT_ARCH "${SYSTEM_ARCH}"
) )
if( CMAKE_SYSTEM_NAME STREQUAL Android )
android_generate( ${TARGET_NAME} )
elseif ( CMAKE_SYSTEM_NAME STREQUAL iOS )
ios_generate( ${TARGET_NAME} )
elseif ( CMAKE_SYSTEM_NAME STREQUAL Linux )
linux_generate( ${TARGET_NAME} )
elseif ( CMAKE_SYSTEM_NAME STREQUAL Darwin )
macos_generate( ${TARGET_NAME} )
elseif ( CMAKE_SYSTEM_NAME STREQUAL Emscripten )
web_generate( ${TARGET_NAME} )
elseif ( CMAKE_SYSTEM_NAME STREQUAL Windows )
windows_generate( ${TARGET_NAME} )
endif ()
endforeach ()
endfunction() endfunction()

22
cmake/ios.cmake Normal file
View File

@ -0,0 +1,22 @@
#[=======================================================================[.rst:
Ios
---
This file contains functions for options and configuration for targeting the
Ios platform
]=======================================================================]
function(ios_options)
# iOS options
endfunction()
function(ios_generate TARGET_NAME)
target_compile_definitions(${TARGET_NAME}
PUBLIC
IOS_ENABLED
UNIX_ENABLED
)
common_compiler_flags(${TARGET_NAME})
endfunction()

22
cmake/linux.cmake Normal file
View File

@ -0,0 +1,22 @@
#[=======================================================================[.rst:
Linux
-----
This file contains functions for options and configuration for targeting the
Linux platform
]=======================================================================]
function( linux_options )
# Linux Options
endfunction()
function( linux_generate TARGET_NAME )
target_compile_definitions( ${TARGET_NAME}
PUBLIC
LINUX_ENABLED
UNIX_ENABLED
)
common_compiler_flags( ${TARGET_NAME} )
endfunction()

59
cmake/macos.cmake Normal file
View File

@ -0,0 +1,59 @@
#[=======================================================================[.rst:
MacOS
-----
This file contains functions for options and configuration for targeting the
MacOS platform
]=======================================================================]
# Find Requirements
IF(APPLE)
set( CMAKE_OSX_SYSROOT $ENV{SDKROOT} )
find_library( COCOA_LIBRARY REQUIRED
NAMES Cocoa
PATHS ${CMAKE_OSX_SYSROOT}/System/Library
PATH_SUFFIXES Frameworks
NO_DEFAULT_PATH)
ENDIF (APPLE)
function( macos_options )
# macos options here
endfunction()
function( macos_generate TARGET_NAME )
# OSX_ARCHITECTURES does not support generator expressions.
if( NOT GODOT_ARCH OR GODOT_ARCH STREQUAL universal )
set( OSX_ARCH "x86_64;arm64" )
set( SYSTEM_ARCH universal )
else()
set( OSX_ARCH ${GODOT_ARCH} )
endif()
set_target_properties( ${TARGET_NAME}
PROPERTIES
OSX_ARCHITECTURES "${OSX_ARCH}"
)
target_compile_definitions(${TARGET_NAME}
PUBLIC
MACOS_ENABLED
UNIX_ENABLED
)
target_link_options( ${TARGET_NAME}
PUBLIC
-Wl,-undefined,dynamic_lookup
)
target_link_libraries( ${TARGET_NAME}
INTERFACE
${COCOA_LIBRARY}
)
common_compiler_flags( ${TARGET_NAME} )
endfunction()

42
cmake/web.cmake Normal file
View File

@ -0,0 +1,42 @@
#[=======================================================================[.rst:
Web
---
This file contains functions for options and configuration for targeting the
Web platform
]=======================================================================]
# Emscripten requires this hack for use of the SHARED option
set( CMAKE_PROJECT_godot-cpp_INCLUDE cmake/emsdkHack.cmake )
function( web_options )
# web options
endfunction()
function( web_generate TARGET_NAME )
target_compile_definitions(${TARGET_NAME}
PUBLIC
WEB_ENABLED
UNIX_ENABLED
)
target_compile_options( ${TARGET_NAME}
PUBLIC
-sSIDE_MODULE
-sSUPPORT_LONGJMP=wasm
-fno-exceptions
)
target_link_options( ${TARGET_NAME}
INTERFACE
-sWASM_BIGINT
-sSUPPORT_LONGJMP=wasm
-fvisibility=hidden
-shared
)
common_compiler_flags( ${TARGET_NAME} )
endfunction()

63
cmake/windows.cmake Normal file
View File

@ -0,0 +1,63 @@
#[=======================================================================[.rst:
Windows
-------
This file contains functions for options and configuration for targeting the
Windows platform
]=======================================================================]
function( windows_options )
option( GODOT_USE_STATIC_CPP "Link MinGW/MSVC C++ runtime libraries statically" ON )
# The below scons variables are controlled via toolchain files instead
# "mingw_prefix" "MinGW prefix"
# "use_llvm" "Use the LLVM compiler (MVSC or MinGW depending on the use_mingw flag)"
# "use_mingw" "Use the MinGW compiler instead of MSVC - only effective on Windows"
endfunction()
function( windows_generate TARGET_NAME )
set( IS_MSVC "$<CXX_COMPILER_ID:MSVC>" )
set( IS_CLANG "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
set( NOT_MSVC "$<NOT:${IS_MSVC}>" )
set( STATIC_CPP "$<BOOL:${GODOT_USE_STATIC_CPP}>")
set( DISABLE_EXCEPTIONS "$<BOOL:${GODOT_DISABLE_EXCEPTIONS}>")
set_target_properties( ${TARGET_NAME}
PROPERTIES
PDB_OUTPUT_DIRECTORY "$<1:${CMAKE_SOURCE_DIR}/bin>"
)
target_compile_definitions( ${TARGET_NAME}
PUBLIC
WINDOWS_ENABLED
$<${IS_MSVC}:
TYPED_METHOD_BIND
NOMINMAX
>
)
target_compile_options( ${TARGET_NAME}
PUBLIC
$<${IS_MSVC}:
$<IF:${STATIC_CPP},/MT,/MD>$<${IS_DEV}:d> # Link microsoft runtime
>
)
target_link_options( ${TARGET_NAME}
PUBLIC
$<${NOT_MSVC}:
-Wl,--no-undefined
$<${STATIC_CPP}:
-static
-static-libgcc
-static-libstdc++
>
>
$<${IS_CLANG}:-lstdc++>
)
common_compiler_flags( ${TARGET_NAME} )
endfunction()

View File

@ -1,57 +0,0 @@
## 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(<all-my-plugin-related-targets> PROPERTIES CXX_VISIBILITY_PRESET hidden)
```
## Todo
Test build for Windows, Mac and mingw.

331
doc/cmake.rst Normal file
View File

@ -0,0 +1,331 @@
CMake
=====
.. warning::
The CMake scripts do not have feature parity with the SCons ones at this
stage and are still a work in progress. There are a number of people who
have been working on alternative CMake solutions that are frequently
referenced in the discord chats: Ivan's cmake-rewrite_ branch and
Vorlac's godot-roguelite_ Project
.. _cmake-rewrite: https://github.com/IvanInventor/godot-cpp/tree/cmake-rewrite
.. _godot-roguelite: https://github.com/vorlac/godot-roguelite
Introduction
------------
Compiling godot-cpp independently of an extension project is mainly for
godot-cpp developers, package maintainers, and CI/CD. Look to the
godot-cpp-template_ for a practical example on how to consume the godot-cpp
library as part of a Godot extension.
Configuration examples are listed at the bottom of the page.
.. _godot-cpp-template: https://github.com/godotengine/godot-cpp-template
Basic walkthrough
-----------------
.. topic:: Clone the git repository
.. code-block::
git clone https://github.com/godotengine/godot-cpp.git
Cloning into 'godot-cpp'...
...
cd godot-cpp
.. topic:: Out-of-tree build directory
Create a build directory for CMake to put caches and build artifacts in and
change directory to it. This is typically as a sub-directory of the project
root but can be outside the source tree. This is so that generated files do
not clutter up the source tree.
.. code-block::
mkdir cmake-build
cd cmake-build
.. topic:: Configure the build
CMake doesn't build the code, it generates the files that another tool uses
to build the code. To see the list of generators run ``cmake --help``. The
first phase of which is running through the configuration scripts.
Configure and generate Ninja build files.
.. code-block::
cmake ../ -G "Ninja"
To list the available options CMake use the ``-L[AH]`` option. ``A`` is for
advanced, and ``H`` is for help strings.
.. code-block::
cmake ../ -LH
Options are specified on the command line when configuring
.. code-block::
cmake ../ -DGODOT_USE_HOT_RELOAD:BOOL=ON \
-DGODOT_PRECISION:STRING=double \
-DCMAKE_BUILD_TYPE:STRING=Debug
Review setting-build-variables_ and build-configurations_ for more information.
.. _setting-build-variables: https://cmake.org/cmake/help/latest/guide/user-interaction/index.html#setting-build-variables
.. _build-configurations: https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#build-configurations
A non-exhaustive list of options:
.. code-block::
// Path to a custom GDExtension API JSON file (takes precedence over `GODOT_GDEXTENSION_DIR`) ( /path/to/custom_api_file )
`GODOT_CUSTOM_API_FILE:FILEPATH=`
// Force disabling exception handling code (ON|OFF)
GODOT_DISABLE_EXCEPTIONS:BOOL=ON
// Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )
GODOT_GDEXTENSION_DIR:PATH=gdextension
// Generate a template version of the Node class's get_node. (ON|OFF)
GODOT_GENERATE_TEMPLATE_GET_NODE:BOOL=ON
// Set the floating-point precision level (single|double)
GODOT_PRECISION:STRING=single
// Symbols visibility on GNU platforms. Use 'auto' to apply the default value. (auto|visible|hidden)
GODOT_SYMBOL_VISIBILITY:STRING=hidden
// Expose headers as SYSTEM.
GODOT_SYSTEM_HEADERS:BOOL=ON
// Enable the extra accounting required to support hot reload. (ON|OFF)
GODOT_USE_HOT_RELOAD:BOOL=
// Treat warnings as errors
GODOT_WARNING_AS_ERROR:BOOL=OFF
.. topic:: Compiling
A target and a configuration is required, as the default ``all`` target does
not include anything and when using multi-config generators like ``Ninja
Multi-Config``, ``Visual Studio *`` or ``Xcode`` the build configuration
needs to be specified at build time. Build in Release mode unless you need
debug symbols.
.. code-block::
cmake --build . -t template_debug --config Release
Examples
--------
Windows and MSVC
~~~~~~~~~~~~~~~~
So long as CMake is installed from the `CMake Downloads`_ page and in the PATH,
and Microsoft Visual Studio is installed with c++ support, CMake will detect
the MSVC compiler.
.. _CMake downloads: https://cmake.org/download/
Assuming the current working directory is the godot-cpp project root:
.. code-block::
mkdir build-msvc
cd build-msvc
cmake ../
cmake --build . -t godot-cpp-test --config Release
MSys2/clang64, "Ninja", godot-cpp-test target with debug symbols
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Assumes the ming-w64-clang-x86_64-toolchain is installed
Using the msys2/clang64 shell
.. code-block::
mkdir build-clang
cd build-clang
cmake ../ -G"Ninja" -DCMAKE_BUILD_TYPE:STRING=Debug
cmake --build . -t godot-cpp-test
MSys2/clang64, "Ninja Multi-Config", godot-cpp-test target with GODOT_DEV_BUILD
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Assumes the ming-w64-clang-x86_64-toolchain is installed
Using the msys2/clang64 shell
.. code-block::
mkdir build-clang
cd build-clang
cmake ../ -G"Ninja Multi-Config" -DGODOT_DEV_BUILD:BOOL=ON
cmake --build . -t godot-cpp-test --config Debug
Emscripten for web, template_release target
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I've only tested this on windows so far.
I cloned, installed, and activating the latest Emscripten tools(for me it was
3.1.69) to ``c:\emsdk``
From a terminal running the ``c:\emsdk\emcmdprompt.bat`` puts me in a cmdprompt
context which I dislike, so after that I run pwsh to get my powershell 7.4.5
context back.
using the ``emcmake.bat`` command adds the emscripten toolchain to the CMake
command
.. code-block::
C:\emsdk\emcmdprompt.bat
pwsh
cd <godot-cpp source folder>
mkdir build-wasm32
cd build-wasm32
emcmake.bat cmake ../
cmake --build . --verbose -t template_release
Android Cross Compile from Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There are two separate paths you can choose when configuring for android.
Use the ``CMAKE_ANDROID_*`` variables specified on the commandline or in your
own toolchain file as listed in the cmake-toolchains_ documentation
.. _cmake-toolchains: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android-with-the-ndk
Or use the toolchain and scripts provided by the Android SDK and make changes
using the ``ANDROID_*`` variables listed there. Where ``<version>`` is whatever
ndk version you have installed ( tested with `23.2.8568313`) and ``<platform>``
is for android sdk platform, (tested with ``android-29``)
.. warning::
The Android SDK website explicitly states that they do not support using
the CMake built-in method, and recommends you stick with their toolchain
files.
.. topic:: Using your own toolchain file as described in the CMake documentation
.. code-block::
mkdir build-android
cd build-android
cmake ../ --toolchain my_toolchain.cmake
cmake --build . -t template_release
Doing the equivalent on just using the command line
.. code-block::
mkdir build-android
cd build-android
cmake ../ \
-DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=<platform> \
-DCMAKE_ANDROID_ARCH_ABI=<arch> \
-DCMAKE_ANDROID_NDK=/path/to/android-ndk
cmake --build . -t template_release
.. topic:: Using the toolchain file from the Android SDK
Defaults to minimum supported version( android-16 in my case) and armv7-a.
.. code-block::
mkdir build-android
cd build-android
cmake ../ --toolchain $ANDROID_HOME/ndk/<version>/build/cmake/android.toolchain.cmake
cmake --build . -t template_release
Specify Android platform and ABI
.. code-block::
mkdir build-android
cd build-android
cmake ../ --toolchain $ANDROID_HOME/ndk/<version>/build/cmake/android.toolchain.cmake \
-DANDROID_PLATFORM:STRING=android-29 \
-DANDROID_ABI:STRING=armeabi-v7a
cmake --build . -t template_release
Toolchains
----------
This section attempts to list the host and target combinations that have been
at tested.
Info on cross compiling triplets indicates that the naming is a little more
freeform that expected, and tailored to its use case. Triplets tend to have the
format ``<arch>[sub][-vendor][-OS][-env]``
* `osdev.org <https://wiki.osdev.org/Target_Triplet>`_
* `stack overflow <https://stackoverflow.com/questions/13819857/does-a-list-of-all-known-target-triplets-in-use-exist>`_
* `LLVM <https://llvm.org/doxygen/classllvm_1_1Triple.html>`_
* `clang target triple <https://clang.llvm.org/docs/CrossCompilation.html#target-triple>`_
* `vcpkg <https://learn.microsoft.com/en-us/vcpkg/concepts/triplets>`_
* `wasm32-unknown-emscripten <https://blog.therocode.net/2020/10/a-guide-to-rust-sdl2-emscripten>`_
Linux Host
~~~~~~~~~~
:Target: x86_64-linux
Macos Host
~~~~~~~~~~
:System: Mac Mini
:OS Name: Sequoia 15.0.1
:Processor: Apple M2
Windows Host
~~~~~~~~~~~~
:OS Name: Microsoft Windows 11 Home, 10.0.22631 N/A Build 22631
:Processor: AMD Ryzen 7 6800HS Creator Edition
`Microsoft Visual Studio 17 2022 <https://visualstudio.microsoft.com/vs/>`_
:Target: x86_64-w64
`LLVM <https://llvm.org/>`_
:Target: x86_64-pc-windows-msvc
`AndroidSDK <https://developer.android.com/studio/#command-tools>`_
armv7-none-linux-androideabi16
`Emscripten <https://emscripten.org/>`_
:Compiler: Emscripten
:Target: wasm32-unknown-emscripten
`MinGW-w64 <https://www.mingw-w64.org/>`_ based toolchains
`MSYS2 <https://www.msys2.org/>`_
Necessary reading about MSYS2 `environments <https://www.msys2.org/docs/environments/>`_
ucrt64
:Compiler: gcc version 14.2.0 (Rev1, Built by MSYS2 project)
:Target: x86_64-w64-mingw32
clang64
:Compiler: clang version 18.1.8
:Target: x86_64-w64-windows-gnu
`LLVM-MinGW <https://github.com/mstorsjo/llvm-mingw/releases>`_
`MinGW-W64-builds <https://github.com/niXman/mingw-builds-binaries/releases>`_
:Compiler: gcc
:Target: x86_64-w64-mingw32-ucrt
`Jetbrains-CLion <https://www.jetbrains.com/clion/>`_
:Target: x86_64-w64-mingw32-msvcrt

View File

@ -1,144 +1,67 @@
cmake_minimum_required(VERSION 3.13) # Testing Extension
project(godot-cpp-test) # This is only linked to the template_release config.
# so it requires the template_release version of godot to run.
set(GODOT_GDEXTENSION_DIR ../gdextension/ CACHE STRING "Path to GDExtension interface header directory") add_library( godot-cpp-test SHARED EXCLUDE_FROM_ALL )
set(CPP_BINDINGS_PATH ../ CACHE STRING "Path to C++ bindings")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux") target_sources( godot-cpp-test
set(TARGET_PATH x11)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(TARGET_PATH win64)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(TARGET_PATH macos)
else()
message(FATAL_ERROR "Not implemented support for ${CMAKE_SYSTEM_NAME}")
endif()
# Change the output directory to the bin directory
set(BUILD_PATH ${CMAKE_SOURCE_DIR}/bin/${TARGET_PATH})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${BUILD_PATH}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PATH}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BUILD_PATH}")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}")
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}")
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}")
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}")
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}")
# Set the c++ standard to c++17
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(GODOT_COMPILE_FLAGS )
set(GODOT_LINKER_FLAGS )
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /WX") # /GF /MP
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /DTYPED_METHOD_BIND")
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /utf-8")
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)
# Disable conversion warning, truncation, unreferenced var, signed mismatch
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /wd4244 /wd4305 /wd4101 /wd4018 /wd4267")
add_definitions(-DNOMINMAX)
# Unkomment for warning level 4
#if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
# string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
#endif()
else()
set(GODOT_LINKER_FLAGS "-static-libgcc -static-libstdc++ -Wl,-R,'$$ORIGIN'")
set(GODOT_COMPILE_FLAGS "-fPIC -g -Wwrite-strings")
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0")
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 ON "Force disabling exception handling code")
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()
# Get Sources
file(GLOB_RECURSE SOURCES src/*.c**)
file(GLOB_RECURSE HEADERS include/*.h**)
# Define our godot-cpp library
add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} SYSTEM
PRIVATE PRIVATE
${CPP_BINDINGS_PATH}/include src/example.cpp
${CPP_BINDINGS_PATH}/gen/include src/example.h
${GODOT_GDEXTENSION_DIR} src/register_types.cpp
src/register_types.h
src/tests.h
) )
# Create the correct name (godot.os.build_type.system_bits) set( TEST_TARGET "template_debug" CACHE STRING "Which godot-cpp::target to link against" )
# Synchronized with godot-cpp's CMakeLists.txt set_property( CACHE TEST_TARGET PROPERTY STRINGS "template_debug;template_release;editor" )
set(BITS 32) target_link_libraries( godot-cpp-test
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(BITS 64)
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(GODOT_CPP_BUILD_TYPE Debug)
else()
set(GODOT_CPP_BUILD_TYPE Release)
endif()
string(TOLOWER ${CMAKE_SYSTEM_NAME} SYSTEM_NAME)
string(TOLOWER ${GODOT_CPP_BUILD_TYPE} BUILD_TYPE)
if(ANDROID)
# Added the android abi after system name
set(SYSTEM_NAME ${SYSTEM_NAME}.${ANDROID_ABI})
endif()
if(CMAKE_VERSION VERSION_GREATER "3.13")
target_link_directories(${PROJECT_NAME}
PRIVATE PRIVATE
${CPP_BINDINGS_PATH}/bin/ godot-cpp::${TEST_TARGET} )
### Get useful properties of the library
get_target_property( GODOT_PLATFORM godot-cpp::${TEST_TARGET} GODOT_PLATFORM )
get_target_property( GODOT_TARGET godot-cpp::${TEST_TARGET} GODOT_TARGET )
get_target_property( GODOT_ARCH godot-cpp::${TEST_TARGET} GODOT_ARCH )
set( OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/project/bin/" )
set_target_properties( godot-cpp-test
PROPERTIES
CXX_STANDARD 17
CXX_EXTENSIONS OFF
CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY}
POSITION_INDEPENDENT_CODE ON
BUILD_RPATH_USE_ORIGIN ON
LINK_SEARCH_START_STATIC ON
LINK_SEARCH_END_STATIC ON
# NOTE: Wrapping the output variables inside a generator expression
# prevents msvc generator from adding addition Config Directories
LIBRARY_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>"
RUNTIME_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>"
PDB_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>" #MSVC Only, ignored on other platforms
PREFIX "lib"
OUTPUT_NAME "gdexample.${GODOT_PLATFORM}.${GODOT_TARGET}.${GODOT_ARCH}"
) )
target_link_libraries(${PROJECT_NAME} if( CMAKE_SYSTEM_NAME STREQUAL Darwin )
godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}$<$<NOT:$<PLATFORM_ID:Android>>:.${BITS}> get_target_property( OSX_ARCH godot-cpp::${TEST_TARGET} OSX_ARCHITECTURES )
)
else() set( OUTPUT_DIR "${OUTPUT_DIR}/libgdexample.macos.${TEST_TARGET}.framework")
target_link_libraries(${PROJECT_NAME}
${CPP_BINDINGS_PATH}/bin/libgodot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}$<$<NOT:$<PLATFORM_ID:Android>>:.${BITS}>.a set_target_properties( godot-cpp-test
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>"
RUNTIME_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>"
OUTPUT_NAME "gdexample.macos.${TEST_TARGET}"
SUFFIX ""
#macos options
OSX_ARCHITECTURES "${OSX_ARCH}"
) )
endif () endif ()
# Add the compile flags
set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS ${GODOT_COMPILE_FLAGS})
set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY LINK_FLAGS ${GODOT_LINKER_FLAGS})
set_property(TARGET ${PROJECT_NAME} PROPERTY OUTPUT_NAME "gdexample")