Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build cxx-qt-lib autogenerated C++ with Cargo instead of CMake #174

Merged
merged 5 commits into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 4 additions & 2 deletions .github/workflows/github-cxx-qt-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ jobs:
qt_version: 5
# FIXME: many tests fail to link
# https://github.com/KDAB/cxx-qt/issues/111
ctest_args: --exclude-regex '^(cxx_qt_gen_cargo_tests|demo_threading_cargo_tests|example_qml.*|qml.*tests|test.*|reuse_lint|cpp_clang_format|.*valgrind)$'
# cxx_qt_lib_cargo_tests fails to run with a missing DLL error.
Be-ing marked this conversation as resolved.
Show resolved Hide resolved
ctest_args: --exclude-regex '^(cxx_qt_gen_cargo_tests|demo_threading_cargo_tests|example_qml.*|qml.*tests|test.*|reuse_lint|cpp_clang_format|.*valgrind|cxx_qt_lib_cargo_tests)$'
exe_suffix: .exe
qt_qpa_platform: windows
compiler_cache_path: C:\Users\runneradmin\AppData\Local\Mozilla\sccache\cache
Expand All @@ -90,7 +91,8 @@ jobs:
qt_version: 6
# FIXME: many tests fail to link
# https://github.com/KDAB/cxx-qt/issues/111
ctest_args: --exclude-regex '^(cxx_qt_gen_cargo_tests|demo_threading_cargo_tests|example_qml.*|qml.*tests|test.*|reuse_lint|cpp_clang_format|.*valgrind)$'
# cxx_qt_lib_cargo_tests fails to run with a missing DLL error.
ctest_args: --exclude-regex '^(cxx_qt_gen_cargo_tests|demo_threading_cargo_tests|example_qml.*|qml.*tests|test.*|reuse_lint|cpp_clang_format|.*valgrind|cxx_qt_lib_cargo_tests)$'
exe_suffix: .exe
qt_qpa_platform: windows
compiler_cache_path: C:\Users\runneradmin\AppData\Local\Mozilla\sccache\cache
Expand Down
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,19 +149,32 @@ endfunction()
add_subdirectory(book)
add_subdirectory(examples)

# CARGO_TARGET_DIR is needed so the generated headers can be added to the
# include paths.
# QMAKE environment variable is needed by qt-build to ensure that Cargo
# uses the same installation of Qt as CMake does.
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui Test REQUIRED)
Be-ing marked this conversation as resolved.
Show resolved Hide resolved
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Test REQUIRED)
get_target_property(QMAKE Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION)
set(CARGO_ENV "QMAKE=${QMAKE};CARGO_TARGET_DIR=${CMAKE_CURRENT_SOURCE_DIR}/target")

# Create helper method which adds relevent cargo tests for a given manifest
function(add_test_cargo TEST_NAME_PREFIX MANIFEST_PATH ADD_DOCTESTS)
Be-ing marked this conversation as resolved.
Show resolved Hide resolved
# Add cargo as a test
add_test(NAME ${TEST_NAME_PREFIX}_cargo_tests COMMAND cargo test --all-targets --manifest-path ${MANIFEST_PATH})
set_property(TEST ${TEST_NAME_PREFIX}_cargo_tests PROPERTY ENVIRONMENT ${CARGO_ENV})
# Check if we should enable doc tests
if (${ADD_DOCTESTS} STREQUAL "DOCTESTS_ON")
# Add cargo docs as a test
add_test(NAME ${TEST_NAME_PREFIX}_cargo_doc_tests COMMAND cargo test --doc --manifest-path ${MANIFEST_PATH})
set_property(TEST ${TEST_NAME_PREFIX}_cargo_doc_tests PROPERTY ENVIRONMENT ${CARGO_ENV})
endif()
# Add clippy as a test
add_test(NAME ${TEST_NAME_PREFIX}_cargo_clippy COMMAND cargo clippy --all-targets --manifest-path ${MANIFEST_PATH} -- -D warnings)
set_property(TEST ${TEST_NAME_PREFIX}_cargo_clippy PROPERTY ENVIRONMENT ${CARGO_ENV})
# Add rustfmt as a test
add_test(NAME ${TEST_NAME_PREFIX}_cargo_fmt COMMAND cargo fmt --manifest-path ${MANIFEST_PATH} -- --check)
set_property(TEST ${TEST_NAME_PREFIX}_cargo_fmt PROPERTY ENVIRONMENT ${CARGO_ENV})
endfunction()

# Add cargo tests for all our manifests
Expand All @@ -180,6 +193,7 @@ add_test(NAME cxx_qt_gen_test_inputs_gen COMMAND rustfmt --check ${CXX_QT_GEN_TE
add_test(NAME cxx_qt_gen_test_outputs_gen COMMAND rustfmt --check ${CXX_QT_GEN_TEST_OUTPUTS})

# QML example has add_test in it's CMakeLists, so just add the cargo tests here
add_test_cargo(qt-build "${CMAKE_CURRENT_SOURCE_DIR}/qt-build/Cargo.toml" DOCTESTS_ON)
add_test_cargo(demo_threading "${CMAKE_CURRENT_SOURCE_DIR}/examples/demo_threading/Cargo.toml" DOCTESTS_OFF)
add_test_cargo(qml_features "${CMAKE_CURRENT_SOURCE_DIR}/examples/qml_features/Cargo.toml" DOCTESTS_OFF)
add_test_cargo(qml_extension_plugin "${CMAKE_CURRENT_SOURCE_DIR}/examples/qml_extension_plugin/core/Cargo.toml" DOCTESTS_OFF)
Expand Down
24 changes: 22 additions & 2 deletions cmake/CxxQt.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,18 @@ function(cxx_qt_generate_cpp GEN_SOURCES)

file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/target/cxx-qt-gen")

get_target_property(QMAKE Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION)

# Run cargo during config to ensure the cpp source file list is created
# CARGO_TARGET_DIR is needed so the generated headers can be added to the
# include paths.
# QMAKE environment variable is needed by qt-build to ensure that Cargo
# uses the same installation of Qt as CMake does.
execute_process(
COMMAND ${CARGO_CMD}
COMMAND cmake -E env
Be-ing marked this conversation as resolved.
Show resolved Hide resolved
"CARGO_TARGET_DIR=${CMAKE_CURRENT_SOURCE_DIR}/target"
"QMAKE=${QMAKE}"
${CARGO_CMD}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

Expand All @@ -62,6 +71,7 @@ function(cxx_qt_include APP_NAME)
target_include_directories(${APP_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
# Include the target folder so that cxx-qt-gen and cxx-qt-lib can be included
target_include_directories(${APP_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/target")
target_include_directories(${APP_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/target/cxxbridge")
# Our cxx_qt and cxx headers are in this folder and need to be included
target_include_directories(${APP_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/target/cxx-qt-gen/statics")
endfunction()
Expand Down Expand Up @@ -100,9 +110,19 @@ function(cxx_qt_link_rustlib APP_NAME)
else()
set(RUST_PART_LIB "${CMAKE_CURRENT_SOURCE_DIR}/target/${TARGET_DIR}/librust.a")
endif()

get_target_property(QMAKE Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION)

# CARGO_TARGET_DIR is needed so the generated headers can be added to the
# include paths.
# QMAKE environment variable is needed by qt-build to ensure that Cargo
# uses the same installation of Qt as CMake does.
add_custom_target(
"${APP_NAME}_rustlib"
COMMAND ${CARGO_CMD}
COMMAND cmake -E env
Be-ing marked this conversation as resolved.
Show resolved Hide resolved
"CARGO_TARGET_DIR=${CMAKE_CURRENT_SOURCE_DIR}/target"
"QMAKE=${QMAKE}"
${CARGO_CMD}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_dependencies(${APP_NAME} "${APP_NAME}_rustlib")
Expand Down
63 changes: 1 addition & 62 deletions cxx-qt-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,61 +233,6 @@ fn write_cpp_sources_list(paths: &[PathBuf]) {
}
}

/// Write our a given cxx-qt-lib header and source set to the given folder
fn write_cxx_qt_lib_set(
file_name: &str,
target_dir: &str,
header: &str,
source: &str,
) -> Vec<PathBuf> {
let mut paths = vec![];
let path_h = PathBuf::from(format!("{}/include/{}.h", target_dir, file_name));
let path_cpp = PathBuf::from(format!("{}/src/{}.cpp", target_dir, file_name));

let mut file = std::fs::File::create(&path_h).expect("Could not create header file");
file.write_all(header.as_bytes())
.expect("Could not write header file");
paths.push(path_h);

let mut file = std::fs::File::create(&path_cpp).expect("Could not create source file");
file.write_all(source.as_bytes())
.expect("Could not write source file");
paths.push(path_cpp);

paths
}

/// Find all the cxx-qt-lib sources and write them to the target directory
fn write_cxx_qt_lib_sources() -> Vec<PathBuf> {
let cxx_qt_lib_target_dir = format!("{}/target/cxx-qt-lib", manifest_dir());
let cxx_qt_lib_include_dir = format!("{}/include", cxx_qt_lib_target_dir);
let cxx_qt_lib_src_dir = format!("{}/src", cxx_qt_lib_target_dir);
std::fs::create_dir_all(&cxx_qt_lib_include_dir).unwrap();
std::fs::create_dir_all(&cxx_qt_lib_src_dir).unwrap();

let mut paths = vec![];
// Add the hand written qt_types file
paths.append(&mut write_cxx_qt_lib_set(
"qt_types",
&cxx_qt_lib_target_dir,
cxx_qt_lib::QT_TYPES_HEADER,
cxx_qt_lib::QT_TYPES_SOURCE,
));
// Add the generated CXX files
let generated: Vec<GeneratedType> =
serde_json::from_str(cxx_qt_lib::QT_TYPES_CXX_JSON).unwrap();
for gen in generated {
paths.append(&mut write_cxx_qt_lib_set(
&gen.name,
&cxx_qt_lib_target_dir,
&gen.header,
&gen.source,
));
}

paths
}

/// Write out the static header file for both the cxx
fn write_cxx_static_header() {
let manifest_dir = manifest_dir();
Expand Down Expand Up @@ -353,19 +298,13 @@ impl CxxQtBuilder {
// TODO: later use the module::object to turn into module/object.h

// Generate files
let mut cpp_paths = write_cxx_generated_files_for_cargo(&self.rust_sources);
let cpp_paths = write_cxx_generated_files_for_cargo(&self.rust_sources);

// TODO: in large projects where where CXX-Qt is used in multiple individual
// components that end up being linked together, having these same static
// files in each one could cause issues.
write_cxx_static_header();

// Check if we have Qt support enabled
if self.qt_enabled {
// Write the cxx-qt-lib sources into the folder
cpp_paths.append(&mut write_cxx_qt_lib_sources());
}

// TODO: find a way to only do this when cargo is called during the config stage of CMake
write_cpp_sources_list(&cpp_paths);
}
Expand Down
7 changes: 2 additions & 5 deletions cxx-qt-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,5 @@ links = "cxx-qt-lib"
cxx = "1.0"

[build-dependencies]
cxx-gen = "0.7"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
syn = { version = "1.0", features = ["printing"] }
quote = "1.0"
cxx-build = "1.0"
qt-build = { path = "../qt-build" }
Loading