diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76abdd570..8c733093d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,78 +13,162 @@ concurrency: jobs: build: - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} + name: "${{ matrix.platform.name }} (${{ matrix.builder.name }}, ${{matrix.platform.description}})" + runs-on: ${{ matrix.platform.os }} strategy: fail-fast: false matrix: - include: - - name: 🐧 Linux (GCC) + + # TODO: remove after CMake IOS config is ready + exclude: + - builder: + name: CMake + + platform: + name: 🍏 iOS + + builder: + - name: SCons + generate_sources: | + scons {0} build_library=no verbose=yes + scons -c + + build_godot_cpp_debug: | + scons {0} target=template_debug verbose=yes + + build_debug: | + cd test + scons {0} target=template_debug build_library=no debug_symbols=yes optimize=debug verbose=yes + + build_release: | + cd test + scons {0} target=template_release verbose=yes + + - name: CMake + generate_sources: | + cmake {0} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -B build test + + build_godot_cpp_debug: | + cmake --build build --config Debug --target godot-cpp -v + + build_debug: | + cmake --build build --config Debug -v + + build_release: | + cmake {0} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DGODOT_TARGET=template_release -B build_release test + cmake --build build_release --config Release -v + + platform: + - name: 🐧 Linux + description: 'GCC' os: ubuntu-20.04 platform: linux artifact-name: godot-cpp-linux-glibc2.27-x86_64-release - artifact-path: bin/libgodot-cpp.linux.template_release.x86_64.a + artifact-path: + SCons: bin/libgodot-cpp.linux.template_release.x86_64.a + CMake: build_release/godot-cpp/bin/Release/libgodot-cpp.linux.template_release.x86_64.a + flags: + SCons: platform=linux + CMake: -G "Ninja Multi-Config" run-tests: true cache-name: linux-x86_64 - - name: 🐧 Linux (GCC, Double Precision) + - name: 🐧 Linux + description: 'GCC, Double Precision' os: ubuntu-20.04 platform: linux artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release - artifact-path: bin/libgodot-cpp.linux.template_release.double.x86_64.a - flags: precision=double + artifact-path: + SCons: bin/libgodot-cpp.linux.template_release.double.x86_64.a + CMake: build_release/godot-cpp/bin/Release/libgodot-cpp.linux.template_release.double.x86_64.a + flags: + SCons: platform=linux precision=double + CMake: -G "Ninja Multi-Config" -DGODOT_PRECISION=double run-tests: false cache-name: linux-x86_64-f64 - - name: 🏁 Windows (x86_64, MSVC) + - name: 🏁 Windows + description: 'x86_64, MSVC' os: windows-2019 platform: windows artifact-name: godot-cpp-windows-msvc2019-x86_64-release - artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.lib + artifact-path: + SCons: bin/libgodot-cpp.windows.template_release.x86_64.lib + CMake: build_release/godot-cpp/bin/Release/godot-cpp.windows.template_release.x86_64.lib + flags: + Scons: platform=windows + CMake: '-G "Visual Studio 16 2019" -A x64 -DCMAKE_VERBOSE_MAKEFILE=TRUE' run-tests: false cache-name: windows-x86_64-msvc - - name: 🏁 Windows (x86_64, MinGW) + - name: 🏁 Windows + description: 'x86_64, MinGW' os: windows-2019 platform: windows artifact-name: godot-cpp-linux-mingw-x86_64-release - artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.a - flags: use_mingw=yes + artifact-path: + SCons: bin/libgodot-cpp.windows.template_release.x86_64.a + CMake: build_release/godot-cpp/bin/Release/libgodot-cpp.windows.template_release.x86_64.a + flags: + SCons: platform=windows use_mingw=yes + CMake: -G "Ninja Multi-Config" + use-mingw: true run-tests: false cache-name: windows-x86_64-mingw - - name: 🍎 macOS (universal) + - name: 🍎 macOS + description: 'universal' os: macos-latest platform: macos artifact-name: godot-cpp-macos-universal-release - artifact-path: bin/libgodot-cpp.macos.template_release.universal.a - flags: arch=universal + artifact-path: + SCons: bin/libgodot-cpp.macos.template_release.universal.a + CMake: build_release/godot-cpp/bin/Release/libgodot-cpp.macos.template_release.a + flags: + SCons: platform=macos arch=universal + CMake: -G Xcode -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=NO run-tests: false cache-name: macos-universal - - name: 🤖 Android (arm64) + - name: 🤖 Android + description: 'arm64' os: ubuntu-20.04 platform: android artifact-name: godot-cpp-android-arm64-release - artifact-path: bin/libgodot-cpp.android.template_release.arm64.a - flags: arch=arm64 + artifact-path: + SCons: bin/libgodot-cpp.android.template_release.arm64.a + CMake: build_release/godot-cpp/bin/Release/libgodot-cpp.android.template_release.arm64.a + flags: + SCons: platform=android arch=arm64 + CMake: --toolchain ${ANDROID_HOME}/ndk/23.2.8568313/build/cmake/android.toolchain.cmake -G "Ninja Multi-Config" -DANDROID_PLATFORM=21 run-tests: false cache-name: android-arm64 - - name: 🍏 iOS (arm64) + - name: 🍏 iOS + description: 'arm64' os: macos-latest platform: ios artifact-name: godot-cpp-ios-arm64-release - artifact-path: bin/libgodot-cpp.ios.template_release.arm64.a - flags: arch=arm64 + artifact-path: + SCons: bin/libgodot-cpp.ios.template_release.arm64.a + CMake: build_release/godot-cpp/bin/Release/Release/libgodot-cpp.ios.template_release.a + flags: + SCons: platform=ios arch=arm64 + CMake: -G Xcode -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=NO run-tests: false cache-name: ios-arm64 - - name: 🌐 Web (wasm32) + - name: 🌐 Web + description: 'wasm32' os: ubuntu-20.04 platform: web artifact-name: godot-cpp-web-wasm32-release - artifact-path: bin/libgodot-cpp.web.template_release.wasm32.a + artifact-path: + SCons: bin/libgodot-cpp.web.template_release.wasm32.a + CMake: build_release/godot-cpp/bin/Release/libgodot-cpp.web.template_release.wasm32.a + flags: + SCons: platform=web + CMake: --toolchain ${EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -G "Ninja Multi-Config" run-tests: false cache-name: web-wasm32 @@ -100,68 +184,79 @@ jobs: submodules: recursive - name: Restore Godot build cache + if: ${{ matrix.builder.name == 'SCons' }} uses: ./.github/actions/godot-cache-restore with: - cache-name: ${{ matrix.cache-name }} + cache-name: ${{ matrix.platform.cache-name }} continue-on-error: true - name: Set up Python (for SCons) + if: ${{ matrix.builder.name == 'SCons' }} uses: actions/setup-python@v5 with: python-version: '3.x' - name: Android dependencies - if: ${{ matrix.platform == 'android' }} + if: ${{ matrix.platform.platform == 'android' }} uses: nttld/setup-ndk@v1 with: ndk-version: r23c link-to-sdk: true - name: Web dependencies - if: ${{ matrix.platform == 'web' }} + if: ${{ matrix.platform.platform == 'web' }} uses: mymindstorm/setup-emsdk@v14 with: version: ${{env.EM_VERSION}} actions-cache-folder: ${{env.EM_CACHE_FOLDER}} - name: Setup MinGW for Windows/MinGW build - if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }} + if: ${{ matrix.platform.use-mingw }} uses: egor-tensin/setup-mingw@v2 with: version: 12.2.0 - name: Install scons + if: ${{ matrix.builder.name == 'SCons' }} run: | python -m pip install scons==4.0.0 + - name: Install CMake + if: ${{ matrix.builder.name == 'CMake' }} + uses: jwlawson/actions-setup-cmake@v2 + + - name: Install ccache + if: ${{ matrix.builder.name == 'CMake' }} + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ matrix.platform.cache-name }} + + - name: Install Ninja + if: ${{ matrix.builder.name == 'CMake' }} + uses: ashutoshvarma/setup-ninja@master + - name: Generate godot-cpp sources only - run: | - scons platform=${{ matrix.platform }} verbose=yes build_library=no ${{ matrix.flags }} - scons -c + run: ${{ format(matrix.builder.generate_sources, matrix.platform.flags[matrix.builder.name]) }} - name: Build godot-cpp (debug) - run: | - scons platform=${{ matrix.platform }} verbose=yes target=template_debug ${{ matrix.flags }} + run: ${{ format(matrix.builder.build_godot_cpp_debug, matrix.platform.flags[matrix.builder.name]) }} - name: Build test without rebuilding godot-cpp (debug) - run: | - cd test - scons platform=${{ matrix.platform }} verbose=yes target=template_debug ${{ matrix.flags }} build_library=no + run: ${{ format(matrix.builder.build_debug, matrix.platform.flags[matrix.builder.name]) }} - name: Build test and godot-cpp (release) - run: | - cd test - scons platform=${{ matrix.platform }} verbose=yes target=template_release ${{ matrix.flags }} + run: ${{ format(matrix.builder.build_release, matrix.platform.flags[matrix.builder.name]) }} - name: Save Godot build cache + if: ${{ matrix.builder.name == 'SCons' }} uses: ./.github/actions/godot-cache-save with: - cache-name: ${{ matrix.cache-name }} + cache-name: ${{ matrix.platform.cache-name }} continue-on-error: true - name: Download latest Godot artifacts uses: dsnopek/action-download-artifact@1322f74e2dac9feed2ee76a32d9ae1ca3b4cf4e9 - if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION == 'master' }} + if: ${{ matrix.platform.run-tests && env.GODOT_TEST_VERSION == 'master' }} with: repo: godotengine/godot branch: master @@ -175,13 +270,13 @@ jobs: path: godot-artifacts - name: Prepare Godot artifacts for testing - if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION == 'master' }} + if: ${{ matrix.platform.run-tests && env.GODOT_TEST_VERSION == 'master' }} run: | chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono echo "GODOT=$(pwd)/godot-artifacts/godot.linuxbsd.editor.x86_64.mono" >> $GITHUB_ENV - name: Download requested Godot version for testing - if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION != 'master' }} + if: ${{ matrix.platform.run-tests && env.GODOT_TEST_VERSION != 'master' }} run: | wget "https://github.com/godotengine/godot-builds/releases/download/${GODOT_TEST_VERSION}/Godot_v${GODOT_TEST_VERSION}_linux.x86_64.zip" -O Godot.zip unzip -a Godot.zip @@ -189,7 +284,7 @@ jobs: echo "GODOT=$(pwd)/Godot_v${GODOT_TEST_VERSION}_linux.x86_64" >> $GITHUB_ENV - name: Run tests - if: ${{ matrix.run-tests }} + if: ${{ matrix.platform.run-tests }} run: | $GODOT --headless --version cd test @@ -200,73 +295,6 @@ jobs: - name: Upload artifact uses: actions/upload-artifact@v3 with: - name: ${{ matrix.artifact-name }} - path: ${{ matrix.artifact-path }} + name: ${{ matrix.platform.artifact-name }}-${{ matrix.builder.name }} + path: ${{ matrix.platform.artifact-path[matrix.builder.name] }} if-no-files-found: error - - linux-cmake: - name: 🐧 Build (Linux, GCC, CMake) - runs-on: ubuntu-20.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: - name: 🐧 Build (Linux, GCC, CMake Ninja) - runs-on: ubuntu-20.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 ninja-build - - - name: Build godot-cpp - run: | - cmake -DCMAKE_BUILD_TYPE=Release -GNinja . - cmake --build . -j $(nproc) --verbose - - - name: Build test GDExtension library - run: | - cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -GNinja . - cmake --build . -j $(nproc) --verbose - - windows-msvc-cmake: - name: 🏁 Build (Windows, MSVC, CMake) - runs-on: windows-2019 - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Build godot-cpp - run: | - cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 16 2019" . - cmake --build . --verbose - - - 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 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e63f1d40c..d70c60e92 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,6 +33,14 @@ repos: - id: codespell additional_dependencies: [tomli] + - repo: https://github.com/cheshirekow/cmake-format-precommit + rev: v0.6.10 + hooks: + - id: cmake-format + files: CMakeLists\.txt$|\.cmake$ + - id: cmake-lint + files: CMakeLists\.txt$|\.cmake$ + - repo: local hooks: - id: copyright-headers diff --git a/CMakeLists.txt b/CMakeLists.txt index d0a6547d1..51af0e0e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,248 +1,158 @@ +# ######### Configuration for building godot-cpp only ########## +# ######### See `tests/CMakeLists.txt` for example configuration ########## +# # cmake arguments -# CMAKE_BUILD_TYPE: Compilation target (Debug or Release defaults to Debug) +# +# CMAKE_BUILD_TYPE Compilation target (Debug, +# Release, RelWithDebInfo, MinSizeRel) +# +# CMAKE_CONFIGURATION_TYPES Set to +# "Debug;Release;RelWithDebInfo;MinSizeRel" in top project config or via cmdline +# (see `test/CMakeLists.txt`) # # 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 +# +# GODOT_TARGET Godot build target (EDITOR, +# TEMPLATE_DEBUG, TEMPLATE_RELEASE) GODOT_PLATFORM: Platform type (LINUX, MACOS, +# WINDOWS, ANDROID, IOS, WEB). Auto-detected by default depending on current OS +# or chosen toolchain 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") +# +# other global and platform-specific options: +# +# $ cmake -LH +# +# Note: use `-B ` option to build in separate directories for +# different configurations +# +# $ cmake -B build && cmake --build build # # Examples # -# Builds a debug version: -# cmake . -# cmake --build . +# Builds default debug configuration: $ cmake . -B build $ cmake --build build +# +# Builds template_release version with Release preset $ cmake +# -DCMAKE_BUILD_TYPE=Release -DGODOT_TARGET=TEMPLATE_RELEASE -B build $ cmake +# --build build +# +# Creates multi-config setup and builds Release version +# +# $ cmake -G "Ninja Multi-Config" -B build # For Linux/non-MSVC +# OR $ cmake -G "Visual Studio 16 2019" -A x64 -B build # For Windows/MSVC +# $ cmake --build build --config Release # -# 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 web version, using Emscripten toolchain # -# 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 . +# $ cmake --toolchain +# /usr/lib/emscripten/cmake/Modules/Platform/Emscripten.cmake -B build $ cmake +# --build 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 . +# Builds an android armeabi-v7a debug version: $ cmake --toolchain +# $ANDROID_NDK/build/cmake/android.toolchain.cmake \ +# -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 -DANDROID_TOOLCHAIN=clang +# -DANDROID_PLATFORM=21 -B build $ cmake --build 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) +# Builds MacOS version via Xcode $ cmake -G Xcode -B build $ cmake --build build +# +# Ensure that you avoid exposing godot-cpp symbols - this might lead to hard to +# debug errors if you ever load multiple plugins using different 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" ) -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() +# Handles all global and platform-specific variables +include(${CMAKE_CURRENT_LIST_DIR}/cmake/godotcpp.cmake) # Generate source from the bindings file find_package(Python3 3.4 REQUIRED) # pathlib should be present + +execute_process( + COMMAND + "${Python3_EXECUTABLE}" "-c" "import binding_generator;\ + binding_generator.print_file_list(\ + \"${GODOT_CUSTOM_API_FILE}\",\ + \"${CMAKE_CURRENT_BINARY_DIR}\",\ + headers=True,\ + sources=True,\ + profile_filepath=\"${GODOT_BUILD_PROFILE}\")" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE GENERATED_FILES_LIST + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(GODOT_GENERATE_TEMPLATE_GET_NODE) - set(GENERATE_BINDING_PARAMETERS "True") + set(GENERATE_BINDING_PARAMETERS "True") else() - set(GENERATE_BINDING_PARAMETERS "False") + 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 +add_custom_command( + OUTPUT ${GENERATED_FILES_LIST} + COMMAND + "${Python3_EXECUTABLE}" "-c" "import binding_generator;\ + binding_generator.generate_bindings(\ + \"${GODOT_CUSTOM_API_FILE}\",\ + \"${GENERATE_BINDING_PARAMETERS}\",\ + \"${GODOT_BITS}\", \"${GODOT_PRECISION}\",\ + \"${CMAKE_CURRENT_BINARY_DIR}\")" + VERBATIM + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + MAIN_DEPENDENCY ${GODOT_CUSTOM_API_FILE} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py + COMMENT "Generating bindings") + 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(${PROJECT_NAME} ${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}) - -# 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}") +if(GODOT_SYSTEM_HEADERS) + set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM) 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}" -) +target_include_directories( + ${PROJECT_NAME} ${GODOT_SYSTEM_HEADERS_ATTRIBUTE} + PUBLIC include ${CMAKE_CURRENT_BINARY_DIR}/gen/include + ${GODOT_GDEXTENSION_DIR}) + +target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17) + +target_compile_options( + ${PROJECT_NAME} PRIVATE ${GODOT_C_FLAGS} ${GODOT_CXX_FLAGS} + ${GODOT_COMPILE_WARNING_FLAGS}) + +target_link_options(${PROJECT_NAME} PRIVATE ${GODOT_LINK_FLAGS}) + +target_compile_definitions(${PROJECT_NAME} PUBLIC ${GODOT_DEFINITIONS}) + +set_target_properties( + ${PROJECT_NAME} + PROPERTIES CXX_EXTENSIONS OFF + POSITION_INDEPENDENT_CODE ON + CXX_VISIBILITY_PRESET ${GODOT_SYMBOLS_VISIBILITY} + GODOT_C_FLAGS "${GODOT_C_FLAGS}" + GODOT_CXX_FLAGS "${GODOT_CXX_FLAGS}" + GODOT_COMPILE_WARNING_FLAGS "${GODOT_COMPILE_WARNING_FLAGS}" + GODOT_LINK_FLAGS "${GODOT_LINK_FLAGS}" + LIBRARY_SUFFIX "${LIBRARY_SUFFIX}" + 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 "${PROJECT_NAME}${LIBRARY_SUFFIX}") + +if(${GODOT_WARNING_AS_ERROR}) + set_warning_as_error(${PROJECT_NAME}) +endif() diff --git a/README.md b/README.md index 005c8e723..8b1378917 100644 --- a/README.md +++ b/README.md @@ -1,149 +1 @@ -# godot-cpp -> [!WARNING] -> -> This repository's `master` branch is only usable with -> [GDExtension](https://godotengine.org/article/introducing-gd-extensions) -> from Godot's `master` branch. -> -> For users of stable branches, switch to the branch matching your target Godot version: -> - [`4.2`](https://github.com/godotengine/godot-cpp/tree/4.2) -> - [`4.1`](https://github.com/godotengine/godot-cpp/tree/4.1) -> - [`4.0`](https://github.com/godotengine/godot-cpp/tree/4.0) -> -> Or check out the Git tag matching your Godot version (e.g. `godot-4.1.1-stable`). -> -> For GDNative users (Godot 3.x), switch to the [`3.x`](https://github.com/godotengine/godot-cpp/tree/3.x) -> or the [`3.5`](https://github.com/godotengine/godot-cpp/tree/3.5) branch. - -This repository contains the *C++ bindings* for the [**Godot Engine**](https://github.com/godotengine/godot)'s GDExtensions API. - -- [**Versioning**](#versioning) -- [**Compatibility**](#compatibility) -- [**Contributing**](#contributing) -- [**Getting started**](#getting-started) -- [**Examples and templates**](#examples-and-templates) - -## Versioning - -This repositories follows the same branch versioning as the main [Godot Engine -repository](https://github.com/godotengine/godot): - -- `master` tracks the current GDExtension development branch for the next Godot - 4.x minor release. -- `3.x` tracks the development of the GDNative plugin for the next 3.x minor - release. -- Other versioned branches (e.g. `4.0`, `3.5`) track the latest stable release - in the corresponding branch. - -Stable releases are also tagged on this repository: -[**Tags**](https://github.com/godotengine/godot-cpp/tags). - -**For any project built against a stable release of Godot, we recommend using -this repository as a Git submodule, checking out the specific tag matching your -Godot version.** - -> As the `master` branch of Godot is constantly getting updated, if you are -> using `godot-cpp` against a more current version of Godot, see the instructions -> in the `gdextension` folder to update the relevant files. - -## Compatibility - -> [!WARNING] -> -> The GDExtension API is brand new in Godot 4.0, and is still -considered in **beta** stage, despite Godot 4.0 itself being released. -> -> This applies to both the GDExtension interface header, the API JSON, and this -first-party `godot-cpp` extension. -> -> Some compatibility breakage is to be expected as GDExtension and `godot-cpp` -> get more used, documented, and critical issues get resolved. See the -> [Godot issue tracker](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension) -> and the [godot-cpp issue tracker](https://github.com/godotengine/godot-cpp/issues) -> for a list of known issues, and be sure to provide feedback on issues and PRs -> which affect your use of this extension. - -## Contributing - -We greatly appreciate help in maintaining and extending this project. If you -wish to help out, ensure you have an account on GitHub and create a "fork" of -this repository. See [Pull request workflow](https://docs.godotengine.org/en/stable/community/contributing/pr_workflow.html) -for instructions. - -Please install clang-format and copy the files in `misc/hooks` into `.git/hooks` -so formatting is done before your changes are submitted. - -## Getting started - -You need the same C++ pre-requisites installed that are required for the `godot` repository. Follow the [official build instructions for your target platform](https://docs.godotengine.org/en/latest/contributing/development/compiling/index.html#building-for-target-platforms). - -Getting started with GDExtensions is a bit similar to what it was for 3.x but also a bit different. - -This new approach is much more akin to how core Godot modules are structured. - -Compiling this repository generates a static library to be linked with your shared lib, -just like before. - -To use the shared lib in your Godot project you'll need a `.gdextension` -file, which replaces what was the `.gdnlib` before. -See [example.gdextension](test/project/example.gdextension) used in the test project: - -```ini -[configuration] - -entry_symbol = "example_library_init" -compatibility_minimum = "4.1" - -[libraries] - -macos.debug = "res://bin/libgdexample.macos.debug.framework" -macos.release = "res://bin/libgdexample.macos.release.framework" -windows.debug.x86_64 = "res://bin/libgdexample.windows.debug.x86_64.dll" -windows.release.x86_64 = "res://bin/libgdexample.windows.release.x86_64.dll" -linux.debug.x86_64 = "res://bin/libgdexample.linux.debug.x86_64.so" -linux.release.x86_64 = "res://bin/libgdexample.linux.release.x86_64.so" -# Repeat for other architectures to support arm64, rv64, etc. -``` - -The `entry_symbol` is the name of the function that initializes -your library. It should be similar to following layout: - -```cpp -extern "C" { - -// Initialization. - -GDExtensionBool GDE_EXPORT example_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { - godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization); - - init_obj.register_initializer(initialize_example_module); - init_obj.register_terminator(uninitialize_example_module); - init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE); - - return init_obj.init(); -} -} -``` - -The `initialize_example_module()` should register the classes in ClassDB, very like a Godot module would do. - -```cpp -using namespace godot; -void initialize_example_module(ModuleInitializationLevel p_level) { - if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { - return; - } - GDREGISTER_CLASS(Example); -} -``` - -Any node and resource you register will be available in the corresponding `Create...` dialog. Any class will be available to scripting as well. - -## Examples and templates - -See the [godot-cpp-template](https://github.com/godotengine/godot-cpp-template) project for a -generic reusable template. - -Or checkout the code for the [Summator example](https://github.com/paddy-exe/GDExtensionSummator) -as shown in the [official documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/gdextension/gdextension_cpp_example.html). diff --git a/cmake/GodotCompilerWarnings.cmake b/cmake/GodotCompilerWarnings.cmake deleted file mode 100644 index 94556415b..000000000 --- a/cmake/GodotCompilerWarnings.cmake +++ /dev/null @@ -1,94 +0,0 @@ -# Add warnings based on compiler & version -# Set some helper variables for readability -set( compiler_less_than_v8 "$,8>" ) -set( compiler_greater_than_or_equal_v9 "$,9>" ) -set( compiler_greater_than_or_equal_v11 "$,11>" ) -set( compiler_less_than_v11 "$,11>" ) -set( compiler_greater_than_or_equal_v12 "$,12>" ) - -# These compiler options reflect what is in godot/SConstruct. -target_compile_options( ${PROJECT_NAME} PRIVATE - # MSVC only - $<${compiler_is_msvc}: - /W4 - - # Disable warnings which we don't plan to fix. - /wd4100 # C4100 (unreferenced formal parameter): Doesn't play nice with polymorphism. - /wd4127 # C4127 (conditional expression is constant) - /wd4201 # C4201 (non-standard nameless struct/union): Only relevant for C89. - /wd4244 # C4244 C4245 C4267 (narrowing conversions): Unavoidable at this scale. - /wd4245 - /wd4267 - /wd4305 # C4305 (truncation): double to float or real_t, too hard to avoid. - /wd4514 # C4514 (unreferenced inline function has been removed) - /wd4714 # C4714 (function marked as __forceinline not inlined) - /wd4820 # C4820 (padding added after construct) - > - - # Clang and GNU common options - $<$: - -Wall - -Wctor-dtor-privacy - -Wextra - -Wno-unused-parameter - -Wnon-virtual-dtor - -Wwrite-strings - > - - # Clang only - $<${compiler_is_clang}: - -Wimplicit-fallthrough - -Wno-ordered-compare-function-pointers - > - - # GNU only - $<${compiler_is_gnu}: - -Walloc-zero - -Wduplicated-branches - -Wduplicated-cond - -Wno-misleading-indentation - -Wplacement-new=1 - -Wshadow-local - -Wstringop-overflow=4 - > - $<$: - # Bogus warning fixed in 8+. - -Wno-strict-overflow - > - $<$: - -Wattribute-alias=2 - > - $<$: - # Broke on MethodBind templates before GCC 11. - -Wlogical-op - > - $<$: - # Regression in GCC 9/10, spams so much in our variadic templates that we need to outright disable it. - -Wno-type-limits - > - $<$: - # False positives in our error macros, see GH-58747. - -Wno-return-type - > -) - -# Treat warnings as errors -function( set_warning_as_error ) - message( STATUS "[${PROJECT_NAME}] Treating warnings as errors") - 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> - $<$:-Werror> - ) - endif() -endfunction() - -if ( GODOT_WARNING_AS_ERROR ) - set_warning_as_error() -endif() diff --git a/cmake/android.cmake b/cmake/android.cmake new file mode 100644 index 000000000..603a59d05 --- /dev/null +++ b/cmake/android.cmake @@ -0,0 +1,68 @@ +# Used with android toolchain at $ANDROID_NDK/build/cmake/android.toolchain.cmake + +set(GODOT_ARCH "arm64" CACHE STRING "Target architecture (arm64, x86_64, arm32, x86_32, custom") + +if(${ANDROID_PLATFORM} VERSION_LESS 21) + message(FATAL_ERROR "Minimum supported API level is 21 (-DANDROID_PLATFORM=21)") +endif() + +# This must be kept in sync with the value in https://github.com/godotengine/godot/blob/master/platform/android/detect.py#L58. +set(ANDROID_NDK_VERSION_EXPECTED "23.2.8568313") +if(NOT "${ANDROID_NDK_REVISION}" STREQUAL "${ANDROID_NDK_VERSION_EXPECTED}") + message(FATAL_ERROR "Android NDK version '${ANDROID_NDK_VERSION_EXPECTED}' expected, got '${ANDROID_NDK_REVISION}'") +endif() + +string(REGEX MATCH "32$|64$" DEFAULT_GODOT_BITS "${GODOT_ARCH}") +set(GODOT_BITS "${DEFAULT_GODOT_BITS}" CACHE STRING "Architecture bits. Needs to be set manually for custom architecture") + + +list(APPEND GODOT_DEFINITIONS + ANDROID_ENABLED + UNIX_ENABLED +) + +list(APPEND GODOT_C_FLAGS + $<$: + --target=armv7a-linux-androideabi${ANDROID_PLATFORM} + -march=armv7-a + + -mfpu=neon + > + $<$: + --target=aarch64-linux-android${ANDROID_PLATFORM} + -march=armv8-a + > + $<$: + --target=i686-linux-android${ANDROID_PLATFORM} + -march=i686 + + -mstackrealign + > + $<$: + --target=x86_64-linux-android${ANDROID_PLATFORM} + -march=x86-64 + > +) + +list(APPEND GODOT_LINK_FLAGS + $<$: + --target=armv7a-linux-androideabi${ANDROID_PLATFORM} + -march=armv7-a + > + $<$: + --target=aarch64-linux-android${ANDROID_PLATFORM} + -march=armv8-a + > + $<$: + --target=i686-linux-android${ANDROID_PLATFORM} + -march=i686 + > + $<$: + --target=x86_64-linux-android${ANDROID_PLATFORM} + -march=x86-64 + > + + $<$: + -shared + > +) diff --git a/cmake/common_compiler_flags.cmake b/cmake/common_compiler_flags.cmake new file mode 100644 index 000000000..c50363942 --- /dev/null +++ b/cmake/common_compiler_flags.cmake @@ -0,0 +1,229 @@ +# Set some helper variables for readability +set(compiler_is_clang "$,$>") +set(compiler_is_gnu "$") +set(compiler_is_msvc "$") + +# Add warnings based on compiler & version +# Set some helper variables for readability +set(compiler_less_than_v8 "$,8>") +set(compiler_greater_than_or_equal_v9 "$,9>") +set(compiler_greater_than_or_equal_v11 "$,11>") +set(compiler_less_than_v11 "$,11>") +set(compiler_greater_than_or_equal_v12 "$,12>") + +# Workaround of $ expanding to "" when default build set +set(CONFIG "$>,${CMAKE_BUILD_TYPE},$>") + +# Default optimization levels if GODOT_OPTIMIZE=AUTO, for multi-config support +set(DEFAULT_OPTIMIZATION_DEBUG_FEATURES "$,$>") +set(DEFAULT_OPTIMIZATION "$") + +set(GODOT_DEBUG_SYMBOLS_ENABLED "$,$>") + +list(APPEND GODOT_DEFINITIONS + $<${compiler_is_msvc}: + $<$: + _HAS_EXCEPTIONS=0 + > + > +) + +list(APPEND GODOT_C_FLAGS + $<${compiler_is_msvc}: + $<${GODOT_DEBUG_SYMBOLS_ENABLED}: + /Zi + /FS + > + + $<$: + $<$,$>: + $<${DEFAULT_OPTIMIZATION}: + /O2 + > + $<${DEFAULT_OPTIMIZATION_DEBUG_FEATURES}: + /O2 + > + > + $<$: + /O1 + > + $<$,$>: + /Od + > + > + $<$:/O2> + $<$:/O2> + $<$:/O1> + $<$:/Od> + $<$:/Od> + + > + $<$: + $<${GODOT_DEBUG_SYMBOLS_ENABLED}: + -gdwarf-4 + + $<$: + -g3 + > + $<$>: + -g2 + > + > + + $<$: + $<$,$>: + $<${DEFAULT_OPTIMIZATION}: + -O3 + > + $<${DEFAULT_OPTIMIZATION_DEBUG_FEATURES}: + -O2 + > + > + $<$: + -Os + > + $<$,$>: + -Og + > + > + $<$:-O3> + $<$:-O2> + $<$:-Os> + $<$:-Og> + $<$:-O0> + > +) + +list(APPEND GODOT_CXX_FLAGS + $<${compiler_is_msvc}: + $<$>: + /EHsc + > + > + $<$: + $<$: + -fno-exceptions + > + > +) + +list(APPEND GODOT_LINK_FLAGS + $<${compiler_is_msvc}: + $<${GODOT_DEBUG_SYMBOLS_ENABLED}: + /DEBUG:FULL + > + + $<$: + $<$,$>: + $<${DEFAULT_OPTIMIZATION}: + /OPT:REF + > + $<${DEFAULT_OPTIMIZATION_DEBUG_FEATURES}: + /OPT:REF + /OPT:NOICF + > + > + $<$: + /OPT:REF + > + > + $<$:/OPT:REF> + $<$:/OPT:REF /OPT:NOICF> + $<$:/OPT:REF> + > + $<$: + $<$: + $<$: # SCons: not is_vanilla_clang(env) + "-Wl,-S" + "-Wl,-x" + "-Wl,-dead_strip" + > + $<$>: + "-s" + > + > + > +) + +# These compiler options reflect what is in godot/SConstruct. +list(APPEND GODOT_COMPILE_WARNING_FLAGS + # MSVC only + $<${compiler_is_msvc}: + /W4 + + # Disable warnings which we don't plan to fix. + /wd4100 # C4100 (unreferenced formal parameter): Doesn't play nice with polymorphism. + /wd4127 # C4127 (conditional expression is constant) + /wd4201 # C4201 (non-standard nameless struct/union): Only relevant for C89. + /wd4244 # C4244 C4245 C4267 (narrowing conversions): Unavoidable at this scale. + /wd4245 + /wd4267 + /wd4305 # C4305 (truncation): double to float or real_t, too hard to avoid. + /wd4514 # C4514 (unreferenced inline function has been removed) + /wd4714 # C4714 (function marked as __forceinline not inlined) + /wd4820 # C4820 (padding added after construct) + > + + # Clang and GNU common options + $<$: + -Wall + -Wctor-dtor-privacy + -Wextra + -Wno-unused-parameter + -Wnon-virtual-dtor + -Wwrite-strings + > + + # Clang only + $<${compiler_is_clang}: + -Wimplicit-fallthrough + -Wno-ordered-compare-function-pointers + > + + # GNU only + $<${compiler_is_gnu}: + -Walloc-zero + -Wduplicated-branches + -Wduplicated-cond + -Wno-misleading-indentation + -Wplacement-new=1 + -Wshadow-local + -Wstringop-overflow=4 + > + $<$: + # Bogus warning fixed in 8+. + -Wno-strict-overflow + > + $<$: + -Wattribute-alias=2 + > + $<$: + # Broke on MethodBind templates before GCC 11. + -Wlogical-op + > + $<$: + # Regression in GCC 9/10, spams so much in our variadic templates that we need to outright disable it. + -Wno-type-limits + > + $<$: + # False positives in our error macros, see GH-58747. + -Wno-return-type + > +) + +# Treat warnings as errors +function(set_warning_as_error TARGET_NAME) + message(STATUS "[${TARGET_NAME}] Treating warnings as errors") + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24") + set_target_properties(${TARGET_NAME} + PROPERTIES + COMPILE_WARNING_AS_ERROR ON + ) + else() + target_compile_options(${TARGET_NAME} + PRIVATE + $<${compiler_is_msvc}:/WX> + $<$:-Werror> + ) + endif() +endfunction() diff --git a/cmake/godotcpp.cmake b/cmake/godotcpp.cmake new file mode 100644 index 000000000..aba414823 --- /dev/null +++ b/cmake/godotcpp.cmake @@ -0,0 +1,248 @@ +# This file contains variables needed by all platforms + +# Helper functions +macro(GODOT_CLEAR_DEFAULT_FLAGS) + # Default options (including multi-config) + set(CMAKE_EXE_LINKER_FLAGS "") + set(CMAKE_STATIC_LINKER_FLAGS "") + set(CMAKE_SHARED_LINKER_FLAGS "") + set(CMAKE_MODULE_LINKER_FLAGS "") + + set(CMAKE_C_FLAGS "") + set(CMAKE_C_FLAGS_DEBUG "") + set(CMAKE_C_FLAGS_RELEASE "") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "") + set(CMAKE_C_FLAGS_MINSIZEREL "") + + set(CMAKE_CXX_FLAGS "") + set(CMAKE_CXX_FLAGS_DEBUG "") + set(CMAKE_CXX_FLAGS_RELEASE "") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "") + set(CMAKE_CXX_FLAGS_MINSIZEREL "") + + # (--sysroot= option removed to match SCons options, may return later) + set(CMAKE_SYSROOT "") + # TODO: remove `--sysroot=` and default `--target=` for android config +endmacro() + +# Equivalent to scons' `GodotCPPDocData` builder +function(godot_make_doc) + find_package(Python3 3.4 REQUIRED) + set(options) + set(oneValueArgs DESTINATION COMPRESSION) + set(multiValueArgs SOURCES) + cmake_parse_arguments(MAKE_DOC "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN}) + + if("${MAKE_DOC_COMPRESSION}" STREQUAL "") + set(make_doc_compression "Z_BEST_COMPRESSION") + else() + set(make_doc_compression ${MAKE_DOC_COMPRESSION}) + endif() + + add_custom_command( + OUTPUT ${MAKE_DOC_DESTINATION} + COMMAND + "${Python3_EXECUTABLE}" + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../docs_generator.py" + "${make_doc_compression}" "${MAKE_DOC_DESTINATION}" ${MAKE_DOC_SOURCES} + VERBATIM + DEPENDS "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../docs_generator.py" + COMMENT "Generating docs..." + COMMAND_EXPAND_LISTS) +endfunction() + +# Options + +set(GODOT_CONFIGS_WITH_DEBUG + "Debug;RelWithDebInfo" + CACHE STRING "Configurations that should have debug symbols\ + (Modify if support for custom configurations is needed)") + +# Default config +if("${CMAKE_BUILD_TYPE}" STREQUAL "") + set(CMAKE_BUILD_TYPE "Debug") +endif() + +set(GODOT_TARGET + "template_debug" + CACHE STRING "Target platform \ + (editor, template_debug, template_release)") + +# Auto-detect platform +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(DEFAULT_GODOT_PLATFORM "linux") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(DEFAULT_GODOT_PLATFORM "windows") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(DEFAULT_GODOT_PLATFORM "macos") +elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS") + set(DEFAULT_GODOT_PLATFORM "ios") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") # Set by providing Emscripten + # toolchain + set(DEFAULT_GODOT_PLATFORM "web") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Android") # Set by providing Android + # toolchain + set(DEFAULT_GODOT_PLATFORM "android") +else() + set(DEFAULT_GODOT_PLATFORM "NOTFOUND") +endif() + +set(GODOT_PLATFORM + "${DEFAULT_GODOT_PLATFORM}" + CACHE STRING "[Auto-detected] Target platform\ + (linux, macos, windows, android, ios, web)") + +if("${GODOT_PLATFORM}" STREQUAL "NOTFOUND") + message( + FATAL_ERROR "Could not auto-detect platform for \"${CMAKE_SYSTEM_NAME}\"\ + automatically, please specify with -DGODOT_PLATFORM=") +endif() + +message(STATUS "Platform detected: ${GODOT_PLATFORM}") + +set(GODOT_GDEXTENSION_DIR + "${CMAKE_CURRENT_SOURCE_DIR}/gdextension" + CACHE PATH "Path to a directory containing GDExtension interface header") + +set(GODOT_CUSTOM_API_FILE + "${GODOT_GDEXTENSION_DIR}/extension_api.json" + CACHE FILEPATH "Path to GDExtension API JSON file") + +set(GODOT_PRECISION + "single" + CACHE STRING "Floating-point precision level (single, double)") + +set(GODOT_OPTIMIZE + "auto" + CACHE STRING "The desired optimization flags\ + (none, custom, debug, speed, speed_trace, size)") + +set(GODOT_SYMBOLS_VISIBILITY + "hidden" + CACHE STRING + "Symbols visibility on GNU platforms (default, visible, hidden)") + +set(GODOT_BUILD_PROFILE + "" + CACHE FILEPATH "Path to a file containing a feature build profile") + +option(GODOT_DEV_BUILD "Developer build with dev-only debugging code" OFF) + +option(GODOT_DEBUG_SYMBOLS "Force build with debugging symbols" OFF) + +set(DEFAULT_GODOT_USE_HOT_RELOAD ON) +if("${GODOT_TARGET}" STREQUAL "template_release") + set(DEFAULT_GODOT_USE_HOT_RELOAD OFF) +endif() +option(GODOT_USE_HOT_RELOAD + "Enable the extra accounting required to support hot reload" + ${DEFAULT_GODOT_USE_HOT_RELOAD}) + +# 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) + +# Optionally mark headers as SYSTEM +option(GODOT_SYSTEM_HEADERS + "Mark the header files as SYSTEM. This may be useful to suppress\ + warnings in projects including this one" OFF) +set(GODOT_SYSTEM_HEADERS_ATTRIBUTE "") +if(GODOT_SYSTEM_HEADERS) + set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM) +endif() + +# Enable by default when building godot-cpp only +set(DEFAULT_WARNING_AS_ERROR OFF) +if(${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) + set(DEFAULT_WARNING_AS_ERROR ON) +endif() +set(GODOT_WARNING_AS_ERROR + "${DEFAULT_WARNING_AS_ERROR}" + CACHE BOOL "Treat warnings as errors") + +option(GODOT_GENERATE_TEMPLATE_GET_NODE + "Generate a template version of the Node class's get_node" ON) + +option(GODOT_THREADS "Enable threading support" ON) + +# + +# Common compiler options and compiler check generators +include(${CMAKE_CURRENT_LIST_DIR}/common_compiler_flags.cmake) + +# Platform-specific options +include(${CMAKE_CURRENT_LIST_DIR}/${GODOT_PLATFORM}.cmake) + +godot_clear_default_flags() + +# Configuration of build targets: * Editor or template * Debug features +# (DEBUG_ENABLED code) * Dev only code (DEV_ENABLED code) * Optimization level * +# Debug symbols for crash traces / debuggers Keep this configuration in sync +# with SConstruct in upstream Godot. +list( + APPEND + GODOT_DEFINITIONS + $<$: + THREADS_ENABLED + > + $<$: + HOT_RELOAD_ENABLED + > + $<$: + TOOLS_ENABLED + > + $<$>: + # DEBUG_ENABLED enables debugging *features* and debug-only code, which is + # intended to give *users* extra debugging information for their game + # development. + DEBUG_ENABLED + # In upstream Godot this is added in typedefs.h when DEBUG_ENABLED is set. + DEBUG_METHODS_ENABLED + > + $<$: + # DEV_ENABLED enables *engine developer* code which should only be compiled + # for those working on the engine itself. + DEV_ENABLED + > + $<$>: + # Disable assert() for production targets (only used in thirdparty code). + NDEBUG + > + $<$: + REAL_T_IS_DOUBLE + > + # Allow detecting when building as a GDExtension. + GDEXTENSION) + +# Suffix See more prefix appends in platform-specific configs +string(PREPEND LIBRARY_SUFFIX ".${GODOT_PLATFORM}.${GODOT_TARGET}") + +if(${GODOT_DEV_BUILD}) + string(APPEND LIBRARY_SUFFIX ".dev") +endif() + +if("${GODOT_PRECISION}" STREQUAL "double") + string(APPEND LIBRARY_SUFFIX ".double") +endif() + +# Mac/IOS uses .framework directory structure and don't need arch suffix +if((NOT "${GODOT_PLATFORM}" STREQUAL "macos") AND (NOT "${GODOT_PLATFORM}" + STREQUAL "ios")) + string(APPEND LIBRARY_SUFFIX ".${GODOT_ARCH}") +endif() + +if(${IOS_SIMULATOR}) + string(APPEND LIBRARY_SUFFIX ".simulator") +endif() + +if(NOT ${GODOT_THREADS}) + string(APPEND LIBRARY_SUFFIX ".nothreads") +endif() + +# Write all flags to file for cmake configuration debug (CMake 3.19+) +# file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/flags-${CONFIG}.txt" CONTENT +# "C_FLAGS '${GODOT_C_FLAGS}'\nCXX_FLAGS '${GODOT_CXX_FLAGS}'\nLINK_FLAGS +# '${GODOT_LINK_FLAGS}'\nCOMPILE_WARNING_FLAGS +# '${GODOT_COMPILE_WARNING_FLAGS}'\nDEFINITIONS '${GODOT_DEFINITIONS}'" TARGET +# ${PROJECT_NAME} ) diff --git a/cmake/ios.cmake b/cmake/ios.cmake new file mode 100644 index 000000000..cfb00980a --- /dev/null +++ b/cmake/ios.cmake @@ -0,0 +1,61 @@ +message(WARNING "IOS configuration is not tested and may not work.") + +set(GODOT_ARCH "universal" CACHE STRING "Target architecture (universal, arm64, x86_64, custom)") + +set(GODOT_IOS_MIN_VERSION "12.0" CACHE STRING "Target minimum iphoneos/iphonesimulator version") + +option(GODOT_IOS_SIMULATOR "Target iOS Simulator" OFF) + +if (${GODOT_ARCH} STREQUAL "universal") + set(DEFAULT_GODOT_BITS 64) +else() + string(REGEX MATCH "32$|64$" DEFAULT_GODOT_BITS "${GODOT_ARCH}") +endif() +set(GODOT_BITS "${DEFAULT_GODOT_BITS}" CACHE STRING "Architecture bits. Needs to be set manually for custom architecture") + + +list(APPEND GODOT_DEFINITIONS + IOS_ENABLED + UNIX_ENABLED +) + +list(APPEND GODOT_C_FLAGS + $<$: + -stdlib=libc++ + > + + $<$: + -mios-simulator-version-min=${GODOT_IOS_MIN_VERSION} + > + $<$>: + -miphoneos-version-min=${IOS_MIN_VERSION} + > + + $<$: + $<$: + "SHELL:-arch x86_64" + "SHELL:-arch arm64" + > + $<$>: + "SHELL:-arch arm64" + > + > + $<$>: + "-arch ${GODOT_ARCH}" + > +) + +list(APPEND GODOT_LINK_FLAGS + $<$: + $<$: + "SHELL:-arch x86_64" + "SHELL:-arch arm64" + > + $<$>: + "SHELL:-arch arm64" + > + > + $<$>: + "SHELL:-arch ${GODOT_ARCH}" + > +) diff --git a/cmake/linux.cmake b/cmake/linux.cmake new file mode 100644 index 000000000..c0c577486 --- /dev/null +++ b/cmake/linux.cmake @@ -0,0 +1,61 @@ +set(GODOT_ARCH "x86_64" CACHE STRING "Target architecture (x86_32, x86_64, arm64, rv64, custom)") + +string(REGEX MATCH "32$|64$" DEFAULT_GODOT_BITS "${GODOT_ARCH}") +set(GODOT_BITS "${DEFAULT_GODOT_BITS}" CACHE STRING "Architecture bits. Needs to be set manually for custom architecture") + + +list(APPEND GODOT_DEFINITIONS + LINUX_ENABLED + UNIX_ENABLED +) + +list(APPEND GODOT_C_FLAGS + # -fPIC is controlled by POSITION_INDEPENDENT_CODE property + + $<$: + # -m64 and -m32 are x86-specific already, but it doesn't hurt to + # be clear and also specify -march=x86-64. Similar with 32-bit. + -m64 + -march=x86-64 + > + $<$: + -m32 + -march=i686 + > + $<$: + -march=armv8-a + > + $<$: + -march=rv64gc + > +) + +list(APPEND GODOT_CXX_FLAGS + $<$,${compiler_is_gnu}>: + # Required for extensions to truly unload. + -fno-gnu-unique + > +) + +list(APPEND GODOT_LINK_FLAGS + -Wl,-R,'$$ORIGIN' + + $<$: + -m64 + -march=x86-64 + > + $<$: + -m32 + -march=i686 + > + $<$: + -march=armv8-a + > + $<$: + -march=rv64gc + > +) + +list(APPEND GODOT_COMPILE_WARNING_FLAGS + -Wwrite-strings +) diff --git a/cmake/macos.cmake b/cmake/macos.cmake new file mode 100644 index 000000000..6fe0620c4 --- /dev/null +++ b/cmake/macos.cmake @@ -0,0 +1,48 @@ +set(GODOT_ARCH "universal" CACHE STRING "Target architecture (universal, arm64, x86_64, custom)") + +set(GODOT_MACOS_DEPLOYMENT_TARGET "default" CACHE STRING "") + +if (${GODOT_ARCH} STREQUAL "universal") + set(DEFAULT_GODOT_BITS 64) +else() + string(REGEX MATCH "32$|64$" DEFAULT_GODOT_BITS "${GODOT_ARCH}") +endif() +set(GODOT_BITS "${DEFAULT_GODOT_BITS}" CACHE STRING "Architecture bits. Needs to be set manually for custom architecture") + + +list(APPEND GODOT_DEFINITIONS + MACOS_ENABLED + UNIX_ENABLED +) + +list(APPEND GODOT_C_FLAGS + $<$: + "SHELL:-arch x86_64" + "SHELL:-arch arm64" + > + $<$>: + "SHELL:-arch ${GODOT_ARCH}" + > + + $<$>: + -mmacosx-version-min=${GODOT_MACOS_DEPLOYMENT_TARGET} + > +) + +list(APPEND GODOT_LINK_FLAGS + -framework + Cocoa + -Wl,-undefined,dynamic_lookup + + $<$: + "SHELL:-arch x86_64" + "SHELL:-arch arm64" + > + $<$>: + "SHELL:-arch ${GODOT_ARCH}" + > + + $<$>: + -mmacosx-version-min=${GODOT_MACOS_DEPLOYMENT_TARGET} + > +) diff --git a/cmake/web.cmake b/cmake/web.cmake new file mode 100644 index 000000000..a2fdbd6cd --- /dev/null +++ b/cmake/web.cmake @@ -0,0 +1,41 @@ +# Used with Emscripted toolchain at *toolchain_dir*/cmake/Modules/Platform/Emscripten.cmake + +set(GODOT_ARCH "wasm32" CACHE STRING "Target architecture (wasm32, custom)") + +string(REGEX MATCH "32$|64$" DEFAULT_GODOT_BITS "${GODOT_ARCH}") +set(GODOT_BITS "${DEFAULT_GODOT_BITS}" CACHE STRING "Architecture bits. Needs to be set manually for custom architecture") + + +list(APPEND GODOT_DEFINITIONS + WEB_ENABLED + UNIX_ENABLED +) + +list(APPEND GODOT_C_FLAGS + $<$: + # Thread support (via SharedArrayBuffer). + -sUSE_PTHREADS=1 + > + # Build as side module (shared library) + -sSIDE_MODULE=1 + + # Force wasm longjmp mode. + -sSUPPORT_LONGJMP='wasm' +) + +list(APPEND GODOT_CXX_FLAGS +) + +list(APPEND GODOT_LINK_FLAGS + $<$: + -sUSE_PTHREADS=1 + > + -sSIDE_MODULE=1 + + # Enable WebAssembly BigInt <-> i64 conversion. + # This must match the flag used to build Godot (true in official builds since 4.3) + -sWASM_BIGINT + + -sSUPPORT_LONGJMP='wasm' + +) diff --git a/cmake/windows.cmake b/cmake/windows.cmake new file mode 100644 index 000000000..cc57b238a --- /dev/null +++ b/cmake/windows.cmake @@ -0,0 +1,53 @@ +set(GODOT_ARCH "x86_64" CACHE STRING "Target architecture (x86_64, arm64, arm32, x86_32, custom)") + +option(GODOT_USE_STATIC_CPP "Link MinGW/MSVC C++ runtime libraries statically" ON) + +string(REGEX MATCH "32$|64$" DEFAULT_GODOT_BITS "${GODOT_ARCH}") +set(GODOT_BITS "${DEFAULT_GODOT_BITS}" CACHE STRING "Architecture bits. Needs to be set manually for custom architecture") + + +list(APPEND GODOT_DEFINITIONS + WINDOWS_ENABLED + + $<${compiler_is_msvc}: + TYPED_METHOD_BIND + NOMINMAX + > +) + +list(APPEND GODOT_C_FLAGS + $<${compiler_is_msvc}: + /utf-8 + + $<$: + /MT + > + $<$>: + /MD + > + > +) + +list(APPEND GODOT_LINK_FLAGS + $<${compiler_is_msvc}: + /WX + > + $<$: + -Wl,--no-undefined + + $<$: + -static + -static-libgcc + -static-libstdc++ + > + > + $<${compiler_is_clang}: + -lstdc++ + > +) + +list(APPEND GODOT_COMPILE_WARNING_FLAGS + $<$: + -Wwrite-strings + > +) diff --git a/docs_generator.py b/docs_generator.py new file mode 100644 index 000000000..9466eb911 --- /dev/null +++ b/docs_generator.py @@ -0,0 +1,53 @@ +import hashlib +import os +import zlib + + +def make_doc(dst, source, compression_str="Z_BEST_COMPRESSION"): + os.makedirs(os.path.basename(dst), exist_ok=True) + g = open(dst, "w", encoding="utf-8") + buf = "" + docbegin = "" + docend = "" + for src_path in source: + if not src_path.endswith(".xml"): + continue + with open(src_path, "r", encoding="utf-8") as f: + content = f.read() + buf += content + + buf = (docbegin + buf + docend).encode("utf-8") + decomp_size = len(buf) + + buf = zlib.compress(buf, getattr(zlib, compression_str)) + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("\n") + g.write("#include \n") + g.write("\n") + + g.write('static const char *_doc_data_hash = "' + hashlib.md5(buf).hexdigest() + '";\n') + g.write("static const int _doc_data_uncompressed_size = " + str(decomp_size) + ";\n") + g.write("static const int _doc_data_compressed_size = " + str(len(buf)) + ";\n") + g.write("static const unsigned char _doc_data_compressed[] = {\n") + for i in range(len(buf)): + g.write("\t" + str(buf[i]) + ",\n") + g.write("};\n") + g.write("\n") + + g.write( + "static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);\n" + ) + g.write("\n") + + g.close() + + +# if ran as a script, use input args as: +# sys.argv[1] compression method +# sys.argv[2] destination file +# sys.argv[3:] .xml sources +if __name__ == "__main__": + import sys + + make_doc(sys.argv[2], sys.argv[3:], compression_str=sys.argv[1]) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 42ea6e086..a9b5dd57c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,143 +1,106 @@ +# Configuration can be used as a template for custom project, read comments cmake_minimum_required(VERSION 3.13) -project(godot-cpp-test) +project(gdexample LANGUAGES CXX) -set(GODOT_GDEXTENSION_DIR ../gdextension/ CACHE STRING "Path to GDExtension interface header directory") -set(CPP_BINDINGS_PATH ../ CACHE STRING "Path to C++ bindings") +set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel") +set(GODOT_CPP_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../) # path to godot-cpp + # repository -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - 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") - - 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() +add_subdirectory( + ${GODOT_CPP_PATH} ${CMAKE_CURRENT_BINARY_DIR}/godot-cpp # needed because + # godot-cpp is top + # directory +) -else() +# Get Sources +file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.c**) +file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS src/*.h**) - set(GODOT_LINKER_FLAGS "-static-libgcc -static-libstdc++ -Wl,-R,'$$ORIGIN'") +godot_clear_default_flags() - set(GODOT_COMPILE_FLAGS "-fPIC -g -Wwrite-strings") +get_target_property(LIBRARY_SUFFIX godot-cpp LIBRARY_SUFFIX) - 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() +if("${GODOT_TARGET}" STREQUAL "editor" OR "${GODOT_TARGET}" STREQUAL + "template_debug") + set(DOC_GEN_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src/gen/doc_data.gen.cpp") + file(GLOB_RECURSE DOC_FILES CONFIGURE_DEPENDS doc_classes/*.xml) -# 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() + godot_make_doc(DESTINATION ${DOC_GEN_PATH} SOURCES ${DOC_FILES} COMPRESSION + Z_BEST_COMPRESSION) + list(APPEND SOURCES ${DOC_GEN_PATH}) 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 - ${CPP_BINDINGS_PATH}/include - ${CPP_BINDINGS_PATH}/gen/include - ${GODOT_GDEXTENSION_DIR} -) - -# Create the correct name (godot.os.build_type.system_bits) -# Synchronized with godot-cpp's CMakeLists.txt - -set(BITS 32) -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) +if("${GODOT_PLATFORM}" STREQUAL "web") + # wasm libraries loaded with dlopen() are created like this in cmake + add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS}) + set_target_properties( + ${PROJECT_NAME} PROPERTIES SUFFIX ".wasm" + OUTPUT_NAME "${PROJECT_NAME}${LIBRARY_SUFFIX}") +elseif("${GODOT_PLATFORM}" STREQUAL "macos") + add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS}) + set(OUTPUT_NAME "lib${PROJECT_NAME}${LIBRARY_SUFFIX}") + set_target_properties( + ${PROJECT_NAME} + PROPERTIES FRAMEWORK TRUE + MACOSX_FRAMEWORK_IDENTIFIER "org.godotengine.lib${PROJECT_NAME}" + MACOSX_BUNDLE_BUNDLE_NAME "lib${PROJECT_NAME}${LIBRARY_SUFFIX}" + MACOSX_BUNDLE_SHORT_VERSION_STRING "1.0.0" + MACOS_BUNDLE_BUNDLE_VERSION "1.0.0" + OUTPUT_NAME "${OUTPUT_NAME}") + + # Workaround of 'bin/***.framework/Resources' existing in godot-cpp repo by + # default + set(RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/project/bin/\ +${OUTPUT_NAME}.framework/Resources") + if(IS_DIRECTORY ${RESOURCES_DIR} AND NOT IS_SYMLINK ${RESOURCES_DIR}) + message(STATUS "Removing '${RESOURCES_DIR}' to create symlink ...") + file(REMOVE_RECURSE ${RESOURCES_DIR}) + endif() + + # TODO: IOS configuration elseif("${GODOT_PLATFORM}" STREQUAL "ios") else() - set(GODOT_CPP_BUILD_TYPE Release) + add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS}) + set_target_properties( + ${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}${LIBRARY_SUFFIX}") 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}) +target_link_libraries(${PROJECT_NAME} PUBLIC godot-cpp) + +get_target_property(GODOT_C_FLAGS godot-cpp GODOT_C_FLAGS) +get_target_property(GODOT_CXX_FLAGS godot-cpp GODOT_CXX_FLAGS) +get_target_property(GODOT_COMPILE_WARNING_FLAGS godot-cpp + GODOT_COMPILE_WARNING_FLAGS) +target_compile_options( + ${PROJECT_NAME} PRIVATE ${GODOT_C_FLAGS} ${GODOT_CXX_FLAGS} + ${GODOT_COMPILE_WARNING_FLAGS}) + +get_target_property(GODOT_LINK_FLAGS godot-cpp GODOT_LINK_FLAGS) +target_link_options(${PROJECT_NAME} PRIVATE ${GODOT_LINK_FLAGS}) + +get_target_property(LIBRARY_SUFFIX godot-cpp LIBRARY_SUFFIX) +set_target_properties( + ${PROJECT_NAME} + PROPERTIES PREFIX "lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/project/bin" + LIBRARY_OUTPUT_DIRECTORY_DEBUG + "${CMAKE_CURRENT_SOURCE_DIR}/project/bin" + LIBRARY_OUTPUT_DIRECTORY_RELEASE + "${CMAKE_CURRENT_SOURCE_DIR}/project/bin" + LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO + "${CMAKE_CURRENT_SOURCE_DIR}/project/bin" + LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL + "${CMAKE_CURRENT_SOURCE_DIR}/project/bin" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/project/bin" + RUNTIME_OUTPUT_DIRECTORY_DEBUG + "${CMAKE_CURRENT_SOURCE_DIR}/project/bin" + RUNTIME_OUTPUT_DIRECTORY_RELEASE + "${CMAKE_CURRENT_SOURCE_DIR}/project/bin" + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO + "${CMAKE_CURRENT_SOURCE_DIR}/project/bin" + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL + "${CMAKE_CURRENT_SOURCE_DIR}/project/bin") + +if(${GODOT_WARNING_AS_ERROR}) + set_warning_as_error(${PROJECT_NAME}) endif() - -if(CMAKE_VERSION VERSION_GREATER "3.13") - target_link_directories(${PROJECT_NAME} - PRIVATE - ${CPP_BINDINGS_PATH}/bin/ - ) - - target_link_libraries(${PROJECT_NAME} - godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}$<$>:.${BITS}> - ) -else() - target_link_libraries(${PROJECT_NAME} - ${CPP_BINDINGS_PATH}/bin/libgodot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}$<$>:.${BITS}>.a - ) -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") diff --git a/tools/godotcpp.py b/tools/godotcpp.py index 9ceac02b1..8437e01ab 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -10,6 +10,7 @@ from SCons.Variables import BoolVariable, EnumVariable, PathVariable from SCons.Variables.BoolVariable import _text2bool +import docs_generator from binding_generator import scons_emit_files, scons_generate_bindings @@ -338,48 +339,8 @@ def options(opts, env): def make_doc_source(target, source, env): - import zlib - - dst = str(target[0]) - g = open(dst, "w", encoding="utf-8") - buf = "" - docbegin = "" - docend = "" - for src in source: - src_path = str(src) - if not src_path.endswith(".xml"): - continue - with open(src_path, "r", encoding="utf-8") as f: - content = f.read() - buf += content - - buf = (docbegin + buf + docend).encode("utf-8") - decomp_size = len(buf) - - # Use maximum zlib compression level to further reduce file size - # (at the cost of initial build times). - buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION) - - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("\n") - g.write("#include \n") - g.write("\n") - - g.write('static const char *_doc_data_hash = "' + str(hash(buf)) + '";\n') - g.write("static const int _doc_data_uncompressed_size = " + str(decomp_size) + ";\n") - g.write("static const int _doc_data_compressed_size = " + str(len(buf)) + ";\n") - g.write("static const unsigned char _doc_data_compressed[] = {\n") - for i in range(len(buf)): - g.write("\t" + str(buf[i]) + ",\n") - g.write("};\n") - g.write("\n") - - g.write( - "static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);\n" - ) - g.write("\n") - - g.close() + compression = env.get("compression", "Z_BEST_COMPRESSION") + docs_generator.make_doc(str(target[0]), [str(src) for src in source], compression) def generate(env):