Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Simon Binder
    @simolus3

    Ah, I see. It sounds like your builder essentially operates on each file independently, right? In that case, I would probably ditch the aggregate builder in favor of a regular builder - take .dirk.html as input and .dirk.dart as output. To only run on files in /lib/views by default, you don't need a build option with globs. Instead, you can configure this when you define your builder:

    builders:
      dirk_code_builder:
        build_extensions: {'.dirk.html': '.dirk.dart'}
        # ...
        defaults:
          generate_for: ['lib/views/**']

    Users can override generate_for if they want to. And in general, a single build step is the smallest unit of invalidation in the build system. So if you want to process more than one file, doing that in multiple build steps enables fast and incremental rebuilds. If you have a single build step where you do everything by matching a glob, you'd have to re-process every file on every edit. With those simple extensions, your builder gets a new build step for each file.
    The builder definition from above has the problem that generated code goes to lib/views as well (not in lib/views/code). Allowing directory moves in builders is not well supported at the moment (dart-lang/build#1689 ), so I think it might be reasonable to just generate the files in lib/views as well. You could implement directory moves with a combination of three builders:

    1. An invisible (build_to: cache) builder from .dirk.html to .dirk.dart. Users would never see the generated files in lib/views since this is only for intermediate results
    2. An aggregate builder (build_extensions: {'lib/$lib$': ['views.tar']}, build_to: cache) that writes all the generated files into a tar file
    3. A post-process builder that extracts the tar file into lib/views/code/.

    In addition to being complicated, this approach has downsides as well (other builders couldn't read the final .dirk.dart files for instance). Each regular (non post-processing) builders may only have a fixed amount of outputs per primary input, and they must be relative to the input file. This might sound very limiting, but it's exactly what enables build_runner to do fast and incremental rebuilds. So everything that prevents fast units of work tends to be a little bit more complicated :)

    Denis Bakhtin
    @tabula-rasa
    Awesome, thank you for guidance, really appreciate that. Yes, I process each file independently. Will try that options without directory moves and see how it goes)
    bekoswe
    @bek0swe
    hello guys i'm new on flutter&dart . I'm getting this error when i'm trying to put build_runner , freeze packages into pubspec_yaml : Because freezed >=0.13.0-nullsafety.0 depends on build ^1.6.0 and build_runner >=1.12.0 depends on build >=2.0.0 <2.1.0, freezed >=0.13.0-nullsafety.0 is incompatible with build_runner >=1.12.0.
    can someone help?
    Jacob MacDonald
    @jakemac53
    You should file an issue on freezed to update to build version 2.0.0. In the meantime lower your build_runner requirement to something like ^1.11.0.
    bekoswe
    @bek0swe
    @jakemac53 thank u a lot
    Matias Meno
    @enyo
    When I build my project with webdev or build_runner all dart files and sourcemaps are copied to the build directory as well. How can I avoid that from happening? I don't want to expose the source code
    I already provide the --production flag
    Simon Binder
    @simolus3
    @enyo I also ran into similar issues with build directories, sometimes there were even missing some assets... I ended up using this. It works, but it feels very hacky. You could adapt _shouldSkipNode to manually exclude nodes that were generated and don't end in .dart.js.
    Jacob MacDonald
    @jakemac53
    The --release flag should be cleaning up any Dart files and source maps, if you are using build_web_compilers. Please file an issue if it isn't.
    Caio Granero
    @caiogranero

    Hi everyone, i have a question. I'm using json_serializable and firestore. json_serializable creates a factory method with Map<String, dynamic> as parameter but after nullsafety changes, firestore start to return a Map<String, dynamic>? as document data and now i can't call json_serializable factory to map my firestore types. can someone help me with this?

    I wrote this example:

    class Entity {
      const Entity({required this.id});
    
      final String id;
    
      factory Entity.fromJson(Map<String, dynamic> json) => _$EntityFromJson(json);
      Map<String, dynamic> toJson() => _$EntityToJson(this);
    }
    
    class Repository {
      Stream<List<Entity>> list() {
        return FirebaseFirestore.instance.collection('entity').snapshots().map((event) {
          return event.docs.map((e) {
            return Entity.fromJson(
              e.data() // The argument type 'Map<String, dynamic>?' can't be assigned to the parameter type 'Map<String, dynamic>'
            );
          }).toList();
        });
      }
    }
    Emilio Dalla Torre
    @emiliodallatorre

    Hi everyone,
    I noticed that - after json_serializable 4.0 update - I cannot use it to generate JSON for my project anymore (needless to say, my project is not null-safe).

    As the main option (downgrading json_serializable) is not available for me (I have other packages conflicts that needs me to keep latest version), I'm currently trying to make json_serializable >= 4.0 work on an unsafe nullable environment.

    Should I raise an issue on GitHub?
    Do someone has any ideas?

    Caio Granero
    @caiogranero
    @emiliodallatorre Your problem sound like mine, i figure out that i need to check if Firestore response is not null before mapping with json_serializable so i think you could try to check this and make all methods nullable.
    Emilio Dalla Torre
    @emiliodallatorre

    Hi @caiogranero. Unfortunately, this is not the problem... I forgot to say that I cannot even generate my .g.dart files as I cannot use json_serializable >=4.0 in a nullable environment.

    Your problem can easily be solved by regenerating your files with latest json_serializable: if you, for instance, declare a string like final String uid;, then json_serializable will act as if it's surely not null on Firebase and will throw an error otherwise.
    If you make that string nullable, json_serializable will generate a nullable deserializer and let the string null if it's null on Firebase.

    Jacob MacDonald
    @jakemac53

    @caiogranero You can either assert the map you got is non-null:

    e.data()!

    or provide a default map:

    e.data() ?? const {}
    or otherwise handle the null map in some other way
    Nick Meinhold
    @nickmeinhold
    Hi! I’m new to package:build and trying write an openapi client generator which generates Dart from markdown, then uses that generated Dart in the next step in combination with a json file to generate a Dart client for that API. My problem is that I can’t seem to get the second builder to wait for the first builder to finish so the output Dart is available. I’ve read the docs and tried various combinations of runs_beforeand applies_builders but nothing seems to work… any suggestions? Thanks!
    This is my build.yaml, I’m trying to make clientBuilder only run when schemaBuilder is done:
    targets:
      openapi_client_builder:
        builders:
          openapi_client_builder:schemaBuilder:
            enabled: true
          openapi_client_builder:clientBuilder:
            enabled: true
    
    builders:
      schemaBuilder:
        import: package:openapi_client_builder/openapi_schema_builder.dart
        builder_factories: [ schemaBuilder ]
        build_extensions:
          input/openapi_spec.md: [ output/schema_classes.dart ]
        build_to: source
        auto_apply: root_package
        runs_before: [ openapi_client_builder:clientBuilder ]
      clientBuilder:
        import: package:openapi_client_builder/openapi_client_builder.dart
        builder_factories: [ clientBuilder ]
        build_extensions:
          input/app-store-connect-openapi.json: [ output/client.dart ]
        build_to: source
        auto_apply: root_package
    Nick Meinhold
    @nickmeinhold
    Actually thinking about it more, I guess I’m trying to do something weird here in wanting Dart code generated in a build step to be part of the running program in a later step… I hadn’t thought it through properly sorry... so I guess I would need to have separate packages, one dependent on the other, and run build_runner separately on each in this case? Thanks!
    Simon Binder
    @simolus3

    wanting Dart code generated in a build step to be part of the running program in a later step

    Yup, that doesn't work. The build script is compiled ahead of time, so builders can't generate themselves :D The runs_before option only reflects that assets generated by schemaBuilder can be read by clientBuilder.

    so I guess I would need to have separate packages, one dependent on the other, and run build_runner separately on each in this case

    That would be a solution, but really I would try to avoid a situation where you need to run build_runner in a specific order for each change. That will be very annoying in practice. Maybe you can rewrite your builders in such a way that none depends on generated code? I could envision a build setup like this:

    1. Have a build_to: cache builder transforming the markdown into a json structure that your builders can pick up
    2. Make the schemaBuilder take that json as input and use that to write the schema classes
    3. Let the clientBuilder take the two jsons to figure out the right client code without importing it itself.
    Nick Meinhold
    @nickmeinhold
    Awesome thanks for that @simolus3! And thanks for taking the time to explain an alternate strategy - I will see if I can rewrite the builders in such a way that none depends on generated code, as you suggest. Thanks again!
    sunbreak
    @sunbreak:matrix.org
    [m]
    I'm trying to add argments to protoc_plugin according to dart-lang/protobuf#497
    I've found the useGrpc flag, but not found others. Could anyone shed some light?
    https://github.com/dart-lang/protobuf/blob/85716c47db6743293cd95983f83a345f1b7210aa/protoc_plugin/lib/file_generator.dart#L250-L256
        if (options.useGrpc) {
          if (grpcGenerators.isNotEmpty) {
            files.add(makeFile(".pbgrpc.dart", generateGrpcFile(config)));
          }
        } else {
          files.add(makeFile(".pbserver.dart", generateServerFile(config)));
        }
    Hannes Winkler
    @ardera
    Hey everyone!
    I'm currently trying to make source_gen work on top of some libc bindings generated by ffigen.
    I have multiple binding files generated for multiple architectures, each defining a set of classes, global variables, enums, typedefs, etc (with different binding files sometimes defining different types for the same name). Right now I want to use source_gen to analyze these generated binding files and build a single "frontend" dart file that automatically selects the correct binding according to the current platform.
    Is it possible with source_gen, I can somehow "view" multiple LibraryReaders at once while generating? Right now it seems I can only generate a single dart file from a single input dart file / library. If that doesn't work, does someone know a workaround?
    Simon Binder
    @simolus3
    @ardera To use multiple library readers in a single build step, just use new LibraryReader(await buildStep.resolver.libraryFor(yourAssetId)). You might have to change your build configuration as well, so that your builder only runs on one input file as a primary input.
    Hannes Winkler
    @ardera
    ah right, thanks!
    Alexey Knyazev
    @lexaknyazev

    Hi!
    Is it possible to have two targets in build.yaml that use the same builder but with different options on different inputs?

    My config looks like:

    targets:
      $default:
        builders:
          build_web_compilers|entrypoint:
            generate_for:
              - web/t1/main.dart
            options:
              compiler: dart2js
              dart2js_args:
                - -DDEF=t1
      web2:
        builders:
          build_web_compilers|entrypoint:
            generate_for:
              - web/t2/main.dart
            options:
              compiler: dart2js
              dart2js_args:
                - -DDEF=t2

    Running dart run build_runner build --release results in

    [SEVERE] Conflicting outputs
    Both build_modules:module_library and build_modules:module_library may output lib/foo.module.library. Potential outputs must be unique across all builders. See https://github.com/dart-lang/build/blob/master/docs/faq.md#why-do-build
    ers-need-unique-outputs

    Thanks!

    Simon Binder
    @simolus3
    I think this should be possible, yes. The problem is that, by defining two targets, you're implicitly applying all default builders twice. build_runner does not like that, since each output needs to have a well-defined target. I'd probably define three targets: One default target that just disables the entrypoint builder and then the two targets you have, except that they should only apply the entrypoint:
    targets:
      $default:
        builders:
          build_web_compilers|entrypoint:
            enabled: false
      web1:
        auto_apply_builders: false
        dependencies: ['$default']
        builders:
          build_web_compilers|entrypoint:
            enabled: true
            generate_for:
              - web/t1/main.dart
            options: # ...
      web2:
        auto_apply_builders: false
        dependencies: ['$default']
        builders:
          build_web_compilers|entrypoint:
            enabled: true
            generate_for:
              - web/t2/main.dart
            options: # ...
    Alexey Knyazev
    @lexaknyazev
    @simolus3 Thanks! That seems to work. What does dependencies: ['$default'] mean here given that the default target has no enabled builders?
    Simon Binder
    @simolus3
    It ensures a correct ordering. It might appear like the default target doesn't enable any builders, but that's not true. Builders can be auto-applied to packages (and almost all builders are). So e.g. the builders from build_modules, which are doing some preparation work for compilation, would be applied to the default target only. The web1/web2 targets then use the the generated module information from the default target, which is why they need to depend on it. If you have any codegen builders like json_serializable or built_value, those would also run in the default target.
    Alexey Knyazev
    @lexaknyazev
    Thanks for the explanation. Would it be possible to configure codegen builders by explicitly adding them to the default target in this configuration?
    Simon Binder
    @simolus3
    Yes exactly, you can configure them just like you'd configure the entrypoint builder in the web targets. You just don't need the enabled: true since the builder would probably be enabled by default :)
    Evan Weible
    @ekweible
    Hello! I'd like to write an aggregate builder with a dynamic number of outputs, but I'm not sure if that's possible. From the docs, it seems that if you use the $package$ synthetic input, you have to explicitly define the full output path of each output. For context, the use case I'm looking at is a builder that would write an aggregate test file for each set of test/**_test.dart files that share a common HTML file. The number of distinct test HTML files would vary per project, so I don't think the outputs can be fully defined statically in the builder definition.
    Jacob MacDonald
    @jakemac53
    Right, you can't do this with a single builder, but you may be able to do it with multiple builders. The build_modules package has a similar thing it wants to do (it groups a bunch of dart files into a single module).
    It does this by creating an aggregate builder that analyzes all the files in the package and determines the outputs it should create. For each group of inputs it chooses (hermetically) a "primary" input to represent that module. Then another normal builder is defined which has as its primary input extension all dart files (just .dart). It reads this meta file when visiting each dart file to see if that dart file is the "primary" of a larger module, if not it just returns and outputs nothing. If so then it creates the module.
    That is a bit simplified, but hopefully it helps
    Evan Weible
    @ekweible
    Yup that makes sense, thanks! Since that will be a bit more involved, I suppose I should ask before going down that path.. My goal is to speed up the build step when running a lot of browser tests in release mode, since dart2js treats each test as a full program and can't share compilation work like DDC. Does this seem like a reasonable approach, or am I maybe missing a simpler alternative?
    Jacob MacDonald
    @jakemac53
    So your goal is to compile a single bigger test but still keep the underlying test files smaller basically?
    That seems reasonable to me yes
    It actually seems like maybe the 2nd builder should have .html as its primary input, if you are creating one of these for each html file effectively.
    Evan Weible
    @ekweible
    Yeah, exactly. And yeah I was thinking the same thing with the .html being the input :thumbsup:
    Jacob MacDonald
    @jakemac53
    You could possibly just do a single builder that way as well, you can glob for files from any builder (you might end up duplicating some work though this way)