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

Guidance on how to create our own Builder #745

Open
Hinageshi opened this issue Mar 27, 2025 · 1 comment
Open

Guidance on how to create our own Builder #745

Hinageshi opened this issue Mar 27, 2025 · 1 comment

Comments

@Hinageshi
Copy link

Hi, I am writing this seeking for help, since it's quite complicated to find resources on the best way to create Builders 🙂

For our project, we created our own Builder for a specific task. From an input file containing annotated elements, we'd like to obtain a .rpc.dart generated file. Then, we want to apply the retrofit builder on this generated file, to obtain the output, a generated file with .g.dart extension.

For this, we created rpc_generator using source_gen. The build.yaml file looks like this:

builders:
  rpc_generator:
    import: "package:rpc_generator/rpc_generator.dart"
    builder_factories: ["rpcBuilder"]
    build_extensions: { ".dart": [".rpc.dart"] }
    auto_apply: dependents
    build_to: source
    runs_before: ["retrofit_generator"]
    applies_builders: ["retrofit_generator"]

rpc_generator.dart contains the following:
Builder rpcBuilder(BuilderOptions options) => generatorFactoryBuilder(options);

And finally, the builder and generator themselves:

Builder generatorFactoryBuilder(BuilderOptions _) {
  return PartBuilder(
    [const RpcGenerator()],
    '.rpc.dart',
    header: '''
    // coverage:ignore-file
    // GENERATED CODE - DO NOT MODIFY BY HAND
        ''',
  );
}

class RpcGenerator extends Generator {
  const RpcGenerator();

  @override
  Future<String> generate(LibraryReader library, BuildStep buildStep) async {
     ...
  }
}

In local, we have this build.yaml file to call our Builder on our files:

global_options:
  freezed:
    runs_before:
      - json_serializable
  json_serializable:
    runs_before:
      - retrofit_generator
      - rpc_generator

targets:
  $default:
    builders:
      ...
      rpc_generator:rpcBuilder:
        generate_for:
          - lib/api/rpc/*.api.dart;
          - lib/api/*.api.dart

My questions are the following:

  1. We used a PartBuilder because we have to keep both outputs from our Builder and retrofit builder. But is it possible to do better for this task? Like have a SharedPartBuilder that first generate a .g.dart containing our generated code, then run retrofit builder on this generated code and combine both outputs in a single .g.dart file ?
  2. When launching dart run build_runner build --delete-conflicting-outputs in local, a warning appears: Warning: Configuring `rpc_generator:rpcBuilder` in target `data:data` but this is not a known Builder. Yet, our files are generating correctly. However, when our CI launches the same command through GitHub Actions, the files are not generated. I do not understand why this warning is triggered and why the build_runner behavior changes from local to remote ?
  3. In our local build.yaml file, we HAVE to call the builder like this: rpc_generator:rpcBuilder:, otherwise the files are not generated if we only put rpc_generator:. From what I understood, if the builder has the same name as its package, we should be able to call rpc_generator: directly without having to specify the builder factory. Do you have an idea why this is happening?

Thanks in advance for your help 🙂 I can provide more details if needed.

@Hinageshi Hinageshi changed the title Guidance on how creating our own Builder Guidance on how to create our own Builder Mar 27, 2025
@jakemac53
Copy link
Contributor

  1. We used a PartBuilder because we have to keep both outputs from our Builder and retrofit builder. But is it possible to do better for this task? Like have a SharedPartBuilder that first generate a .g.dart containing our generated code, then run retrofit builder on this generated code and combine both outputs in a single .g.dart file ?

If the retrofit builder needs to analyze)the output of your builder, then they must output to different files. So it sounds to me like you are doing this correctly.

It is a bit more annoying for users to have to list the separate files, but you can only share outputs if you don't need to see the outputs of the other builders (files cannot change once emitted).

2. When launching dart run build_runner build --delete-conflicting-outputs in local, a warning appears: Warning: Configuring `rpc_generator:rpcBuilder` in target `data:data` but this is not a known Builder. Yet, our files are generating correctly. However, when our CI launches the same command through GitHub Actions, the files are not generated. I do not understand why this warning is triggered and why the build_runner behavior changes from local to remote ?

The name you defined is rpc_generator not rpcBuilder (its the top level key in the builders map, not the name of the builder factory).

You should just be able to do rpc_generator as the name, assuming that is also the package name. This configuration you have is not being respected if you see that message - but the rpc_generator has auto_apply: dependents set so it is being applied automatically anyways - its just not respecting your configuration since its using the wrong name.

I can't answer why it wouldn't work on GitHub actions without more information - there is likely something misconfigured in the action (working dir, etc).

In our local build.yaml file, we HAVE to call the builder like this: rpc_generator:rpcBuilder:, otherwise the files are not generated if we only put rpc_generator:. From what I understood, if the builder has the same name as its package, we should be able to call rpc_generator: directly without having to specify the builder factory. Do you have an idea why this is happening?

That doesn't make sense, something else is going on. The correct name based on the config above is either rpc_generator or rpc_generator:rpc_generator.

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

No branches or pull requests

2 participants