Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Use package.links trick for Protobuf compilation #32

Merged

Conversation

slowli
Copy link
Contributor

@slowli slowli commented Nov 9, 2023

What ❔

Propagates Protobuf information via env variables by relying on package.links.

Why ❔

This simplifies Protobuf configuration and eliminate misconfiguration risks.

@slowli slowli marked this pull request as ready for review November 10, 2023 08:49

impl Descriptor {
/// Constructs a descriptor and adds it to the global pool.
pub fn new(_dependencies: &[&'static Self], descriptor_bytes: &[u8]) -> Self {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if unused, please remove

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having dependency refs allows ensuring via type system that these dependencies are added in the global pool. Would it be better to force dependencies to get initialized via Lazy::force(), or in some other way?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type system doesn't ensure any relation between the dependencies and the newly constructed descriptor, so this is as good as Lazy::force (or just dereferencing the lazy descriptors).

/// Validates this configuration.
fn validate(&self) -> anyhow::Result<()> {
/// Flag set to `true` if a public compilation target was encountered in a build script.
static HAS_PUBLIC_TARGET: AtomicBool = AtomicBool::new(false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be hard to lift this constraint?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theoretically, it can be lifted by changing the exported variable name (manifest rn) depending on the compilation target; but I didn't come up with a good way to ID compilation targets and passing these IDs to dependent crates. IMO, restricting a crate to at most one public target makes sense – it makes sure that all public generated code is in a single place. Do you have use cases for multiple public targets in mind?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example roles crate could have a separate protobuf targets for validator and node roles. I don't see any large benefits though, so it can wait.

@slowli
Copy link
Contributor Author

slowli commented Nov 10, 2023

I should've said from the start: I'm not entirely sure that this approach is better than the one implemented currently.

  • (+) It removes requirement to have Protobuf dependencies as build-time deps; this should improve compilation time.
  • (+) It also simplifies global descriptor pool management and marginally simplifies Protobuf compilation config.
  • (+)The error messages if package.links is forgotten or set to a wrong value should be helpful.
  • (-) OTOH, it requires that Protobuf dependencies are direct dependencies, and that they are not renamed. The latter requirement could be lifted with some effort; the former one is fundamental because of how package.links works.

Global descriptor pool management could theoretically be simplified even further by making Descriptors private. It would work by listing all deps (including transitive ones) when a descriptor is created; this is essentially the paths part to Manifest, which we build anyway (and which is topologically sorted by design). A couple of things that bother me about this approach:

  • Will the compiler / linker properly deduplicate include_bytes! of the same file?
  • Ideally, we'd want to not parse the same descriptor bytes into a descriptor multiple times, which would require keeping track of the loaded descriptors.

The current approach sidesteps both of these issues, and ensures topological sorting of descriptors via Rust type system, which IMO is quite cool.

@pompon0 pompon0 self-requested a review November 10, 2023 15:41
pompon0
pompon0 previously approved these changes Nov 10, 2023
brunoffranca
brunoffranca previously approved these changes Nov 10, 2023
@slowli slowli dismissed stale reviews from brunoffranca and pompon0 via f4b1e14 November 13, 2023 08:16
@slowli slowli requested a review from pompon0 November 13, 2023 08:30
@brunoffranca brunoffranca merged commit 95c1853 into main Nov 13, 2023
4 checks passed
@brunoffranca brunoffranca deleted the aov-bft-373-use-packagelinks-trick-for-protobuf-compilation branch November 13, 2023 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants