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 Aug 23, 2024
1 parent 60ae68b commit 38f44c2
Show file tree
Hide file tree
Showing 27 changed files with 60 additions and 39 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

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
10 changes: 7 additions & 3 deletions book/src/getting-started/5-cmake-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <qml_minimal/qobject.cxxqt.h>`
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 <qml_minimal/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 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.
Expand Down
9 changes: 2 additions & 7 deletions crates/cxx-qt-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -275,7 +271,6 @@ fn generate_cxxqt_cpp_files(

let mut generated_file_paths: Vec<GeneratedCppFilePaths> = 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());

Expand All @@ -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
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 @@ -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()
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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]
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 @@ -86,7 +86,7 @@ impl GeneratedRustBlocks {
fn generate_include(parser: &Parser) -> Result<Item> {
let import_path = format!(
"{header_prefix}/{}.cxxqt.h",
parser.cxx_file_stem,
parser.cxx_file_stem(),
header_prefix = writer::get_header_prefix()
);

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 @@ -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<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 @@ -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(),
Expand Down Expand Up @@ -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)]
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_inputs/inheritance.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[cxx_qt::bridge]
#[cxx_qt::bridge(cxx_file_stem = "inheritance")]
mod inheritance {
extern "C++" {
include!("cxx-qt-lib/qmodelindex.h");
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_inputs/invokables.rs
Original file line number Diff line number Diff line change
@@ -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++" {
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_inputs/properties.rs
Original file line number Diff line number Diff line change
@@ -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++" {
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_inputs/qenum.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_inputs/shebang.rs
Original file line number Diff line number Diff line change
@@ -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]
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_inputs/signals.rs
Original file line number Diff line number Diff line change
@@ -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++" {
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/invokables.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "cxx-qt-gen/ffi.cxxqt.h"
#include "cxx-qt-gen/invokables.cxxqt.h"

namespace cxx_qt::my_object {
void
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/invokables.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ using MyObjectCxxQtThread = ::rust::cxxqt1::CxxQtThread<MyObject>;

} // 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
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/invokables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 "]
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/properties.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ using MyObjectCxxQtSignalHandlermyOnChanged =
::rust::cxxqt1::SignalHandler<struct MyObjectCxxQtSignalParamsmyOnChanged*>;
} // 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
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 "]
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/qenum.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "cxx-qt-gen/ffi.cxxqt.h"
#include "cxx-qt-gen/qenum.cxxqt.h"

namespace cxx_qt::my_object {
void
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/qenum.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/qenum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 "]
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/signals.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/signals.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ using QTimerCxxQtSignalHandlertimeout =
::rust::cxxqt1::SignalHandler<struct QTimerCxxQtSignalParamstimeout*>;
} // 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
Expand Down
2 changes: 1 addition & 1 deletion crates/cxx-qt-gen/test_outputs/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 "]
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 38f44c2

Please sign in to comment.