diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c4b62060..065adc566 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `QDateTime::from_string` to parse `QDateTime` from a `QString`. - Support for further types: `QUuid` +- Optional feature `cmake` to cxx-qt-build to prefer CMake instead of QMake for finding and linking to Qt. ### Fixed diff --git a/crates/cxx-qt-build/Cargo.toml b/crates/cxx-qt-build/Cargo.toml index 618b37fea..c4d811e8f 100644 --- a/crates/cxx-qt-build/Cargo.toml +++ b/crates/cxx-qt-build/Cargo.toml @@ -27,6 +27,7 @@ serde_json = "1.0" [features] link_qt_object_files = ["qt-build-utils/link_qt_object_files"] +cmake = ["qt-build-utils/cmake"] [lints] workspace = true diff --git a/crates/qt-build-utils/Cargo.toml b/crates/qt-build-utils/Cargo.toml index 751503e76..5e84a4102 100644 --- a/crates/qt-build-utils/Cargo.toml +++ b/crates/qt-build-utils/Cargo.toml @@ -17,6 +17,7 @@ rust-version.workspace = true cc.workspace = true versions = "6.3" thiserror.workspace = true +cmake-package = { version = "0.1.5", optional = true } [features] # When Cargo links an executable, whether a bin crate or test executable, @@ -31,5 +32,9 @@ thiserror.workspace = true # When linking Qt dynamically, this makes no difference. link_qt_object_files = [] +# Prefer using CMake to find Qt modules, instead of using qmake. +# This may be desirable in certain installations. +cmake = ["cmake-package"] + [lints] workspace = true diff --git a/crates/qt-build-utils/src/lib.rs b/crates/qt-build-utils/src/lib.rs index c6efff722..9104b811d 100644 --- a/crates/qt-build-utils/src/lib.rs +++ b/crates/qt-build-utils/src/lib.rs @@ -558,6 +558,30 @@ impl QtBuild { /// Get the include paths for Qt, including Qt module subdirectories. This is intended /// to be passed to whichever tool you are using to invoke the C++ compiler. pub fn include_paths(&self) -> Vec { + #[cfg(feature = "cmake")] + { + let Ok(package) = cmake_package::find_package(format!("Qt{}", self.version.major)) + .components(self.qt_modules.clone()) + .find() + else { + return Vec::default(); + }; + + let mut paths = Vec::new(); + for qt_module in &self.qt_modules { + if let Some(target) = package.target(format!("Qt::{}", qt_module)) { + paths.extend(target.include_directories); + } + } + + return paths + .iter() + .map(PathBuf::from) + // Only add paths if they exist + .filter(|path| path.exists()) + .collect(); + } + let root_path = self.qmake_query("QT_INSTALL_HEADERS"); let lib_path = self.qmake_query("QT_INSTALL_LIBS"); let mut paths = Vec::new(); @@ -591,6 +615,27 @@ impl QtBuild { /// Lazy load the path of a Qt executable tool /// Skip doing this in the constructor because not every user of this crate will use each tool fn get_qt_tool(&self, tool_name: &str) -> Result { + #[cfg(feature = "cmake")] + { + // QML tools live in the QML target, of course + let tools_component = if tool_name.contains("qml") { + "QmlTools" + } else { + "CoreTools" + }; + + let Ok(package) = cmake_package::find_package(format!("Qt{}", self.version.major)) + .components([tools_component.into()]) + .find() + else { + return Err(()); + }; + let Some(target) = package.target(format!("Qt6::{}", tool_name)) else { + return Err(()); + }; + return target.location.ok_or(()); + } + // "qmake -query" exposes a list of paths that describe where Qt executables and libraries // are located, as well as where new executables & libraries should be installed to. // We can use these variables to find any Qt tool. diff --git a/examples/cargo_without_cmake/Cargo.toml b/examples/cargo_without_cmake/Cargo.toml index cf39e21a3..9c55b7c2e 100644 --- a/examples/cargo_without_cmake/Cargo.toml +++ b/examples/cargo_without_cmake/Cargo.toml @@ -31,3 +31,6 @@ cxx-qt-lib = { workspace = true, features = ["full"] } # Use `cxx-qt-build = "0.7"` here instead! # The link_qt_object_files feature is required for statically linking Qt 6. cxx-qt-build = { workspace = true, features = [ "link_qt_object_files" ] } + +[features] +cmake = ["cxx-qt-build/cmake"]