Skip to content

Add version for cxx-qt-build/cxx-qt-lib #88

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ version = "0.6.0"
[workspace.dependencies]
cxx-qt = { path = "crates/cxx-qt" }
cxx-qt-macro = { path = "crates/cxx-qt-macro", version = "0.6.0" }
cxx-qt-build = { path = "crates/cxx-qt-build" }
cxx-qt-build = { path = "crates/cxx-qt-build", version = "0.6.0" }
cxx-qt-gen = { path = "crates/cxx-qt-gen", version = "0.6.0" }
cxx-qt-lib = { path = "crates/cxx-qt-lib" }
cxx-qt-lib = { path = "crates/cxx-qt-lib", version = "0.6.0" }
cxx-qt-lib-headers = { path = "crates/cxx-qt-lib-headers", version = "0.6.0" }
qt-build-utils = { path = "crates/qt-build-utils", version = "0.6.0" }

Expand Down
27 changes: 18 additions & 9 deletions crates/cxx-qt-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ use diagnostics::{Diagnostic, GeneratedError};

mod opts;
pub use opts::CxxQtBuildersOpts;
pub use opts::QObjectHeaderOpts;

mod qml_modules;
use qml_modules::OwningQmlModule;
pub use qml_modules::QmlModule;

pub use qt_build_utils::MocArguments;
use quote::ToTokens;
use std::{
collections::HashSet,
Expand Down Expand Up @@ -303,7 +305,7 @@ fn panic_duplicate_file_and_qml_module(
#[derive(Default)]
pub struct CxxQtBuilder {
rust_sources: Vec<PathBuf>,
qobject_headers: Vec<PathBuf>,
qobject_headers: Vec<QObjectHeaderOpts>,
qrc_files: Vec<PathBuf>,
qt_modules: HashSet<String>,
qml_modules: Vec<OwningQmlModule>,
Expand Down Expand Up @@ -414,10 +416,10 @@ impl CxxQtBuilder {

/// Specify a C++ header containing a Q_OBJECT macro to run [moc](https://doc.qt.io/qt-6/moc.html) on.
/// This allows building QObject C++ subclasses besides the ones autogenerated by cxx-qt.
pub fn qobject_header(mut self, path: impl AsRef<Path>) -> Self {
let path = path.as_ref();
self.qobject_headers.push(path.to_owned());
println!("cargo:rerun-if-changed={}", path.display());
pub fn qobject_header(mut self, opts: impl Into<QObjectHeaderOpts>) -> Self {
let opts = opts.into();
println!("cargo:rerun-if-changed={}", opts.path.display());
self.qobject_headers.push(opts);
self
}

Expand Down Expand Up @@ -557,13 +559,17 @@ impl CxxQtBuilder {
self.cc_builder.file(files.plain_cpp);
if let (Some(qobject), Some(qobject_header)) = (files.qobject, files.qobject_header) {
self.cc_builder.file(&qobject);
self.qobject_headers.push(qobject_header);
self.qobject_headers.push(qobject_header.into());
}
}

// Run moc on C++ headers with Q_OBJECT macro
for qobject_header in self.qobject_headers {
let moc_products = qtbuild.moc(&qobject_header, None);
for QObjectHeaderOpts {
path,
moc_arguments,
} in self.qobject_headers
{
let moc_products = qtbuild.moc(&path, moc_arguments);
self.cc_builder.file(moc_products.cpp);
}

Expand All @@ -581,7 +587,10 @@ impl CxxQtBuilder {
if let (Some(qobject), Some(qobject_header)) = (files.qobject, files.qobject_header)
{
self.cc_builder.file(&qobject);
let moc_products = qtbuild.moc(qobject_header, Some(&qml_module.uri));
let moc_products = qtbuild.moc(
qobject_header,
MocArguments::default().uri(qml_module.uri.clone()),
);
self.cc_builder.file(moc_products.cpp);
qml_metatypes_json.push(moc_products.metatypes_json);
}
Expand Down
44 changes: 43 additions & 1 deletion crates/cxx-qt-build/src/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use std::collections::HashSet;
use std::{
collections::HashSet,
path::{Path, PathBuf},
};

use crate::MocArguments;

/// Options for external crates to use
#[derive(Default)]
Expand Down Expand Up @@ -42,3 +47,40 @@ impl CxxQtBuildersOpts {
self
}
}

/// Options for qobject_headers
///
/// QObjectHeaderOpts can be created using the `From<impl AsRef<Path>>` trait.
/// ```
/// # use cxx_qt_build::{QObjectHeaderOpts, MocArguments};
/// QObjectHeaderOpts::from("path/to/header.h")
/// .moc_arguments(MocArguments::default());
/// ```
pub struct QObjectHeaderOpts {
pub(crate) path: PathBuf,
pub(crate) moc_arguments: MocArguments,
}

impl<T> From<T> for QObjectHeaderOpts
where
T: AsRef<Path>,
{
fn from(path: T) -> Self {
Self {
path: path.as_ref().to_owned(),
moc_arguments: MocArguments::default(),
}
}
}

impl QObjectHeaderOpts {
/// Set the moc arguments for this header
///
/// By default this is `MocArguments::default()`
pub fn moc_arguments(self, moc_arguments: MocArguments) -> Self {
Self {
moc_arguments,
..self
}
}
}
50 changes: 44 additions & 6 deletions crates/qt-build-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,34 @@ pub struct MocProducts {
pub metatypes_json: PathBuf,
}

/// Arguments for a Qt moc invocation.
/// See: [QtBuild::moc]
#[derive(Default, Clone)]
pub struct MocArguments {
uri: Option<String>,
include_paths: Vec<PathBuf>,
}

impl MocArguments {
/// Should be passed if the input_file is part of a QML module
pub fn uri(mut self, uri: String) -> Self {
self.uri = Some(uri);
self
}

/// Additional include path to pass to moc
pub fn include_path(mut self, include_path: PathBuf) -> Self {
self.include_paths.push(include_path);
self
}

/// Additional include paths to pass to moc.
pub fn include_paths(mut self, mut include_paths: Vec<PathBuf>) -> Self {
self.include_paths.append(&mut include_paths);
self
}
}

/// Paths to C++ files generated by [QtBuild::register_qml_module]
pub struct QmlModuleRegistrationFiles {
/// File generated by [rcc](https://doc.qt.io/qt-6/rcc.html) for the QML plugin. The compiled static library
Expand Down Expand Up @@ -550,8 +578,7 @@ impl QtBuild {
/// The return value contains the path to the generated C++ file, which can then be passed to [cc::Build::files](https://docs.rs/cc/latest/cc/struct.Build.html#method.file),
/// as well as the path to the generated metatypes.json file, which can be passed to [register_qml_module](Self::register_qml_module).
///
/// * uri - Should be passed if the input_file is part of a QML module
pub fn moc(&mut self, input_file: impl AsRef<Path>, uri: Option<&str>) -> MocProducts {
pub fn moc(&mut self, input_file: impl AsRef<Path>, arguments: MocArguments) -> MocProducts {
if self.moc_executable.is_none() {
self.moc_executable = Some(self.get_qt_tool("moc").expect("Could not find moc"));
}
Expand All @@ -566,14 +593,19 @@ impl QtBuild {
let metatypes_json_path = PathBuf::from(&format!("{}.json", output_path.display()));

let mut include_args = String::new();
for include_path in self.include_paths() {
// Qt includes
for include_path in self
.include_paths()
.iter()
.chain(arguments.include_paths.iter())
{
include_args += &format!("-I {} ", include_path.display());
}

let mut cmd = Command::new(self.moc_executable.as_ref().unwrap());

if let Some(uri) = uri {
cmd.arg(&format!("-Muri={}", uri));
if let Some(uri) = arguments.uri {
cmd.arg(&format!("-Muri={uri}"));
}

cmd.args(include_args.trim_end().split(' '));
Expand Down Expand Up @@ -847,7 +879,13 @@ public:
"#
)
.unwrap();
self.moc(&qml_plugin_cpp_path, Some(uri));
self.moc(
&qml_plugin_cpp_path,
MocArguments {
uri: Some(uri.to_owned()),
..Default::default()
},
);

// Generate file to load static QQmlExtensionPlugin
let mut qml_plugin_init = File::create(&qml_plugin_init_path).unwrap();
Expand Down