You may have encountered a problem with build_runner before. Looking at it from the side the library is very useful. However, it has one fundamental flaw that bugs me, and it’s succinctly called: flutter pub run build_runner build –delete-conflicting-outputs.
Some of you probably use the fvm library, which allows you to manage Flutter versions. You may have also encountered a problem when using the intl plugin in Android Studio. With lower versions of Flutter we can get errors while generating text files. The best solution to this is to generate them manually with command flutter –no-color pub global run intl_utils:generate.
I’m sure many of you forgot these commands at the beginning of your career. Surely many of you already have them added as system aliases. Today I will try to present you an option which I prefer and which solves these and other problems when we have to leave IDE to console.
Note
On windows devices, Dart libraries that add custom commands execute twice (As of October 2021), this is due to the order in which the Path variable is loaded on the system, for more information see, among others, this issue – [BUG] fvm runs commands twice on [Windows] – Issue #227 – leoafarias/fvm.
Grinder
Grinder is a powerful tool that allows you to write your own commands, or rather aliases for dart subroutines. It works so simple that you just add the command in your code with the appropriate annotation and you’re done!
1
2@Task('build model')
3void build() {
4 try {
5 log('building...');
6
7 run(
8 'fvm flutter pub run build_runner build --delete-conflicting-outputs --no-fail-on-severe --verbose > build_log.txt',
9 quiet: isQuiet(),
10 runOptions: RunOptions(runInShell: true),
11 );
12 } catch (error) {
13 handleError(error);
14 }
15}
// command for build_runner
This allows us to shorten this monstrously long command to a simple grind build. We can even add additional functions like logging to file.
This solution works perfectly in conjunction with already described by me Mason (link to the article about Mason). It allows us to move our programs to new projects without remembering about them. You can also try to combine both solutions and create a system that does even more work for us!
Back to the point of the article, however, Grinder is not without a few drawbacks that I’m still struggling with at this point. First of all, as you can see, I use the handleError method, which handles errors. This is directly related to a problem I encountered when handling this command. When running build_runner command I’m getting an error on Windows with code -1073741819. The query is executing correctly, but returns an error, so I set error handling to ignore this one error as a hotfix.
1void handleError(final dynamic error) {
2 if (error is ProcessException && error.exitCode == -1073741819) {
3 // do nothing no idea why this happens only with build_runner
4 } else {
5 throw error;
6 }
7}
Another bug is problems running the same script on both macOS and Windows. This sometimes requires extra work.
Why do I recommend using Grinder?
Probably many of you would ask me this simple question at this point – why?
Arguments for:
Grinder is not for everyone – many people prefer to describe their own scripts and aliases in the default tools. However, there are several advantages to using Grinder over regular scripts.
First of all, if you’re working in a larger team, it’s very beneficial to have a solution that you know 100% will work the same for everyone (ignoring the previously mentioned problems on macOS and Windows, which are rather disposable for installations). Once we go through a basic installation of the tool, we are confident that our script will work the same for every person in the team.
I’m currently working on a project that uses bash scripts to retrieve texts from an external server and build a class that gives simple access to them in code. This solution works well. However, it has one drawback – installing it takes time. It requires several additional libraries that need to be installed separately for each worker. Not counting that, it requires maintaining two versions of the same code for different systems (again, Windows and macOS, just assuming that someone, like me, prefers Windows).
It is easy to see that here we would have a very large gain by using Grinder. The libraries are managed in the project by our pubspec.yaml. So each person will have exactly the libraries we need (unless they don’t run the pub get but that’s unlikely to happen). Additionally, it allows us to write in our favorite Dart language without having to deal with other languages. It gives us the freedom to edit our commands and doesn’t require the less proficient in bash to search the internet for knowledge for every simplest change.
Arguments against:
Grinder certainly sounds good at first glance, but even leaving aside the implementation problems it may still be a second-rate tool for some.
First, people who work alone or in a small development team probably won’t gain that much difference from system scripts. Much of the previous argument focuses on bringing commands to a common platform. If you don’t have one, this is unlikely to be a priority.
A second argument against, might be the fact that Grinder is not a native tool. It runs in the console and allows you to invoke system commands. However, it will not have the freedom that we gain when working with native resources.
A half argument could be that you have to define Grinder for each project separately. This can cause changes between projects that need to be resolved. Part of the problem of portability between projects is improved for us by Mason, for example, which does an excellent job of normalizing the overhead we gain by expanding our tool pool.
The last argument I see is implementation. As I mentioned earlier, my work with the tool has not been without problems. Grinder needs work to stabilize it. Probably it is less work than installing dependencies for native scripts, but at this point, for me, this library looks more like a cool feature, than a full fledged tool.
Conclusion
Grinder is a tool that inspired me. Personally I will try to continue using it. Previously, I used the no longer supported Derry library for adding aliases in pubspec.yaml, but Grinder quickly took its place and fit in without a problem. I recommend it to people who work in different environments, because despite the first problems I trust that it can replace most of the incomprehensible for most scripts.