From 10df0ac3e4d96ad13c5eaa51dbff50b47f0b4b78 Mon Sep 17 00:00:00 2001 From: ytnuf <161308826+ytnuf@users.noreply.github.com> Date: Wed, 20 Mar 2024 20:53:56 +0000 Subject: [PATCH] Make godot-cpp installable with cmake config This is so this library can be used via a package manager The install destination uses CMAKE_INSTALL_ so that package managers can choose the best location for these artifacts godot-cpp-dev is the installed component this is so that if this library is a subproject, the user can install their project without installing this library by specifying the components As BUILD_INTERFACE requires absolute path, this means that GODOT_GDEXTENSION_DIR needs to be an absolute path config filename can either be PascalCase or kebab-case, the latter was chosen to be consistent with the package's name (godot-cpp) string(JSON ...) is only available in cmake v3.19, as it is used to obtain the version, this means that config-version file is only created when using cmake v3.19 or later --- CMakeLists.txt | 18 ++++++++---- cmake/config.cmake | 1 + cmake/install.cmake | 67 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 cmake/config.cmake create mode 100644 cmake/install.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index e71510268..dfbcfd189 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,10 @@ # -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 -DANDROID_PLATFORM=android-23 -DCMAKE_BUILD_TYPE=Debug . # cmake --build . # +# Installation (after the library is built): +# cmake --install --component godot-cpp-dev +# +# # 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 . @@ -65,9 +69,8 @@ if(NOT DEFINED BITS) endif() # Input from user for GDExtension interface header and the API JSON file -set(GODOT_GDEXTENSION_DIR "gdextension" CACHE STRING "") +set(GODOT_GDEXTENSION_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gdextension" CACHE STRING "") set(GODOT_CUSTOM_API_FILE "" CACHE STRING "") - 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}") @@ -183,9 +186,10 @@ if (GODOT_CPP_SYSTEM_HEADERS) endif () target_include_directories(${PROJECT_NAME} ${GODOT_CPP_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC - include - ${CMAKE_CURRENT_BINARY_DIR}/gen/include - ${GODOT_GDEXTENSION_DIR} + $ + $ + $ + $ ) # Add the compile flags @@ -213,4 +217,8 @@ set_target_properties(${PROJECT_NAME} LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" OUTPUT_NAME "${OUTPUT_NAME}" + EXPORT_NAME "cpp" # This ensures that the exported target is godot::cpp ) + + +include("cmake/install.cmake") diff --git a/cmake/config.cmake b/cmake/config.cmake new file mode 100644 index 000000000..d00f350ea --- /dev/null +++ b/cmake/config.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/godot-cpp-target.cmake") diff --git a/cmake/install.cmake b/cmake/install.cmake new file mode 100644 index 000000000..ebee704f8 --- /dev/null +++ b/cmake/install.cmake @@ -0,0 +1,67 @@ + +include("CMakePackageConfigHelpers") +include("GNUInstallDirs") + +# Install the library and headers to their respective install location +# CMAKE_INSTALL_ are used to allow the package manager to chose the install location +# Components are used so that if godot-cpp is a subproject, the user can chose not to install it +install(TARGETS "godot-cpp" + EXPORT "godot-cpp-target" + ARCHIVE + DESTINATION "${CMAKE_INSTALL_LIBDIR}" + COMPONENT "godot-cpp-dev" +) +install( + DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}/include/" + "${CMAKE_CURRENT_BINARY_DIR}/gen/include/" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT "godot-cpp-dev" +) +# Install the gdextension files +# The gdextension header is assumed to be the root include directory +# As the JSON file is neither a header nor lib file it goes to the datadir +install(FILES "${GODOT_GDEXTENSION_DIR}/gdextension_interface.h" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT "godot-cpp-dev" +) +install(FILES "${GODOT_GDEXTENSION_API_FILE}" + DESTINATION "${CMAKE_INSTALL_DATADIR}/godot-cpp" + COMPONENT "godot-cpp-dev" +) + +# Install the export config file +# This allows this library to be easily consumed by cmake projects: +# find_package("godot-cpp" 4.2.0 CONFIG REQUIRED) +# target_link_libaries("my-project" PRIVATE "godot::cpp") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/config.cmake" + RENAME "godot-cpp-config.cmake" + DESTINATION "${CMAKE_INSTALL_DATADIR}/godot-cpp" + COMPONENT "godot-cpp-dev" +) +install(EXPORT "godot-cpp-target" + NAMESPACE "godot::" + DESTINATION "${CMAKE_INSTALL_DATADIR}/godot-cpp" + COMPONENT "godot-cpp-dev" +) + +if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.19") # string(JSON...) only available in cmake v3.19+ + # Use the JSON api file to get the version + file(READ "${GODOT_GDEXTENSION_API_FILE}" GODOT_GDEXTENSION_API_JSON) + # GODOT_API_VERSION_MAJOR = GODOT_GDEXTENSION_API_JSON["header"]["version_major"] + string(JSON GODOT_API_VERSION_MAJOR GET "${GODOT_GDEXTENSION_API_JSON}" "header" "version_major") + string(JSON GODOT_API_VERSION_MINOR GET "${GODOT_GDEXTENSION_API_JSON}" "header" "version_minor") + string(JSON GODOT_API_VERSION_PATCH GET "${GODOT_GDEXTENSION_API_JSON}" "header" "version_patch") + set(GODOT_API_VERSION "${GODOT_API_VERSION_MAJOR}.${GODOT_API_VERSION_MINOR}.${GODOT_API_VERSION_PATCH}") + unset(GODOT_GDEXTENSION_API_JSON) + + # Install the config version file so that the gdextension version can be specified in find_package + write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/godot-cpp-config-version.cmake" + VERSION "${GODOT_API_VERSION}" + COMPATIBILITY SameMinorVersion + ) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/godot-cpp-config-version.cmake" + DESTINATION "${CMAKE_INSTALL_DATADIR}/godot-cpp" + COMPONENT "godot-cpp-dev" + ) +endif()