Skip to content

Conversation

WSH032
Copy link
Contributor

@WSH032 WSH032 commented Jun 2, 2025

Discussed at #13033 (comment)

This allows simulating the behavior of generate_context! at runtime and dynamically loading the Context.

@github-project-automation github-project-automation bot moved this to 📬Proposal in Roadmap Jun 2, 2025
@WSH032
Copy link
Contributor Author

WSH032 commented Jun 2, 2025

CC @Legend-Master.

In examples/precompiled, you can see that I only set the most basic tauri.conf.json at build time, and then dynamically set the identifier, provide frontend assets, etc. at runtime based on examples/precompiled/src-tauri.

Copy link
Contributor

github-actions bot commented Jun 2, 2025

Package Changes Through 8a56ea7

There are 8 changes which include tauri-bundler with minor, tauri with minor, tauri-cli with minor, tauri-codegen with minor, tauri-utils with minor, @tauri-apps/api with minor, @tauri-apps/cli with minor, tauri-runtime-wry with patch

Planned Package Versions

The following package releases are the planned based on the context of changes in this pull request.

package current next
@tauri-apps/api 2.5.0 2.6.0
tauri-utils 2.4.0 2.5.0
tauri-bundler 2.4.0 2.5.0
tauri-runtime 2.6.0 2.6.1
tauri-runtime-wry 2.6.0 2.6.1
tauri-codegen 2.2.0 2.3.0
tauri-macros 2.2.0 2.2.1
tauri-plugin 2.2.0 2.2.1
tauri-build 2.2.0 2.2.1
tauri 2.5.1 2.6.0
@tauri-apps/cli 2.5.0 2.6.0
tauri-cli 2.5.0 2.6.0

Add another change file through the GitHub UI by following this link.


Read about change files or the docs at github.com/jbolda/covector

@Legend-Master
Copy link
Contributor

So basically, this is duplicating the code from context_codegen in tauri-codegen to tauri so that it can be used at runtime, and they would be normal functions instead of ones that works with rust TokenStream right?

To be honest, this is just moving the responsibility of maintaining it from pytauri to tauri, and I don't think anyone on the team really wants to do it...

I don't know how feasible is it, but I think it might be better/easier to move out Context and its fields to a shared crate (maybe tauri-utils) and implement quote::ToTokens, then change the code inside tauri-codegen to 2 parts, one part generates the Context and another part quote! it to TokenStream that the macro could use, and then you can use the one generated from the first part directly

@WSH032
Copy link
Contributor Author

WSH032 commented Jun 2, 2025

To be honest, this is just moving the responsibility of maintaining it from pytauri to tauri, and I don't think anyone on the team really wants to do it...

I would argue that if Tauri wants to support bindings for other languages, it must provide a way to configure at runtime. Otherwise:

Each user has their own configuration → their own tauri.conf.json → needs to be converted into a runtime-usable Context by the Rust compiler (tauri-codegen) → every user needs the Rust compiler (even if they're using bindings for other languages) → users will complain, "If I need the Rust compiler anyway, why not just write Rust directly?" 🤔

Moreover, both Qt and CEF provide runtime configuration, allowing them to be compiled as dynamic libraries. If Tauri doesn't make changes, it can only be used as an executable.

@Legend-Master
Copy link
Contributor

I do really want to support using another language binding without the rust compiler, and that's why I suggested that we change the codegen to generate the Context instead just of rust source code, that way, you can just ship that code, and then generate the Context dynamically at runtime

@WSH032
Copy link
Contributor Author

WSH032 commented Jun 2, 2025

In fact, I think the context should only be used to control runtime behavior, and should not be used for embedding assets.

Ideally, we should split tauri.conf.json into two parts: one solely for controlling build-time behavior, and the other solely for controlling runtime behavior. This is why I said that build configuration should only be controlled by BuildConfig.

static embedded_assets:  {
    icon_bytes: &[u8],
    plugin_global_api_scripts: &[u8],
    // ...
} = generate_embedded_assets!();

let context: Context = serde::from_str(include_str!("tauri.runtime-conf.json"));

Builder::default()
    .embedded_assets(Some(embedded_assets))
    .runtime_context(context)

You should specify in the Context whether you want to use embedded assets or runtime assets.
The Builder should initialize the app by calling existing tauri api based on the provided Context (used only for configuration), rather than relying on macros to dynamically generate initialization rust code.

impl Builder {
    fn init(self) {
        if self.runtime_context.use_embedded_assets {
            app.set_icon(Image::from_bytes(embedded_assets.icon_bytes));
        } else {
            self.set_icon(Image::from_path(self.runtime_context.icon_path));
        }
    }
}

@Legend-Master
Copy link
Contributor

I like the idea of splitting them up so it's clear which one is used in build and which one is used at runtime

The Builder should initialize the app by calling existing tauri api based on the provided Context (used only for configuration), rather than relying on macros to dynamically generate initialization rust code.

The method that I suggested is just basically moving this to tauri-codegen, and let it produce the Context instead of just rust code, so if you want to generate the Context at runtime, you can

And if you would like to consume it not through tauri-codegen, but through tauri, we can gate that in a feature and re-export them, so we don't have so much duplicated code, we might also want to enable it in dev for faster compile speed by moving them to runtime

@Legend-Master
Copy link
Contributor

You should specify in the Context whether you want to use embedded assets or runtime assets.

I believe this is only for your currently implementation of pytauri, if we have the Context generation as a function (instead of a macro that generates the rust code), you can just do that in the runtime, and swap to use your own Assets implementation

For example, currently you do:

  1. Context generation at your library's build time
  2. Modify this context at runtime based on library consumer's configs

What we can do if that's a function:

  1. Ship the context generation code
  2. Generate this context at runtime based on library consumer's configs

And there's no need for

        if self.runtime_context.use_embedded_assets {
            app.set_icon(Image::from_bytes(embedded_assets.icon_bytes));
        } else {
            self.set_icon(Image::from_path(self.runtime_context.icon_path));
        }

@WSH032
Copy link
Contributor Author

WSH032 commented Jun 3, 2025

The method that I suggested is just basically moving this to tauri-codegen, and let it produce the Context instead of just rust code, so if you want to generate the Context at runtime, you can

What we can do if that's a function:

  1. Ship the context generation code
  2. Generate this context at runtime based on library consumer's configs

Sorry, I don't quite understand. Could you provide some pseudocode to describe how users/downstream consumers would use this new API?

@Legend-Master
Copy link
Contributor

So currently, we have

pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult<TokenStream> {

And we change it to pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult<Context> {}, and then you can use this function to generate the context directly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 📬Proposal

Development

Successfully merging this pull request may close these issues.

2 participants