Closed yacineblr closed 3 years ago
Does the sqfenity_gen
builder always generate files for the mobx_codegen
builder? If so then we do support that via the runs_before
option in the builder configuration.
Otherwise generally the ordering of builders is "random" but consistent. You can split your project into targets in order to deal with this, but it is a pain to do :/. We can give you some help in that area if you need to do it though.
See also this section of the build config readme although it doesn't go into much depth https://github.com/dart-lang/build/blob/07c39cdd05e52c69538b8a7d9c24023caf5686ce/build_config/README.md#adjusting-builder-ordering
Thank you for your answer. Yes "sqfenity_gen" generates the classes to be used in the types for "mobx_codegen", but "mobx_codegen" is run first, it doesn't find the classes and type by "dynamic".
I tested :
builders:
property_sqfentity:
import: "package:sqfentity_gen/builder.dart"
builder_factories: ["sqfentityBuilder"]
build_extensions: {".dart": ["sqfentity.g.part"]}
runs_before:
- mobx_generator
and :
targets:
$default:
builders:
mobx_codegen:
options:
runs_before:
- sqfentity_gen
but it doesn't change anything.
Duplicate of #https://github.com/hhtokpinar/sqfEntity/issues/116
When you refer to a generator from another package the builder name needs to be prefixed with the package name.
Try:
builders:
property_sqfentity:
import: "package:sqfentity_gen/builder.dart"
builder_factories: ["sqfentityBuilder"]
build_extensions: {".dart": ["sqfentity.g.part"]}
runs_before:
- mobx_codegen:mobx_generator
Thanks a lot but that didn't solve the problem. mobx always launches before the other builder ("sqfEntity").
I have created a project if you want to test the problem.
Otherwise generally the ordering of builders is "random" but consistent.
Is it possible to make build_runner
get the ordering from the pubspec.yaml
? It must be really nice. For example,
dev_dependencies:
a_generator: any # this will run first
b_generator: any # and second
c_generator: any # and third
It can possibly collide with APIs like required_inputs
and runs_before
. But if those configurations aren't specified, build_runner
should use the order as per pubspec.yaml
.
Also, if I'm not mistaken, the dev_dependencies
is a map that can possibly have a problem storing the positions of the entries. Even if that's the case, at least it must be nice to have an API to configure the order (for example, as a List) whether in pubspec.yaml
or build.yaml
.
Yaml maps do not afaik guarantee ordering when we iterate the entries, although in practice today they are likely ordered. In any case though a decision was made early on to not use that ordering - the other things like runs_before
and required_inputs
are more stable ways and guarantee things work regardless of ordering in the pubspec.
It would be possible to add some other way of ordering builders explicitly, but we would have to make sure we didn't override the settings from runs_before
and required_inputs
as those are generally very hard constraints that the builder itself has defined. This ends up getting pretty complicated I think ultimately and the use cases we have seen so far are covered by the existing solutions.
Can you help us understand why you require an ordering that isn't expressed with required_inputs
and runs_before
?
I really want to avoid a situation where a builder author starts telling folks they need brand new config like this.
Well, I'm lost actually. Let me tell you about the whole situation. I have a builder that I want to run first because it generates a file that is required by another builder.
part 'env.g.dart';
// I need this ^ file to be generated first because I need to use the Env.api
// in an annotation for another builder
@Envify()
abstract class Env {
static const api = _Env.api;
}
This is another file,
part 'api.g.drt';
@RestApi(baseUrl: Env.api)
abstract class Api {}
But baseUrl
is always null
so I thought ordering is the problem here. But when I tried to inspect the build snapshot, the snapshot seems to be in the correct order actually.
// a chunk from .dart_tool/build/entrypoint/build.dart
final _builders = <_i1.BuilderApplication>[
_i1.apply('envify_generator:envifyBuilder', [_i2.envifyBuilder],
_i1.toDependentsOf('envify_generator'),
hideOutput: true, appliesBuilders: ['source_gen:combining_builder']),
_i1.apply('retrofit_generator:retrofit', [_i5.retrofitBuilder],
_i1.toDependentsOf('retrofit_generator'),
hideOutput: true, appliesBuilders: ['source_gen:combining_builder']),
];
envifyBuilder
also got run first when I try to inspect the build_runner
output with the --verbose
flag too. Then it might not be a problem with the ordering right?
Also, I can confirm that this is not a problem with the way the library implement to consume the annotation value, because I've tested with several other builders and none of them pick the value of Env.api
.
Are you sure you have computed the constants? I think the api is computeConstantValue()
instead of using the constantValue
getter?
Hmmm, I read the annotation's values from the ConstantReader
of source_gen, not from the metadata of the element. I think computeConstantValue
is only available in the analyzer. Do I have to read the annotation as the element's metadata to get it's computed value?
I also opened an issue in the source_gen repo, to check if the ConstantReader
is just not being able to read computed values.
Using the ConstantReader
from source_gen should be fine
Yea, but the value would still be null
. For example,
/// ... some code up here
/// ConstantReader annotation
annotation.read('field').literalValue;
// ^ would be null if the value of field comes from a part file
// every other cases are fine
// but, it's not null if I use a file import instead of part file
// the null case is only with part files
Are you on the latest build_resolvers
version? There was an issue like this previously which was resolved...
I do use the build_runner
version 1.10.4
which depends on the build_resolvers
version 1.4.3
. So yes, I guess.
Oh wait, are all the builders in this case SharedPartBuilder
s? None of the actual part files exist until the end if that is the case.
Can you try adding something like print(await buildStep.canRead(<asset-id-of-the-part-file>));
that would confirm whether or not the part file is visible.
Oh wait, are all the builders in this case
SharedPartBuilder
s? None of the actual part files exist until the end if that is the case.
Ah, that's a good call. In order to make this work the one that needs to write output which works from the resolver will likely need to change to write to a separate part of
file instead of using the .g.dart
suffix through the combining builder.
Oh wait, are all the builders in this case
SharedPartBuilder
s? None of the actual part files exist until the end if that is the case.
Yes, they all are using SharedPartBuilder
and combining_builder
. It might be the problem I guess.
the resolver will likely need to change to write to a separate
part of
file instead of using the.g.dart
suffix through the combining builder.
Does it mean the one that wants to get generated first can't use combining_builder
or does it have to have a different suffix other than .g.dart
?
Does it mean the one that wants to get generated first can't use
combining_builder
or does it have to have a different suffix other than.g.dart
?
Yes, it needs to generate its own file, with a different extension. Essentially you use the PartBuilder instead of the SharedPartBuilder. And then yes that builder does not need to apply the combining builder.
Okay, I see. Thanks. Then it must also be the culprit of the problem for this issue's OP since both mobx_codegen
and sqfentity_gen
use combining builder.
Ok, closing this issue then :)
So i had a similar issue with floor
and freezed
in my Flutter project. Where the floor_generator
runs before freezed
.
runs_before:
to my build.yaml as suggested by @natebosch but that didn't work.I added the line required_inputs: [".freezed.dart"]
to the package:floor_generator/build.yaml
file, under builders:
. This turned out well after running flutter pub run build_runner
. _Below is the package:floor_generator/build.yaml
after modifications._
targets:
$default:
builders:
floor_generator:
enabled: true
builders:
floor_generator:
import: "package:floor_generator/builder.dart"
# The builder function name, which gets called on build/watch
builder_factories: ["floorBuilder"]
# The 'partId' argument to 'SharedPartBuilder' is 'floor'
build_extensions: { ".dart": [".floor.g.part"] }
# Apply the Builder to the package with a direct dependency on the package exposing the builder
auto_apply: dependents
build_to: cache
required_inputs: [".freezed.dart"] ########### ADDED THIS LINE ############
# To copy the '.g.dart' content into '.g.dart' in the source tree
# Combine the output of multiple builders into one output (combining_builder)
applies_builders: ["source_gen|combining_builder"]
Tip: To use the modified floor_generator
in my CI builds, i had to fork the repository, make my change and push to a new ref.
pubspec.yaml
after modification....
dev_dependencies:
...
# Code Generators
build_runner: ^2.1.1
freezed: ^0.14.5
# floor_generator: ^1.2.0
floor_generator:
git:
url: git://github.com/Flutter-Fox/floor.git
ref: ft/require-freezed
path: floor_generator/
json_serializable: ^5.0.0
...
That's it! Hope this helps others having similar issues.
To expand on https://github.com/dart-lang/build/issues/2701#issuecomment-922857918, you don't have to fork and edit the package to which you want to add the required_inputs
line. What worked for me is using the build config from the package in my app's build.yaml
, adding required_inputs
and disabling the old builder
For example:
targets:
$default:
builders:
mockito:mockBuilder:
enabled: false
foo:fooMockBuilder:
enabled: true
builders:
fooMockBuilder:
import: "package:mockito/src/builder.dart"
required_inputs: [".firebase.g.dart"] ########### ADDED THIS LINE ############
builder_factories: ["buildMocks"]
build_extensions: { ".dart": [".mocks.dart"] }
build_to: source
auto_apply: dependents
_This example makes sure that the code generation by cloud_firestoreodm is completely finished before creating the mocks
Infact you can use runs_before
, with PartBuilder
. check this out : https://github.com/chaturadilan/riverpod_repo_generator
Seems , that _runsbefore stops working...
Seems , that _runsbefore stops working...
A recent change caused the order of builders which were not constrained by required_inputs
or runs_before
to change, but nothing has broken the ordering constraints when they are in place. Double check that the configuration is correct or if additional constraints need to be added.
runs_before
stopped working for me too. I double checked everything few times and still no luck. I suggest to reopen it.
runs_before
stopped working for me too.
Can you give more information? Do you have a reproduction case?
Yes, now it is having an issue here. https://github.com/chaturadilan/riverpod_repo_generator/blob/main/build.yaml
riverpod_repo does not execute before riverpod_generator here.
Hi, I use two build_runner ("mobx_codegen" and "sqfentity_gen") on a flutter application.
The files generated by "mobx_codegen" depend on the files generated by "sqfentity_gen", only I have the impression that the files are generated randomly.
How do I run the build_runner in a specific order?