fzyzcjy / flutter_rust_bridge

Flutter/Dart <-> Rust binding generator, feature-rich, but seamless and simple.
https://fzyzcjy.github.io/flutter_rust_bridge/
MIT License
4.28k stars 300 forks source link

Using frb with main executable #2292

Closed anlumo closed 2 weeks ago

anlumo commented 2 months ago

Is your feature request related to a problem? Please describe.

I want to use flutter_rust_bridge with a project that uses the Flutter embedder API. The Rust code to be called by Dart is located in the executable directly, rather than a dynamic library.

Describe the solution you'd like

I'm using ExternalLibrary.process(iKnowHowToUseIt: true) right now. Ideally, this is all that's needed, but unfortunately it's not. The problem is that while building the executable, the linker strips out all of the symbols that are looked up dynamically by frb via DynamicLibrary.lookup, like frb_get_rust_content_hash.

Describe alternatives you've considered

I've been able to make this work on Linux by adding the file .cargo/config.toml with the following content:

[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "link-arg=-Wl,--export-dynamic"]

This stops the linker from stripping any unused symbols.

However, it also stops it from stripping everything else in the binary, making it unnecessarily large (and more vulnerable to reverse engineering, which might be a problem). In addition, this approach doesn't work on Windows, because there the linker expects an explicit symbol name to include. ld also supports supplying an explicit list of symbols to include, which would fix this problem.

Now the problem is that the list of symbols seems to be an implementation detail. It seems to be generated based on some C header files in frb_dart_source_code.rs.

Summary

I think this basically boils down to the following request: Please add a command or flag (on generate) to flutter_rust_bridge_codegen to export a list of symbols that are required to be used in the final binary (text file, one symbol per line). This list could then be picked up by my build system to be passed to the linker.

fzyzcjy commented 2 months ago

export a list of symbols that are required to be used in the final binary

frb can be configured to generate C code (indeed a .h file). Is that what you need? For example, you can parse that header file (either via llvm helper or via regex) and know all symbols

anlumo commented 2 months ago

I just tried generating that header file using the -c flag, but it doesn't contain frb_get_rust_content_hash, so that can't be it?

fzyzcjy commented 2 months ago

For those, please refer to https://github.com/fzyzcjy/flutter_rust_bridge/tree/master/frb_dart/lib/src/ffigen_generated/intermediate. They are not generated during frb codegen phase, but pre-generated.

anlumo commented 2 months ago

Well, that's why I'm asking for a command to dump that list. It would remove the need to generate and parse C code, download the pre-generated header files from the github repo, etc.

fzyzcjy commented 2 months ago

Another thought: Do all symbols prefix with frb_? (It should be; if you find anything that is not, feel free to ping me and we should fix it). If so, maybe we can firstly check list all symbols in your binary, and then simply filter with that prefix.

anlumo commented 2 months ago

The ones in the generated header file mostly start with frbgen_, but there's also store_dart_post_cobject and there are a few dart_ functions like dart_opaque_rust2dart_decode that are also looked up.

fzyzcjy commented 2 months ago
anlumo commented 1 month ago

Would it be possible to funnel all symbol lookups through a custom Rust function instead of dart:ffi's lookup, which then is generated in frb_generated.rs to handle all symbols needed?

That would make the list of symbols that have to be exported static (at least per version), which would greatly simplify things.

fzyzcjy commented 1 month ago

Are you using full_dep: true or false? The latter enables SSE codec by default and thus less generated symbols.

As for whether it can be static: A large part may not be hard; but e.g. the native finalizers of the rust opaque objects may needs some work. Anyway, if everything has the same prefix, then it is just a line of grep and we can get every symbol.

anlumo commented 1 month ago

I’ve turned that off.

A simple grep on symbols is easy on Linux, but my code also has to run on Windows, and there’s it’s much more complicated.

fzyzcjy commented 1 month ago

but my code also has to run on Windows, and there’s it’s much more complicated.

Do you mean there is no grep or Windows symbols are different? For the former, I guess you can write several lines of Dart/Python/etc scripts to extract the symbols.

anlumo commented 3 weeks ago

Ok, so I tried generating the C header as the first step, but this doesn't work in the first place, making that approach not useful.

I think I should create new tickets for the stuff I ran into there.

anlumo commented 3 weeks ago

Besides #2368, the other issue I have is just a cyclical type (ticket here), which shouldn't matter for this.

github-actions[bot] commented 1 day ago

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new issue.