Skip to content

Commit

Permalink
cxx-qt-gen: require cxx_file_stem until Span::source_file is stable
Browse files Browse the repository at this point in the history
Closes KDAB#855
  • Loading branch information
ahayzen-kdab committed Apr 18, 2024
1 parent bd6d571 commit 26a5d30
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `#[qobject]` attribute is now optional on types in `extern "RustQt"`
- `#[qobject]` attribute is now required on types in `extern "C++Qt"`
- 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

### Fixed

Expand Down
4 changes: 3 additions & 1 deletion book/src/bridge/extern_rustqt.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion book/src/bridge/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down
8 changes: 6 additions & 2 deletions book/src/getting-started/5-cmake-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,15 @@ 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.
They will always be in the `cxx-qt-gen/` include path and use the snake_case naming convention.
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 cxx-qt-gen/qobject.cxxqt.h`
The name of the header file will be the `cxx_file_stem` of your `#[cxx_qt::bridge]`, followed by `.cxxqt.h`.
So in our case: `#include cxx-qt-gen/src/cxxqt_object.cxxqt.h`

> 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 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 fargo manifest are considered hence the `src` folder.
Including the generated header allows accessing 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.
That's the power of CXX-Qt.
Expand Down
6 changes: 1 addition & 5 deletions crates/cxx-qt-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,9 @@ impl GeneratedCpp {
.map_err(to_diagnostic)?;
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()
.to_owned();
Expand Down
6 changes: 3 additions & 3 deletions crates/cxx-qt-gen/src/generator/cpp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl GeneratedCppBlocks {
Ok(GeneratedCppBlocks {
forward_declares,
includes,
cxx_file_stem: parser.cxx_file_stem.clone(),
cxx_file_stem: parser.cxx_file_stem(),
qobjects: parser
.cxx_qt_data
.qobjects
Expand All @@ -86,7 +86,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]
Expand Down Expand Up @@ -124,7 +124,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]
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/src/generator/rust/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl GeneratedRustBlocks {

/// Generate the include line for this parsed block
fn generate_include(parser: &Parser) -> Result<Item> {
let import_path = format!("{}.cxxqt.h", parser.cxx_file_stem);
let import_path = format!("{}.cxxqt.h", parser.cxx_file_stem());

syn::parse2(quote! {
unsafe extern "C++" {
Expand Down
27 changes: 23 additions & 4 deletions crates/cxx-qt-gen/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,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<String>,
}

impl Parser {
fn parse_mod_attributes(module: &mut ItemMod) -> Result<(Option<String>, String)> {
fn parse_mod_attributes(module: &mut ItemMod) -> Result<(Option<String>, Option<String>)> {
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"]) {
Expand All @@ -58,13 +58,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(),
Expand Down Expand Up @@ -127,6 +135,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)]
Expand Down
2 changes: 1 addition & 1 deletion examples/qml_minimal/rust/src/cxxqt_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 26a5d30

Please sign in to comment.