diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6580de90f..35c6462e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -202,8 +202,8 @@ jobs: run: | mkdir cmake-build cd cmake-build - cmake ../ -DTEST_TARGET=template_release - cmake --build . --verbose -j $(nproc) -t godot-cpp-test --config Release + cmake ../ -DGODOT_ENABLE_TESTING=YES + cmake --build . --verbose -j $(nproc) -t godot-cpp.test.template_release --config Release windows-msvc-cmake: name: 🏁 Build (Windows, MSVC, CMake) @@ -218,5 +218,5 @@ jobs: run: | mkdir cmake-build cd cmake-build - cmake ../ -DTEST_TARGET=template_release - cmake --build . --verbose -t godot-cpp-test --config Release + cmake ../ -DGODOT_ENABLE_TESTING=YES + cmake --build . --verbose -t godot-cpp.test.template_release --config Release diff --git a/CMakeLists.txt b/CMakeLists.txt index fa2f1cc97..68bcb7b11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ The CMake equivalent is below. ]=======================================================================] include( cmake/godotcpp.cmake ) + godotcpp_options() #[[ Python is required for code generation ]] @@ -53,5 +54,12 @@ project( godot-cpp compiler_detection() godotcpp_generate() -# Test Example -add_subdirectory( test ) +# Conditionally enable the godot-cpp.test. integration testing targets +if( GODOT_ENABLE_TESTING ) + add_subdirectory( test ) +endif() + +# If this is the top level CMakeLists.txt, Generators which honor the +# USE_FOLDERS flag will organize godot-cpp targets under the subfolder +# 'godot-cpp'. This is enable by default from CMake version 3.26 +set_property(GLOBAL PROPERTY USE_FOLDERS ON) diff --git a/cmake/android.cmake b/cmake/android.cmake index 2227f89ce..d3d95ee50 100644 --- a/cmake/android.cmake +++ b/cmake/android.cmake @@ -29,13 +29,12 @@ function( android_options ) # Android Options endfunction() -function( android_generate TARGET_NAME ) - +function( android_generate ) target_compile_definitions(${TARGET_NAME} PUBLIC ANDROID_ENABLED UNIX_ENABLED ) - common_compiler_flags( ${TARGET_NAME} ) + common_compiler_flags() endfunction() diff --git a/cmake/common_compiler_flags.cmake b/cmake/common_compiler_flags.cmake index ac3f4490d..e6954216e 100644 --- a/cmake/common_compiler_flags.cmake +++ b/cmake/common_compiler_flags.cmake @@ -44,7 +44,7 @@ function( compiler_detection ) endif () endfunction( ) -function( common_compiler_flags TARGET_NAME ) +function( common_compiler_flags ) target_compile_features(${TARGET_NAME} PUBLIC diff --git a/cmake/godotcpp.cmake b/cmake/godotcpp.cmake index 9bad5ae0d..9f96504fa 100644 --- a/cmake/godotcpp.cmake +++ b/cmake/godotcpp.cmake @@ -142,6 +142,9 @@ function( godotcpp_options ) option( GODOT_SYSTEM_HEADERS "Expose headers as SYSTEM." OFF ) option( GODOT_WARNING_AS_ERROR "Treat warnings as errors" OFF ) + # Enable Testing + option( GODOT_ENABLE_TESTING "Enable the godot-cpp.test. integration testing targets" OFF ) + #[[ Target Platform Options ]] android_options() ios_options() @@ -263,7 +266,8 @@ function( godotcpp_generate ) set( DEV_TAG "$<${IS_DEV_BUILD}:.dev>" ) ### Define our godot-cpp library targets - foreach ( TARGET_NAME template_debug template_release editor ) + foreach ( TARGET_ALIAS template_debug template_release editor ) + set( TARGET_NAME "godot-cpp.${TARGET_ALIAS}" ) # Generator Expressions that rely on the target set( DEBUG_FEATURES "$>" ) @@ -271,7 +275,7 @@ function( godotcpp_generate ) # the godot-cpp.* library targets add_library( ${TARGET_NAME} STATIC EXCLUDE_FROM_ALL ) - add_library( godot-cpp::${TARGET_NAME} ALIAS ${TARGET_NAME} ) + add_library( godot-cpp::${TARGET_ALIAS} ALIAS ${TARGET_NAME} ) file( GLOB_RECURSE GODOTCPP_SOURCES LIST_DIRECTORIES NO CONFIGURE_DEPENDS src/*.cpp ) @@ -298,33 +302,36 @@ function( godotcpp_generate ) BUILD_RPATH_USE_ORIGIN ON PREFIX lib - OUTPUT_NAME "${PROJECT_NAME}.${SYSTEM_NAME}.${TARGET_NAME}${DEV_TAG}.${SYSTEM_ARCH}" + OUTPUT_NAME "${PROJECT_NAME}.${SYSTEM_NAME}.${TARGET_ALIAS}${DEV_TAG}.${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_TARGET "${TARGET_ALIAS}" GODOT_ARCH "${SYSTEM_ARCH}" + + # Some IDE's respect this property to logically group targets + FOLDER "godot-cpp" ) if( CMAKE_SYSTEM_NAME STREQUAL Android ) - android_generate( ${TARGET_NAME} ) + android_generate() elseif ( CMAKE_SYSTEM_NAME STREQUAL iOS ) - ios_generate( ${TARGET_NAME} ) + ios_generate() elseif ( CMAKE_SYSTEM_NAME STREQUAL Linux ) - linux_generate( ${TARGET_NAME} ) + linux_generate() elseif ( CMAKE_SYSTEM_NAME STREQUAL Darwin ) - macos_generate( ${TARGET_NAME} ) + macos_generate() elseif ( CMAKE_SYSTEM_NAME STREQUAL Emscripten ) - web_generate( ${TARGET_NAME} ) + web_generate() elseif ( CMAKE_SYSTEM_NAME STREQUAL Windows ) - windows_generate( ${TARGET_NAME} ) + windows_generate() endif () endforeach () # Added for backwards compatibility with prior cmake solution so that builds dont immediately break # from a missing target. - add_library( godot::cpp ALIAS template_debug ) + add_library( godot::cpp ALIAS godot-cpp.template_debug ) endfunction() diff --git a/cmake/ios.cmake b/cmake/ios.cmake index bb9642210..a4c570577 100644 --- a/cmake/ios.cmake +++ b/cmake/ios.cmake @@ -10,13 +10,12 @@ function(ios_options) # iOS options endfunction() -function(ios_generate TARGET_NAME) - +function(ios_generate) target_compile_definitions(${TARGET_NAME} PUBLIC IOS_ENABLED UNIX_ENABLED ) - common_compiler_flags(${TARGET_NAME}) + common_compiler_flags() endfunction() diff --git a/cmake/linux.cmake b/cmake/linux.cmake index fae620e0e..15855099e 100644 --- a/cmake/linux.cmake +++ b/cmake/linux.cmake @@ -10,13 +10,12 @@ function( linux_options ) # Linux Options endfunction() -function( linux_generate TARGET_NAME ) - +function( linux_generate ) target_compile_definitions( ${TARGET_NAME} PUBLIC LINUX_ENABLED UNIX_ENABLED ) - common_compiler_flags( ${TARGET_NAME} ) + common_compiler_flags() endfunction() diff --git a/cmake/macos.cmake b/cmake/macos.cmake index 1bb4dbcfb..6cb33bcc7 100644 --- a/cmake/macos.cmake +++ b/cmake/macos.cmake @@ -23,7 +23,7 @@ function( macos_options ) endfunction() -function( macos_generate TARGET_NAME ) +function( macos_generate ) # OSX_ARCHITECTURES does not support generator expressions. if( NOT GODOT_ARCH OR GODOT_ARCH STREQUAL universal ) @@ -55,5 +55,5 @@ function( macos_generate TARGET_NAME ) ${COCOA_LIBRARY} ) - common_compiler_flags( ${TARGET_NAME} ) + common_compiler_flags() endfunction() diff --git a/cmake/web.cmake b/cmake/web.cmake index b7d6c13aa..8ccd28f2d 100644 --- a/cmake/web.cmake +++ b/cmake/web.cmake @@ -15,8 +15,7 @@ function( web_options ) endfunction() -function( web_generate TARGET_NAME ) - +function( web_generate ) target_compile_definitions(${TARGET_NAME} PUBLIC WEB_ENABLED @@ -38,5 +37,5 @@ function( web_generate TARGET_NAME ) -shared ) - common_compiler_flags( ${TARGET_NAME} ) + common_compiler_flags() endfunction() diff --git a/cmake/windows.cmake b/cmake/windows.cmake index fd07bd188..4dc064036 100644 --- a/cmake/windows.cmake +++ b/cmake/windows.cmake @@ -58,7 +58,7 @@ function( windows_options ) endfunction() #[===========================[ Target Generation ]===========================] -function( windows_generate TARGET_NAME ) +function( windows_generate ) set( STATIC_CPP "$") set( DEBUG_CRT "$" ) @@ -96,5 +96,5 @@ function( windows_generate TARGET_NAME ) $<${IS_CLANG}:-lstdc++> ) - common_compiler_flags( ${TARGET_NAME} ) + common_compiler_flags() endfunction() diff --git a/doc/cmake.rst b/doc/cmake.rst index f604e78a6..59c11dae3 100644 --- a/doc/cmake.rst +++ b/doc/cmake.rst @@ -38,6 +38,27 @@ the notable differences. Does not define NDEBUG when disabled, NDEBUG is set via Release-like CMake build configurations; Release, MinSizeRel. +Testing Integration +------------------- +When consuming a third party CMake project into yours, an unfortunate side +effect is that the targets of the consumed project appear in the list of +available targets, and are by default included in the ALL meta target +created by most build systems. For this reason, all the targets specified +in godot-cpp are marked with the ``EXCLUDE_FROM_ALL`` tag to prevent +unnecessary compilation. The testing targets ``godot-cpp.test.`` +are also guarded by ``GODOT_ENABLE_TESTING`` which is off by default. + +To configure and build the godot-cpp project to enable the integration +testing targets the command will look something like: + +.. code-block:: + + # Assuming our current directory is the godot-cpp source root + mkdir cmake-build + cd cmake-build + cmake .. -DGODOT_ENABLE_TESTING=YES + cmake --build . --target godot-cpp.test.template_debug + Basic walkthrough ----------------- @@ -73,20 +94,20 @@ Basic walkthrough .. code-block:: - cmake ../ -G "Ninja" + 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 + cmake .. -LH Options are specified on the command line when configuring .. code-block:: - cmake ../ -DGODOT_USE_HOT_RELOAD:BOOL=ON \ + cmake .. -DGODOT_USE_HOT_RELOAD:BOOL=ON \ -DGODOT_PRECISION:STRING=double \ -DCMAKE_BUILD_TYPE:STRING=Debug @@ -137,78 +158,85 @@ Basic walkthrough .. code-block:: - cmake --build . -t template_debug --config Release + cmake --build . -t template_debug --config Debug Examples -------- -Windows and MSVC -~~~~~~~~~~~~~~~~ +Windows and MSVC - Release +~~~~~~~~~~~~~~~~~~~~~~~~~~ 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/ +Remembering that Visual Studio is a Multi-Config Generator so the build type +needs to be specified at build time. -Assuming the current working directory is the godot-cpp project root: +.. _CMake downloads: https://cmake.org/download/ .. code-block:: + # Assuming our current directory is the godot-cpp source root mkdir build-msvc cd build-msvc - cmake ../ - cmake --build . -t godot-cpp-test --config Release + cmake .. -DGODOT_ENABLE_TESTING=YES + cmake --build . -t godot-cpp.test.template_debug --config Debug -MSys2/clang64, "Ninja", godot-cpp-test target with debug symbols -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +MSys2/clang64, "Ninja" - Debug +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Assumes the ming-w64-clang-x86_64-toolchain is installed +Remembering that Ninja is a Single-Config Generator so the build type +needs to be specified at Configure time. + Using the msys2/clang64 shell .. code-block:: + # Assuming our current directory is the godot-cpp source root mkdir build-clang cd build-clang - cmake ../ -G"Ninja" -DCMAKE_BUILD_TYPE:STRING=Debug - cmake --build . -t godot-cpp-test + cmake .. -G"Ninja" -DGODOT_ENABLE_TESTING=YES -DCMAKE_BUILD_TYPE=Debug + cmake --build . -t godot-cpp.test.template_debug -MSys2/clang64, "Ninja Multi-Config", godot-cpp-test target with GODOT_DEV_BUILD -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +MSys2/clang64, "Ninja Multi-Config" - dev_build, Debug Symbols +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Assumes the ming-w64-clang-x86_64-toolchain is installed +This time we are choosing the 'Ninja Multi-Config' generator, so the build +type is specified at build time. + Using the msys2/clang64 shell .. code-block:: + # Assuming our current directory is the godot-cpp source root mkdir build-clang cd build-clang - cmake ../ -G"Ninja Multi-Config" -DGODOT_DEV_BUILD:BOOL=ON - cmake --build . -t godot-cpp-test --config Debug + cmake .. -G"Ninja Multi-Config" -DGODOT_ENABLE_TESTING=YES -DGODOT_DEV_BUILD:BOOL=ON + cmake --build . -t godot-cpp.test.template_debug --config Debug -Emscripten for web, template_release target -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Emscripten for web platform +~~~~~~~~~~~~~~~~~~~~~~~~~~~ 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`` +I cloned and installed the latest Emscripten tools to ``c:\emsdk`` +At the time of writing that was v3.1.69 -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. +I've been using ``C:\emsdk\emsdk.ps1 activate latest`` to enable the +environment from powershell in the current shell. -using the ``emcmake.bat`` command adds the emscripten toolchain to the CMake -command +The ``emcmake.bat`` utility adds the emscripten toolchain to the CMake command .. code-block:: - C:\emsdk\emcmdprompt.bat - pwsh - cd + # Assuming our current directory is the godot-cpp source root + C:\emsdk\emsdk.ps1 activate latest mkdir build-wasm32 cd build-wasm32 emcmake.bat cmake ../ - cmake --build . --verbose -t template_release + cmake --build . --target template_release Android Cross Compile from Windows ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -221,7 +249,7 @@ own toolchain file as listed in the cmake-toolchains_ documentation Or use the toolchain and scripts provided by the Android SDK and make changes using the ``ANDROID_*`` variables listed there. Where ```` is whatever -ndk version you have installed ( tested with `23.2.8568313`) and ```` +ndk version you have installed (tested with `23.2.8568313`) and ```` is for android sdk platform, (tested with ``android-29``) .. warning:: @@ -234,18 +262,20 @@ is for android sdk platform, (tested with ``android-29``) .. code-block:: + # Assuming our current directory is the godot-cpp source root mkdir build-android cd build-android - cmake ../ --toolchain my_toolchain.cmake + cmake .. --toolchain my_toolchain.cmake cmake --build . -t template_release Doing the equivalent on just using the command line .. code-block:: + # Assuming our current directory is the godot-cpp source root mkdir build-android cd build-android - cmake ../ \ + cmake .. \ -DCMAKE_SYSTEM_NAME=Android \ -DCMAKE_SYSTEM_VERSION= \ -DCMAKE_ANDROID_ARCH_ABI= \ @@ -258,20 +288,22 @@ is for android sdk platform, (tested with ``android-29``) .. code-block:: + # Assuming our current directory is the godot-cpp source root mkdir build-android cd build-android - cmake ../ --toolchain $ANDROID_HOME/ndk//build/cmake/android.toolchain.cmake + cmake .. --toolchain $ANDROID_HOME/ndk//build/cmake/android.toolchain.cmake cmake --build . -t template_release Specify Android platform and ABI .. code-block:: + # Assuming our current directory is the godot-cpp source root mkdir build-android cd build-android - cmake ../ --toolchain $ANDROID_HOME/ndk//build/cmake/android.toolchain.cmake \ - -DANDROID_PLATFORM:STRING=android-29 \ - -DANDROID_ABI:STRING=armeabi-v7a + cmake .. --toolchain $ANDROID_HOME/ndk//build/cmake/android.toolchain.cmake \ + -DANDROID_PLATFORM:STRING=android-29 \ + -DANDROID_ABI:STRING=armeabi-v7a cmake --build . -t template_release diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 12e44f163..d13a2bf01 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,68 +1,81 @@ -# Testing Extension -# This is only linked to the template_release config. -# so it requires the template_release version of godot to run. - -add_library( godot-cpp-test SHARED EXCLUDE_FROM_ALL ) - -target_sources( godot-cpp-test - PRIVATE - src/example.cpp - src/example.h - src/register_types.cpp - src/register_types.h - src/tests.h -) - -set( TEST_TARGET "template_debug" CACHE STRING "Which godot-cpp::target to link against" ) -set_property( CACHE TEST_TARGET PROPERTY STRINGS "template_debug;template_release;editor" ) - -target_link_libraries( godot-cpp-test - PRIVATE - 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( DEV_TAG "$<$:.dev>" ) - -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}${DEV_TAG}.${GODOT_ARCH}" -) - -if( CMAKE_SYSTEM_NAME STREQUAL Darwin ) - get_target_property( OSX_ARCH godot-cpp::${TEST_TARGET} OSX_ARCHITECTURES ) - - set( OUTPUT_DIR "${OUTPUT_DIR}/libgdexample.macos.${TEST_TARGET}.framework") - - set_target_properties( godot-cpp-test +#[=======================================================================[.rst: +Integration Testing +------------------- + +The Test target used to validate changes in the GitHub CI. + +]=======================================================================] + +message( STATUS "Testing Integration targets are enabled.") + +foreach( TARGET_ALIAS template_debug template_release editor ) + set( TARGET_NAME "godot-cpp.test.${TARGET_ALIAS}" ) + set( LINK_TARGET "godot-cpp::${TARGET_ALIAS}" ) + + add_library( ${TARGET_NAME} SHARED EXCLUDE_FROM_ALL ) + + target_sources( ${TARGET_NAME} + PRIVATE + src/example.cpp + src/example.h + src/register_types.cpp + src/register_types.h + src/tests.h + ) + + target_link_libraries( ${TARGET_NAME} PRIVATE ${LINK_TARGET} ) + + ### Get useful properties of the library + get_target_property( GODOT_PLATFORM ${LINK_TARGET} GODOT_PLATFORM ) + get_target_property( GODOT_TARGET ${LINK_TARGET} GODOT_TARGET ) + get_target_property( GODOT_ARCH ${LINK_TARGET} GODOT_ARCH ) + + set( OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/project/bin/" ) + set( DEV_TAG "$<$:.dev>" ) + + set_target_properties( ${TARGET_NAME} PROPERTIES + CXX_STANDARD 17 + CXX_EXTENSIONS OFF + CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY} + + POSITION_INDEPENDENT_CODE ON + BUILD_RPATH_USE_ORIGIN ON + + # Try to ensure only static libraries are selected to be linked to. + 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 - OUTPUT_NAME "gdexample.macos.${TEST_TARGET}${DEV_TAG}" - SUFFIX "" + PREFIX "lib" + OUTPUT_NAME "gdexample.${GODOT_PLATFORM}.${GODOT_TARGET}${DEV_TAG}.${GODOT_ARCH}" - #macos options - OSX_ARCHITECTURES "${OSX_ARCH}" + # Some IDE's respect this property to logically group targets + FOLDER "godot-cpp" ) -endif () + + # CMAKE_SYSTEM_NAME refers to the target system + if( CMAKE_SYSTEM_NAME STREQUAL Darwin ) + get_target_property( OSX_ARCH ${LINK_TARGET} OSX_ARCHITECTURES ) + + set( OUTPUT_DIR "${OUTPUT_DIR}/libgdexample.macos.${TEST_TARGET}.framework") + + set_target_properties( ${TARGET_NAME} + PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>" + RUNTIME_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>" + + OUTPUT_NAME "gdexample.macos.${TEST_TARGET}${DEV_TAG}" + SUFFIX "" + + #macos options + OSX_ARCHITECTURES "${OSX_ARCH}" + ) + endif () + +endforeach()