Open randomPoison opened 5 years ago
One part of this might be to allow for code generation to happen as part of the build.rs
script. Right now, users have to manually execute a command in order to perform code generation, which means if they first open their project without doing so, they'll end up with a bunch of compiler errors. If code generation happened as part of the build script, it would ensure that users could always run cargo build
on their worker project without needing to remember any other manual steps.
For a local workflow, having the generated code in its own crate might be worth looking at.
This is a common pattern for C# workers where you have csproj
that is just generated code (and that on build you run codegen) and another which is your worker code that depends on the csproj
. This solves a few problems:
However it does incur some overhead -
How this translates into shipping schema with a crate, I'm not sure. Say a user publishes a crate with some game functionality "spatialos-overwatch-movement", it could have a dependency on "spatialos-overmatch-movement-gen-code" which contains the generated Rust code.
The obvious limitation is that you cannot reuse the schema defined in the crate. You could ship schema with the generated code crate. I.e. -
spatialos-overmatch-movement-gen-code
---
|- schema/
|- src/
|- Cargo.toml
But I'm not sure how a user could access this schema.
Giving it some more though, I think we should be able to distribute schema files via crates.io:
cargo metadata
command. There's also a cargo_metadata crate that makes it easier to access that data programmatically. We can use this information to search the dependencies tree for additional schema files to include in schema compilation.So, in your example, the user could ship a spatialos-overwatch-schema
crate, or they could even just bundle the schemas and the worker code into the spatialos-overwatch-movement
crate. I'm not sure what's the best practice there, and I think there are additional questions to be answered about distributing entire workers via crates.io, though I think it should be possible from a technical perspective.
Spatial.toml
file so that downstream crates can find the generated code for a given crate.Another thing to consider: How do we allow for custom code generation (e.g. for GDKs to have custom code generation) if code generation is baked into each crate that provides schemas? In the current version where code generation is centralized in the final consumer's crate, it's much easier to swap out the code generator implementation.
It might be possible to do some magic with environment variables and build parameters to have the root crate inject codegen information into its dependencies, but would that be a good idea? It seems a bit icky to modify the code in a dependency based on who's consuming it. On the other hand, that's exactly what feature flags do (albeit in a more controlled way).
Downstream crates changing how upstream crates compile is its own potentially hairy thing to deal with, but it at least sounds like a viable direction for investigation!
The current method for code generation involves generating the binding code for all schema-defined types in a single Rust source file. While this approach is fairly simple, it has the major drawback of making it difficult (or impossible) to distribute schema files and schema-generated code as part of a crate. For example, the SDK can't provide any useful method or trait implementations for the
improbable::Position
component, since the component effectively doesn't exist until the end-user generates it.An alternative approach would be for each crate to distribute the generated code associated with any schema types it defines. This would allow the crate to also provide useful inherent/trait impls for such types. The SDK would distribute the standard schema library.
Unanswered Questions