From 41e809c3f024ed97aed3cee74f41dabd82da70d9 Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Mon, 26 Jun 2023 10:47:07 +0100 Subject: [PATCH] cxx-qt-lib: use +whole_archive for std_types so that cargo-only works When building with cargo we need to ensure that the statics aren't optimised out for registering types with Qt 5. Otherwise we cannot use numbers in QML. Also move std_types from -lib into -build, which potentially allows us to have cxx-qt-lib separate in the future. Closes #592 --- crates/cxx-qt-build/src/lib.rs | 31 +++++++++++++++++-- .../src/std_types_qt5.cpp} | 0 crates/cxx-qt-lib/build.rs | 5 +-- 3 files changed, 32 insertions(+), 4 deletions(-) rename crates/{cxx-qt-lib/src/std_types.cpp => cxx-qt-build/src/std_types_qt5.cpp} (100%) diff --git a/crates/cxx-qt-build/src/lib.rs b/crates/cxx-qt-build/src/lib.rs index e7db5fb51..2033e6ff9 100644 --- a/crates/cxx-qt-build/src/lib.rs +++ b/crates/cxx-qt-build/src/lib.rs @@ -389,12 +389,11 @@ impl CxxQtBuilder { // Ensure that the linker is setup correctly for Cargo builds qt_build_utils::setup_linker(); - let out_dir = env::var("OUT_DIR").unwrap(); // The include directory needs to be namespaced by crate name when exporting for a C++ build system, // but for using cargo build without a C++ build system, OUT_DIR is already namespaced by crate name. let header_root = match env::var("CXXQT_EXPORT_DIR") { Ok(export_dir) => format!("{export_dir}/{}", env::var("CARGO_PKG_NAME").unwrap()), - Err(_) => out_dir, + Err(_) => env::var("OUT_DIR").unwrap(), }; let generated_header_dir = format!("{header_root}/cxx-qt-gen"); @@ -429,6 +428,7 @@ impl CxxQtBuilder { // https://github.com/rust-lang/rust/issues/110912 cc_builder_whole_archive.link_lib_modifier("-bundle"); for builder in [&mut self.cc_builder, &mut cc_builder_whole_archive] { + // Note, ensure our settings stay in sync across cxx-qt-build and cxx-qt-lib builder.cpp(true); // MSVC builder.flag_if_supported("/std:c++17"); @@ -506,6 +506,33 @@ impl CxxQtBuilder { cc_builder_whole_archive.file(qtbuild.qrc(&qrc_file)); cc_builder_whole_archive_files_added = true; } + + // If we are using Qt 5 then write the std_types source + // This registers std numbers as a type for use in QML + // + // Note that we need this to be compiled into the whole_archive builder + // as they are stored in statics in the source. + if qtbuild.version().major == 5 { + let std_types_contents = include_str!("std_types_qt5.cpp"); + let std_types_path = format!( + "{out_dir}/std_types_qt5.cpp", + out_dir = env::var("OUT_DIR").unwrap() + ); + let mut source = + File::create(&std_types_path).expect("Could not create std_types source"); + write!(source, "{std_types_contents}").expect("Could not write std_types source"); + + cc_builder_whole_archive.file(&std_types_path); + cc_builder_whole_archive_files_added = true; + // Note we need to have std_types in the cc_builder for CMake builds to work. + // + // This is similar to how CMake needs to have qrc and QML module imports in the CMakeLists + // and they cannot just be in the build.rs and cc_builder_whole_archive. + // + // We likely need to have qt-static-initializers linked somewhere to solve this. + self.cc_builder.file(&std_types_path); + } + if cc_builder_whole_archive_files_added { cc_builder_whole_archive.compile("qt-static-initializers"); } diff --git a/crates/cxx-qt-lib/src/std_types.cpp b/crates/cxx-qt-build/src/std_types_qt5.cpp similarity index 100% rename from crates/cxx-qt-lib/src/std_types.cpp rename to crates/cxx-qt-build/src/std_types_qt5.cpp diff --git a/crates/cxx-qt-lib/build.rs b/crates/cxx-qt-lib/build.rs index 8c432f4cf..b7008e0f1 100644 --- a/crates/cxx-qt-lib/build.rs +++ b/crates/cxx-qt-lib/build.rs @@ -232,8 +232,6 @@ fn main() { } builder.file("src/qt_types.cpp"); println!("cargo:rerun-if-changed=src/qt_types.cpp"); - builder.file("src/std_types.cpp"); - println!("cargo:rerun-if-changed=src/std_types.cpp"); println!("cargo:rerun-if-changed=src/assertion_utils.h"); // Write this library's manually written C++ headers to files and add them to include paths @@ -251,11 +249,14 @@ fn main() { builder.define("CXX_QT_QML_FEATURE", None); } + // Note, ensure our settings stay in sync across cxx-qt-build and cxx-qt-lib + builder.cpp(true); // MSVC builder.flag_if_supported("/std:c++17"); builder.flag_if_supported("/Zc:__cplusplus"); builder.flag_if_supported("/permissive-"); // GCC + Clang builder.flag_if_supported("-std=c++17"); + builder.compile("cxx-qt-lib"); }