KDAB / cxx-qt

Safe interop between Rust and Qt
https://kdab.github.io/cxx-qt/book/
964 stars 66 forks source link

Add an "internals" section to the book #983

Open LeonMatthesKDAB opened 2 weeks ago

LeonMatthesKDAB commented 2 weeks ago

This section should explain some of our internal architecture decisions so that we can remember them and contributors can understand them more easily

LeonMatthesKDAB commented 1 week ago

I just had another idea on how to organize the build.

We had the additional problem that if you depend on a crate that is build with cxx-qt-build (e..g cxx-qt-lib), you need to make sure that crate is built before your own one.

To ensure this is actually the case, it needs to be added to the [build-dependencies]. We were planning to make sure though that our users don't forget this step by adding some kind of token that they need to provide to cxx-qt-build.

Now, what if that token was just the manifest? That way we would avoid having to write a manifest.json, which would pull in serde and serde_json as a dependency. cxx-qt-build could simply generate a Rust function that can be included by the library which returns the appropriate struct.

So it would work like this:

  1. The build script of e.g. cxx-qt-lib would automatically dump out a function into the OUT_DIR with the signature:

    fn cxxqt_build_manifest() -> cxx_qt::BuildManifest
  2. The user then needs to export this from their library (we will want to simplify this with a macro, e.g.:)

    // In cxx-qt-lib lib.rs
    cxx_qt::include_build_manifest! {};
  3. When depending on cxx-qt-lib, you add it to both the dependencies and build-dependencies and then add the opts from cxx-qt-build:

    // build.rs in your crate
    CxxQtBuilder::new()
        // ...
        .with_dependency(cxx_qt_lib::cxx_qt_build_manifest())
        .build();

This way we would completely avoid the need to serialize and deserialize the manifest and force our users to include everything in the right order.

@ahayzen-kdab what do you think?

I already discussed this with @vimpostor this morning, and he pointed out that the downside would be more code added to the library, but that should hopefully be optimized out, as it is only used in the build script, not in the final binary.

ahayzen-kdab commented 1 week ago

@LeonMatthesKDAB Sounds good, how do you make the options set in the build.rs exposed to the function that is returning the struct? Is this all done automatically by cxx-qt-build ?

Eg if i add extra defines in the build.rs to the cxx-qt-build, does that write them somewhere in the out_dir ? Then somehow include_build_manifest includes those during the build and exposes the defines back in the method ? As this is before where we needed both a lib and headers crate.

LeonMatthesKDAB commented 1 week ago

Yes, all that data can go into the generated function. The manifest can automatically include certain options (like the modules).

Out of that data, we generate a manifest.rs file and dump it in the OUT_DIR.

include_build_manifest can then expand to:

include!(concat!(env!("OUT_DIR"), "/cxx_qt_build/manifest.rs"));

which would include the Rust code inside the library itself.