Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .github/workflows/github-cxx-qt-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,8 @@ jobs:
# Ensure clippy and rustfmt is installed, they should come from github runner
#
# Note we still need rustfmt for the cxx-qt-gen tests
#
# TODO: Remove the `rustup default 1.77` selection.
# This is a workaround for Github Actions, which cannot currently compile CXX-Qt with Rust 1.78.
#
# See: https://github.com/KDAB/cxx-qt/issues/958
- name: "Install Rust toolchain"
run: rustup default 1.77 && rustup component add clippy rustfmt
run: rustup component add clippy rustfmt

- name: "Rust tools cache"
uses: actions/cache@v4
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(CompilerCaching)
include(CxxQt)

# Enable extra Qt definitions for all projects
add_compile_definitions(
Expand Down
122 changes: 122 additions & 0 deletions cmake/CxxQt.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
# SPDX-FileContributor: Andrew Hayzen <[email protected]>
# SPDX-FileContributor: Leon Matthes <[email protected]>
#
# SPDX-License-Identifier: MIT OR Apache-2.0

find_package(Corrosion QUIET)
if(NOT Corrosion_FOUND)
include(FetchContent)
FetchContent_Declare(
Corrosion
GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git
GIT_TAG v0.5.0
)

FetchContent_MakeAvailable(Corrosion)
endif()

function(cxxqt_import_crate)
cmake_parse_arguments(IMPORT_CRATE "" "CXXQT_EXPORT_DIR;QMAKE" "" ${ARGN})

corrosion_import_crate(IMPORTED_CRATES __cxxqt_imported_crates ${IMPORT_CRATE_UNPARSED_ARGUMENTS})

message(STATUS "CXX-Qt Found crate(s): ${__cxxqt_imported_crates}")

if (NOT DEFINED IMPORT_CRATE_CXXQT_EXPORT_DIR)
set(IMPORT_CRATE_CXXQT_EXPORT_DIR "${CMAKE_CURRENT_BINARY_DIR}/cxxqt/")
endif()
message(VERBOSE "CXX-Qt EXPORT_DIR: ${IMPORT_CRATE_CXXQT_EXPORT_DIR}")

if (NOT DEFINED IMPORT_CRATE_QMAKE)
get_target_property(QMAKE Qt::qmake IMPORTED_LOCATION)
if (NOT QMAKE STREQUAL "QMAKE-NOTFOUND")
set(IMPORT_CRATE_QMAKE "${QMAKE}")
else()
message(FATAL_ERROR "cxxqt_import_crate: QMAKE is not defined and could not be queried from the Qt::qmake target!\nPlease use the QMAKE argument to specify the path to the qmake executable or use find_package(Qt) before calling this function.")
endif()
endif()

foreach(CRATE ${__cxxqt_imported_crates})
corrosion_set_env_vars(${CRATE}
"CXXQT_EXPORT_DIR=${IMPORT_CRATE_CXXQT_EXPORT_DIR}"
"QMAKE=${IMPORT_CRATE_QMAKE}"
$<$<BOOL:${CMAKE_RUSTC_WRAPPER}>:RUSTC_WRAPPER=${CMAKE_RUSTC_WRAPPER}>)

file(MAKE_DIRECTORY "${IMPORT_CRATE_CXXQT_EXPORT_DIR}/include/${CRATE}")
target_include_directories(${CRATE} INTERFACE "${IMPORT_CRATE_CXXQT_EXPORT_DIR}/include/${CRATE}")

set_target_properties(${CRATE}
PROPERTIES
CXXQT_EXPORT_DIR "${IMPORT_CRATE_CXXQT_EXPORT_DIR}")

# cxx-qt-build generates object files that need to be linked to the final target.
# These are the static initializers that would be removed as an optimization if they're not referenced.
# So add them to an object library instead.
file(MAKE_DIRECTORY "${IMPORT_CRATE_CXXQT_EXPORT_DIR}/initializers/")
# When using the Ninja generator, we need to provide **some** way to generate the object file
# Unfortunately I'm not able to tell corrosion that this obj file is indeed a byproduct, so
# create a fake target for it.
# This target doesn't need to do anything, because the file should already exist after building the crate.
add_custom_target(${CRATE}_mock_initializers
COMMAND ${CMAKE_COMMAND} -E true
DEPENDS ${CRATE}
BYPRODUCTS "${IMPORT_CRATE_CXXQT_EXPORT_DIR}/initializers/${CRATE}.o")

add_library(${CRATE}_initializers OBJECT IMPORTED)
set_target_properties(${CRATE}_initializers
PROPERTIES
IMPORTED_OBJECTS "${IMPORT_CRATE_CXXQT_EXPORT_DIR}/initializers/${CRATE}.o")
# Note that we need to link using TARGET_OBJECTS, so that the object files are included **transitively**, otherwise
# Only the linker flags from the object library would be included, but not the actual object files.
# See also the "Linking Object Libraries" and "Linking Object Libraries via $<TARGET_OBJECTS>" sections:
# https://cmake.org/cmake/help/latest/command/target_link_libraries.html
target_link_libraries(${CRATE} INTERFACE ${CRATE}_initializers $<TARGET_OBJECTS:${CRATE}_initializers>)

message(VERBOSE "CXX-Qt Expects QML plugin: ${QML_MODULE_URI} in directory: ${QML_MODULE_PLUGIN_DIR}")
endforeach()

endfunction()


function(cxxqt_import_qml_module target)
cmake_parse_arguments(QML_MODULE "" "URI;SOURCE_CRATE" "" ${ARGN})

if (NOT DEFINED QML_MODULE_URI)
message(FATAL_ERROR "cxxqt_import_qml_module: URI must be specified!")
endif()

if (NOT DEFINED QML_MODULE_SOURCE_CRATE)
message(FATAL_ERROR "cxxqt_import_qml_module: SOURCE_CRATE must be specified!")
endif()

get_target_property(QML_MODULE_EXPORT_DIR ${QML_MODULE_SOURCE_CRATE} CXXQT_EXPORT_DIR)
get_target_property(QML_MODULE_CRATE_TYPE ${QML_MODULE_SOURCE_CRATE} TYPE)

if (${QML_MODULE_EXPORT_DIR} STREQUAL "QML_MODULE_EXPORT_DIR-NOTFOUND")
message(FATAL_ERROR "cxxqt_import_qml_module: SOURCE_CRATE must be a valid target that has been imported with cxxqt_import_crate!")
endif()

# Note: This needs to match the URI conversion in cxx-qt-build
string(REPLACE "." "_" plugin_name ${QML_MODULE_URI})
set(QML_MODULE_PLUGIN_DIR "${QML_MODULE_EXPORT_DIR}/plugins/${plugin_name}")
file(MAKE_DIRECTORY ${QML_MODULE_PLUGIN_DIR})

# QML plugin - init target
# When using the Ninja generator, we need to provide **some** way to generate the object file
# Unfortunately I'm not able to tell corrosion that this obj file is indeed a byproduct, so
# create a fake target for it.
# This target doesn't need to do anything, because the file should already exist after building the crate.
add_custom_target(${target}_mock_obj_output
COMMAND ${CMAKE_COMMAND} -E true
DEPENDS ${QML_MODULE_SOURCE_CRATE}
BYPRODUCTS "${QML_MODULE_PLUGIN_DIR}/plugin_init.o")

add_library(${target} OBJECT IMPORTED)
set_target_properties(${target}
PROPERTIES
IMPORTED_OBJECTS "${QML_MODULE_PLUGIN_DIR}/plugin_init.o")
target_link_libraries(${target} INTERFACE ${QML_MODULE_SOURCE_CRATE})

message(VERBOSE "CXX-Qt Expects QML plugin: ${QML_MODULE_URI} in directory: ${QML_MODULE_PLUGIN_DIR}")
endfunction()
Loading