diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dae1da90..ec5565d65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add CMake wrappers around corrosion to simplify importing crates and qml modules that were built with cxx-qt-build - CMake code has been extracted into a separate repository for faster downloads (kdab/cxx-qt-cmake) - Folder structure of Rust bridges is now considered in the same way as CXX in `CxxQtBuilder` +- All `#[cxx_qt::bridge]` macros must specify a `cxx_file_stem` until `Span::source_file()` is stable ### Removed diff --git a/book/src/bridge/extern_rustqt.md b/book/src/bridge/extern_rustqt.md index 6c05f68f5..8aa7f162e 100644 --- a/book/src/bridge/extern_rustqt.md +++ b/book/src/bridge/extern_rustqt.md @@ -23,7 +23,9 @@ mod ffi { The `extern "RustQt"` section of a CXX bridge declares Rust types and signatures to be made available to Qt and C++. -The CXX code generator uses your `extern "Rust"` section(s) to produce a C++ header file containing the corresponding C++ declarations. The generated header has a file name matching the module ident or the `cxx_file_stem` field in the `#[cxx_qt::bridge]` attribute and with a `.cxxqt.h` file extension. +The CXX code generator uses your `extern "Rust"` section(s) to produce a C++ header file containing the corresponding C++ declarations. The generated header has a file name of the `cxx_file_stem` field in the `#[cxx_qt::bridge]` attribute and with a `.cxxqt.h` file extension. + +> Note that once there is support for `source_file` or similar in the `Span` macro we want to support copying the file name like CXX. A bridge module may contain zero or more `extern "RustQt"` blocks. diff --git a/book/src/bridge/index.md b/book/src/bridge/index.md index 3cd4da9d6..e9adedf44 100644 --- a/book/src/bridge/index.md +++ b/book/src/bridge/index.md @@ -30,7 +30,7 @@ By default, the name of the generated C++ header file will be the name of the mo This can cause issues as the module is normally called `ffi` or `qobject`, so collisions would occur. -The `cxx_file_stem` option allow a file name to be specified to avoid collisions. +The `cxx_file_stem` option allows a file name to be specified to avoid collisions. ```rust,ignore {{#include ../../../examples/qml_features/rust/src/types.rs:book_cxx_file_stem}} diff --git a/book/src/getting-started/5-cmake-integration.md b/book/src/getting-started/5-cmake-integration.md index 6e47a9c97..d8d8e6e46 100644 --- a/book/src/getting-started/5-cmake-integration.md +++ b/book/src/getting-started/5-cmake-integration.md @@ -38,10 +38,14 @@ You can add as much C++ code as you want in addition to this. For every `#[cxx_qt::bridge]` that we define in Rust, CXX-Qt will generate a corresponding C++ header file. To include any of the generated files, use the crates name as the include directory. -The name of the header file will be the name of the Rust module of your `#[cxx_qt::bridge]`, followed by `.cxxqt.h`. -So in our case: `#include ` +The name of the header file will be the folder names, combined with the `cxx_file_stem` of your `#[cxx_qt::bridge]`, followed by `.cxxqt.h`. +So in our case: `#include ` -> Note that the [`cxx_file_stem`](../bridge/index.md#cxx_file_stem) option can be specified in the bridge macro to choose the file name. +> Note that the [`cxx_file_stem`](../bridge/index.md#cxx_file_stem) option must be specified in the bridge macro to choose the file name. + +> Note that once `Span::source_file()` is stable the `cxx_file_stem` will be optional and the file name will be the default like CXX> + +> Note any folders relative to the cargo manifest are considered hence the `src` folder. Including the generated header allows us to access the `MyObject` C++ class, just like any other C++ class. Inherit from it, connect signals and slots to it, put it in a QVector, do whatever you want with it. diff --git a/crates/cxx-qt-build/src/lib.rs b/crates/cxx-qt-build/src/lib.rs index 9c21e5207..526f42b59 100644 --- a/crates/cxx-qt-build/src/lib.rs +++ b/crates/cxx-qt-build/src/lib.rs @@ -138,13 +138,9 @@ impl GeneratedCpp { let rust_tokens = write_rust(&generated_rust); // Use the relative path with the cxx_file_stem - // - // TODO: ideally CXX-Qt would also use the file name - // but it uses the module or cxx_file_stem for now - // https://github.com/KDAB/cxx-qt/pull/200/commits/4861c92e66c3a022d3f0dedd9f8fd20db064b42b file_ident = relative_path .as_ref() - .with_file_name(parser.cxx_file_stem) + .with_file_name(parser.cxx_file_stem()) .to_str() .unwrap() .clone_into(&mut file_ident); @@ -275,7 +271,6 @@ fn generate_cxxqt_cpp_files( let mut generated_file_paths: Vec = Vec::with_capacity(rs_source.len()); for rs_path in rs_source { - let cpp_directory = cxx_qt_dir.join("src"); let path = manifest_dir.join(rs_path); println!("cargo:rerun-if-changed={}", path.to_string_lossy()); @@ -286,7 +281,7 @@ fn generate_cxxqt_cpp_files( std::process::exit(1); } }; - generated_file_paths.push(generated_code.write_to_directories(cpp_directory, &header_dir)); + generated_file_paths.push(generated_code.write_to_directories(cxx_qt_dir, &header_dir)); } generated_file_paths diff --git a/crates/cxx-qt-gen/src/generator/cpp/mod.rs b/crates/cxx-qt-gen/src/generator/cpp/mod.rs index fcd96bc53..45b160ab0 100644 --- a/crates/cxx-qt-gen/src/generator/cpp/mod.rs +++ b/crates/cxx-qt-gen/src/generator/cpp/mod.rs @@ -66,7 +66,7 @@ impl GeneratedCppBlocks { Ok(GeneratedCppBlocks { forward_declares, includes, - cxx_file_stem: parser.cxx_file_stem.clone(), + cxx_file_stem: parser.cxx_file_stem(), qobjects: structures .qobjects .iter() @@ -119,7 +119,7 @@ mod tests { #[test] fn test_generated_cpp_blocks() { let module: ItemMod = parse_quote! { - #[cxx_qt::bridge] + #[cxx_qt::bridge(cxx_file_stem = "ffi")] mod ffi { extern "RustQt" { #[qobject] @@ -157,7 +157,7 @@ mod tests { #[test] fn test_generated_cpp_blocks_namespace() { let module: ItemMod = parse_quote! { - #[cxx_qt::bridge(namespace = "cxx_qt")] + #[cxx_qt::bridge(cxx_file_stem = "ffi", namespace = "cxx_qt")] mod ffi { extern "RustQt" { #[qobject] diff --git a/crates/cxx-qt-gen/src/generator/rust/mod.rs b/crates/cxx-qt-gen/src/generator/rust/mod.rs index 0c85e30a4..ad8cf0b73 100644 --- a/crates/cxx-qt-gen/src/generator/rust/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/mod.rs @@ -86,7 +86,7 @@ impl GeneratedRustBlocks { fn generate_include(parser: &Parser) -> Result { let import_path = format!( "{header_prefix}/{}.cxxqt.h", - parser.cxx_file_stem, + parser.cxx_file_stem(), header_prefix = writer::get_header_prefix() ); diff --git a/crates/cxx-qt-gen/src/parser/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index 3a57501db..c41122cd4 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -40,13 +40,13 @@ pub struct Parser { /// all type names that were found in this module, including CXX types pub(crate) type_names: TypeNames, /// The stem of the file that the CXX headers for this module will be generated into - pub cxx_file_stem: String, + pub(crate) cxx_file_stem: Option, } impl Parser { - fn parse_mod_attributes(module: &mut ItemMod) -> Result<(Option, String)> { + fn parse_mod_attributes(module: &mut ItemMod) -> Result<(Option, Option)> { let mut namespace = None; - let mut cxx_file_stem = module.ident.to_string(); + let mut cxx_file_stem = None; // Remove the cxx_qt::bridge attribute if let Some(attr) = attribute_take_path(&mut module.attrs, &["cxx_qt", "bridge"]) { @@ -62,13 +62,21 @@ impl Parser { namespace = Some(expr_to_string(&name_value.value)?); // Parse any custom file stem } else if name_value.path.is_ident("cxx_file_stem") { - cxx_file_stem = expr_to_string(&name_value.value)?; + cxx_file_stem = Some(expr_to_string(&name_value.value)?); } } _others => {} } } } + + // Temporary until Span::source_file() is stable + if cxx_file_stem.is_none() { + return Err(Error::new( + module.span(), + "All cxx_qt::bridge macros specify a cxx_file_stem until Span::source_file() is stable https://github.com/rust-lang/rust/issues/54725", + )); + } } else { return Err(Error::new( module.span(), @@ -150,6 +158,17 @@ impl Parser { cxx_file_stem, }) } + + /// Determine the file stem to use for this macro + pub fn cxx_file_stem(&self) -> String { + if let Some(cxx_file_stem) = self.cxx_file_stem.as_ref() { + cxx_file_stem.clone() + } else { + // TODO: ideally CXX-Qt would also use the file name but it uses the cxx_file_stem for now + // https://github.com/KDAB/cxx-qt/pull/200/commits/4861c92e66c3a022d3f0dedd9f8fd20db064b42b + unimplemented!("Missing cxx_file_stem, once Span::source_file() is stable we can determine the file name") + } + } } #[cfg(test)] diff --git a/crates/cxx-qt-gen/test_inputs/inheritance.rs b/crates/cxx-qt-gen/test_inputs/inheritance.rs index f3a9cf6e7..5f9e50638 100644 --- a/crates/cxx-qt-gen/test_inputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_inputs/inheritance.rs @@ -1,4 +1,4 @@ -#[cxx_qt::bridge] +#[cxx_qt::bridge(cxx_file_stem = "inheritance")] mod inheritance { extern "C++" { include!("cxx-qt-lib/qmodelindex.h"); diff --git a/crates/cxx-qt-gen/test_inputs/invokables.rs b/crates/cxx-qt-gen/test_inputs/invokables.rs index 17f5e1e92..d08b2e1f4 100644 --- a/crates/cxx-qt-gen/test_inputs/invokables.rs +++ b/crates/cxx-qt-gen/test_inputs/invokables.rs @@ -1,4 +1,4 @@ -#[cxx_qt::bridge(namespace = "cxx_qt::my_object")] +#[cxx_qt::bridge(cxx_file_stem = "invokables", namespace = "cxx_qt::my_object")] mod ffi { #[namespace = ""] unsafe extern "C++" { diff --git a/crates/cxx-qt-gen/test_inputs/properties.rs b/crates/cxx-qt-gen/test_inputs/properties.rs index 3e07fae22..fa7a5c8b1 100644 --- a/crates/cxx-qt-gen/test_inputs/properties.rs +++ b/crates/cxx-qt-gen/test_inputs/properties.rs @@ -1,4 +1,4 @@ -#[cxx_qt::bridge(namespace = "cxx_qt::my_object")] +#[cxx_qt::bridge(cxx_file_stem = "properties", namespace = "cxx_qt::my_object")] mod ffi { #[namespace = ""] unsafe extern "C++" { diff --git a/crates/cxx-qt-gen/test_inputs/qenum.rs b/crates/cxx-qt-gen/test_inputs/qenum.rs index c485c8380..06740d157 100644 --- a/crates/cxx-qt-gen/test_inputs/qenum.rs +++ b/crates/cxx-qt-gen/test_inputs/qenum.rs @@ -1,4 +1,4 @@ -#[cxx_qt::bridge(namespace = "cxx_qt::my_object")] +#[cxx_qt::bridge(cxx_file_stem = "qenum", namespace = "cxx_qt::my_object")] mod ffi { #[qenum(MyObject)] enum MyEnum { diff --git a/crates/cxx-qt-gen/test_inputs/shebang.rs b/crates/cxx-qt-gen/test_inputs/shebang.rs index 80832760b..b24fa2bae 100644 --- a/crates/cxx-qt-gen/test_inputs/shebang.rs +++ b/crates/cxx-qt-gen/test_inputs/shebang.rs @@ -1,6 +1,6 @@ #!/usr/bin/ // Test for qtitem and qtfile, for code coverage -#[cxx_qt::bridge] +#[cxx_qt::bridge(cxx_file_stem = "shebang")] mod ffi { extern "RustQt" { #[qobject] diff --git a/crates/cxx-qt-gen/test_inputs/signals.rs b/crates/cxx-qt-gen/test_inputs/signals.rs index 3aca1f5bd..2c35a0e1e 100644 --- a/crates/cxx-qt-gen/test_inputs/signals.rs +++ b/crates/cxx-qt-gen/test_inputs/signals.rs @@ -1,4 +1,4 @@ -#[cxx_qt::bridge(namespace = "cxx_qt::my_object")] +#[cxx_qt::bridge(cxx_file_stem = "signals", namespace = "cxx_qt::my_object")] mod ffi { #[namespace = ""] unsafe extern "C++" { diff --git a/crates/cxx-qt-gen/test_outputs/invokables.cpp b/crates/cxx-qt-gen/test_outputs/invokables.cpp index c3f79859e..9b83ab80e 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.cpp +++ b/crates/cxx-qt-gen/test_outputs/invokables.cpp @@ -1,4 +1,4 @@ -#include "cxx-qt-gen/ffi.cxxqt.h" +#include "cxx-qt-gen/invokables.cxxqt.h" namespace cxx_qt::my_object { void diff --git a/crates/cxx-qt-gen/test_outputs/invokables.h b/crates/cxx-qt-gen/test_outputs/invokables.h index e2c0bff26..172bd8366 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.h +++ b/crates/cxx-qt-gen/test_outputs/invokables.h @@ -10,7 +10,7 @@ using MyObjectCxxQtThread = ::rust::cxxqt1::CxxQtThread; } // namespace cxx_qt::my_object -#include "cxx-qt-gen/ffi.cxx.h" +#include "cxx-qt-gen/invokables.cxx.h" namespace cxx_qt::my_object { class MyObject diff --git a/crates/cxx-qt-gen/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index 4d43f4ee4..cacfdbcbc 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -25,7 +25,7 @@ mod ffi { type QMetaObjectConnection = cxx_qt::QMetaObjectConnection; } unsafe extern "C++" { - include!("cxx-qt-gen/ffi.cxxqt.h"); + include!("cxx-qt-gen/invokables.cxxqt.h"); } unsafe extern "C++" { #[doc = "The C++ type for the QObject "] diff --git a/crates/cxx-qt-gen/test_outputs/properties.cpp b/crates/cxx-qt-gen/test_outputs/properties.cpp index adc71444f..f64018635 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.cpp +++ b/crates/cxx-qt-gen/test_outputs/properties.cpp @@ -1,4 +1,4 @@ -#include "cxx-qt-gen/ffi.cxxqt.h" +#include "cxx-qt-gen/properties.cxxqt.h" // Define namespace otherwise we hit a GCC bug // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480 diff --git a/crates/cxx-qt-gen/test_outputs/properties.h b/crates/cxx-qt-gen/test_outputs/properties.h index a3764c763..11ca2b7a9 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.h +++ b/crates/cxx-qt-gen/test_outputs/properties.h @@ -32,7 +32,7 @@ using MyObjectCxxQtSignalHandlermyOnChanged = ::rust::cxxqt1::SignalHandler; } // namespace cxx_qt::my_object::rust::cxxqtgen1 -#include "cxx-qt-gen/ffi.cxx.h" +#include "cxx-qt-gen/properties.cxx.h" namespace cxx_qt::my_object::rust::cxxqtgen1 { ::QMetaObject::Connection diff --git a/crates/cxx-qt-gen/test_outputs/properties.rs b/crates/cxx-qt-gen/test_outputs/properties.rs index 4e30a6020..772752941 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -18,7 +18,7 @@ mod ffi { type QMetaObjectConnection = cxx_qt::QMetaObjectConnection; } unsafe extern "C++" { - include!("cxx-qt-gen/ffi.cxxqt.h"); + include!("cxx-qt-gen/properties.cxxqt.h"); } unsafe extern "C++" { #[doc = "The C++ type for the QObject "] diff --git a/crates/cxx-qt-gen/test_outputs/qenum.cpp b/crates/cxx-qt-gen/test_outputs/qenum.cpp index ca47d96c2..899fdf535 100644 --- a/crates/cxx-qt-gen/test_outputs/qenum.cpp +++ b/crates/cxx-qt-gen/test_outputs/qenum.cpp @@ -1,4 +1,4 @@ -#include "cxx-qt-gen/ffi.cxxqt.h" +#include "cxx-qt-gen/qenum.cxxqt.h" namespace cxx_qt::my_object { void diff --git a/crates/cxx-qt-gen/test_outputs/qenum.h b/crates/cxx-qt-gen/test_outputs/qenum.h index 15547536a..5b3dfca36 100644 --- a/crates/cxx-qt-gen/test_outputs/qenum.h +++ b/crates/cxx-qt-gen/test_outputs/qenum.h @@ -72,7 +72,7 @@ enum class MyRenamedEnum : ::std::int32_t }; } // namespace cxx_qt::my_object -#include "cxx-qt-gen/ffi.cxx.h" +#include "cxx-qt-gen/qenum.cxx.h" namespace cxx_qt::my_object { class MyObject diff --git a/crates/cxx-qt-gen/test_outputs/qenum.rs b/crates/cxx-qt-gen/test_outputs/qenum.rs index 01c49f0e6..72a9192f7 100644 --- a/crates/cxx-qt-gen/test_outputs/qenum.rs +++ b/crates/cxx-qt-gen/test_outputs/qenum.rs @@ -62,7 +62,7 @@ mod ffi { type MyRenamedEnum; } unsafe extern "C++" { - include!("cxx-qt-gen/ffi.cxxqt.h"); + include!("cxx-qt-gen/qenum.cxxqt.h"); } unsafe extern "C++" { #[doc = "The C++ type for the QObject "] diff --git a/crates/cxx-qt-gen/test_outputs/signals.cpp b/crates/cxx-qt-gen/test_outputs/signals.cpp index 6930eaf89..c24619e7f 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.cpp +++ b/crates/cxx-qt-gen/test_outputs/signals.cpp @@ -1,4 +1,4 @@ -#include "cxx-qt-gen/ffi.cxxqt.h" +#include "cxx-qt-gen/signals.cxxqt.h" // Define namespace otherwise we hit a GCC bug // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480 diff --git a/crates/cxx-qt-gen/test_outputs/signals.h b/crates/cxx-qt-gen/test_outputs/signals.h index 0c9eb7e4e..31740a4da 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.h +++ b/crates/cxx-qt-gen/test_outputs/signals.h @@ -30,7 +30,7 @@ using QTimerCxxQtSignalHandlertimeout = ::rust::cxxqt1::SignalHandler; } // namespace cxx_qt::my_object::rust::cxxqtgen1 -#include "cxx-qt-gen/ffi.cxx.h" +#include "cxx-qt-gen/signals.cxx.h" namespace cxx_qt::my_object::rust::cxxqtgen1 { ::QMetaObject::Connection diff --git a/crates/cxx-qt-gen/test_outputs/signals.rs b/crates/cxx-qt-gen/test_outputs/signals.rs index 263d973b1..668f03c6f 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.rs +++ b/crates/cxx-qt-gen/test_outputs/signals.rs @@ -19,7 +19,7 @@ mod ffi { type QMetaObjectConnection = cxx_qt::QMetaObjectConnection; } unsafe extern "C++" { - include!("cxx-qt-gen/ffi.cxxqt.h"); + include!("cxx-qt-gen/signals.cxxqt.h"); } unsafe extern "C++" { #[doc = "The C++ type for the QObject "] diff --git a/examples/qml_minimal/rust/src/cxxqt_object.rs b/examples/qml_minimal/rust/src/cxxqt_object.rs index 60d7ec8ab..f6a2e99e7 100644 --- a/examples/qml_minimal/rust/src/cxxqt_object.rs +++ b/examples/qml_minimal/rust/src/cxxqt_object.rs @@ -9,7 +9,7 @@ // ANCHOR: book_bridge_macro /// The bridge definition for our QObject -#[cxx_qt::bridge] +#[cxx_qt::bridge(cxx_file_stem = "cxxqt_object")] pub mod qobject { // ANCHOR_END: book_bridge_macro