Dart-code: Automatically run build_runner when opening a Dart or Flutter project

Created on 19 Sep 2018  路  30Comments  路  Source: Dart-Code/Dart-Code

For the time being, we have to run pub run build_runner watch (or flutter packages pub run build_runner watch for Flutter) each time we are working on a project with code generation.

It would be great if this command could be launched automatically if there was a dev dependency to build_runner in the pubspec.yaml file.
This feature should be enabled with a setting, in order to let people decide if want to activate it or not.

What do you think about this?

in tasks is enhancement

Most helpful comment

I've got something basic working here that contributes build_runner tasks for projects that reference build_runner in the pubspec. It'd be good to get some testing of it if anyone would like to give it a try.

Grab this file, unzip it (I can't attach vsix files here!), then run Extensions: Install from VSIX from the VS Code command palette and browse to it, then reload. (Note: you'll automatically be upgraded to v2.20 stable when I publish it, so this functionality may vanish then, depending on whether this work gets merged into it - which depends on testing/feedback!)

dart-code-2.20.0-beta.1.with-build-runner.vsix.zip

Then set the dart.previewBuildRunnerTasks setting to true in your VS Code settings.

With this done, if you run the Run Task command from the VS Code command palette, you should see some build_runner tasks (note: this requires that your project is a workspace root in VS Code, it won't work for projects in sub-folders):

screen shot 2018-10-23 at 3 03 18 pm

If you have multiple roots that match, the workspace folder names will appear alongside the task names.

If you run watch (for ex.) then it'll run the task and show Building... in the status bar. Once the initial build finishes, the Building... should vanish. When you trigger a rebuild (eg. by editing a file), you should see Building... reappear in the status bar for the duration of the build. You can click the little spanner/screwdriver icon in the status bar to jump to the command output.

If you want this to run automatically, you can add this as a preLaunchTask in launch.json (in future maybe this will be automatic, but for now it's opt-in):

{
    "name": "Dart",
    "program": "lib/main.dart",
    "request": "launch",
    "type": "dart",
    "preLaunchTask": "pub: build_runner watch"
}

With this set, when you hit F5 to try and run the project, it'll first run build_runner watch. Once it sees the build has completed, it'll launch the app. build_runner will continue to run in the background, and on subsequent presses of F5 it'll wait for any in-progress builds and then launch.

It should(!) run the correct command (Flutter vs Pub) based on your project type automatically, so this should be testable with either.

Note: It's not currently possible to customise the command (such as adding args), please 馃憤 this issue to support this.

Please try it out if you can, and post feedback!

All 30 comments

This would be great, but we'd need a reliable way when opening a project to know whether to run something (and what). I don't know enough to know if things are stable/standard enough to do this right now.

That said, you can get some of the way there with VS Code tasks (for ex. see https://github.com/Dart-Code/Dart-Code/issues/68#issuecomment-379337028).

@natebosch @jakemac53 are things standard enough that an editor could automatically run things on project open (if not - is it a planned goal?) or would we likely always rely on the user configuring them in something like VS Code tasks (I'm not sure how much the commands people run may vary across each projects).

We haven't made a decision to lock down the CLI arguments so I can't guarantee perfect stability - but something like pub run build_runner watch is very likely to stick around. If we do change that it will definitely be indicated with a breaking major version bump, so if you'd like to be cautious (and are willing to do an update whenever we release new versions) you could lock down support by checking the version of build_runner dep.

We're definitely very careful about changes to the major CLI arguments like build, watch, serve. I would not rely on the exact names or usage of some of the more experimental flags like --live-reload.

@natebosch Cool - I'm not too concerned about breaks (we could ship as opt-in behind a flag for a while) and more about logically whether the same command (eg. pub run build_runner watch) is general enough that we can just run it for everyone automatically without them explicitly starting a task. Sounds like probably it is.

That said, is there a reliable method to know whether to do this? It doesn't make sense to run for projects not using this - I could review the pubspec/.packages to see if the build_runner package is referenced, but is this a good enough indicator?

That said, is there a reliable method to know whether to do this?

You can check the pubspec.yaml for a build_runner dependency, which is a good indication. However, I don't know how you would know whether to run watch or serve, and also when the user runs pub get it is likely that the process will kill itself and need to be restarted.

In general, I am actually more in favor of the user explicitly starting/stopping this task, and even explicitly configuring it.

I don't know how you would know whether to run watch or serve

Ah, good point :(

I am actually more in favor of the user explicitly starting/stopping this task, and even explicitly configuring it.

Ok, I wonder if we should maybe just make it easier for the user to configure the tasks. Am I right in thinking serve is generally for web apps, and watch for other apps (cli, Flutter, whatever)? I'm thinking maybe watch makes sense as a task (eg. if you hit Ctrl+Shift+B for Build it should be run as a build task and then live in the background, and you just run your app with F5 as normal) whereas serve would more likely be pressing F5 for a web app, which would run serve and spawn a browser - and when you click Stop on the debug toolbar, it'd be reasonable to terminate serve (unlike watch that would always be a background task).

Does that sound sane?

That sounds reasonable to me yes - for instance the intellij integration does basically the same thing for web apps. If you tell it to launch something that it understands as a web app (not sure how it decides) then it runs webdev serve and launches a browser.

On my setup I can't run the default command, I need to call
flutter pub pub run build_runner watch

Can you differentiate that you need to call default or flutter dart sdk

@Solido Do you just mean switching between flutter and pub, or is that pub pub deliberate? We should definitely use the flutter version for Flutter projects.

I think this is best implemented as a task provider:

https://code.visualstudio.com/docs/extensions/example-tasks

That way when the user hits Build/Cmd+Shift+B we'll provide a list of tasks (build, watch, etc. - based on what we find in the files). Auto-starting them is probably best handled by VS Code (see https://github.com/Microsoft/vscode/issues/17147) though if that never progresses maybe we can add a setting somewhere.

Ah, I see - it was flutter packages pub I was expecting. But in any case, whatever we do, it should work well for Flutter projects too, it shouldn't be Dart VM only.

I've got something basic working here that contributes build_runner tasks for projects that reference build_runner in the pubspec. It'd be good to get some testing of it if anyone would like to give it a try.

Grab this file, unzip it (I can't attach vsix files here!), then run Extensions: Install from VSIX from the VS Code command palette and browse to it, then reload. (Note: you'll automatically be upgraded to v2.20 stable when I publish it, so this functionality may vanish then, depending on whether this work gets merged into it - which depends on testing/feedback!)

dart-code-2.20.0-beta.1.with-build-runner.vsix.zip

Then set the dart.previewBuildRunnerTasks setting to true in your VS Code settings.

With this done, if you run the Run Task command from the VS Code command palette, you should see some build_runner tasks (note: this requires that your project is a workspace root in VS Code, it won't work for projects in sub-folders):

screen shot 2018-10-23 at 3 03 18 pm

If you have multiple roots that match, the workspace folder names will appear alongside the task names.

If you run watch (for ex.) then it'll run the task and show Building... in the status bar. Once the initial build finishes, the Building... should vanish. When you trigger a rebuild (eg. by editing a file), you should see Building... reappear in the status bar for the duration of the build. You can click the little spanner/screwdriver icon in the status bar to jump to the command output.

If you want this to run automatically, you can add this as a preLaunchTask in launch.json (in future maybe this will be automatic, but for now it's opt-in):

{
    "name": "Dart",
    "program": "lib/main.dart",
    "request": "launch",
    "type": "dart",
    "preLaunchTask": "pub: build_runner watch"
}

With this set, when you hit F5 to try and run the project, it'll first run build_runner watch. Once it sees the build has completed, it'll launch the app. build_runner will continue to run in the background, and on subsequent presses of F5 it'll wait for any in-progress builds and then launch.

It should(!) run the correct command (Flutter vs Pub) based on your project type automatically, so this should be testable with either.

Note: It's not currently possible to customise the command (such as adding args), please 馃憤 this issue to support this.

Please try it out if you can, and post feedback!

I'm shipping the above functionality (still behind the preview flag) in v2.20. There's an updated beta at https://github.com/Dart-Code/Dart-Code/releases/tag/v2.20.0-beta.2 and release notes at https://dartcode.org/releases/v2-20/#preview-build_runner-tasks

I'm going to consider this issue "done" since I think running at startup (as opposed to just in a preLaunchTask) is something better done by VS Code (or an extension) - see https://github.com/Microsoft/vscode/issues/17147. @letsar let me know if you don't think having it as a preLaunchTask solves the issue for you (I've opened https://github.com/Dart-Code/Dart-Code/issues/1283 about allowing you to enable this globally so you don't need to create launch.jsons).

Please try it out and file bugs for any issues you find.

@DanTup is there a place I can add/hardcode --delete-conflicting-outputs ?

Not currently. We'd need to get it injected into the args in createBuildRunnerCommandBackgroundTask.

Probably we could just add a setting (like dart.vmAdditionalArgs) that would unconditionally be appended. Please open a new issue and I'll take a look soon :-)

@HerrNiklasRaab I got an email notification but looks like you deleted your comment - did you get it sorted? :)

@DanTup Yes, at least sort of.

I wanted to start the watch task as soon as I open VS Code. So I did the following:

  1. STRG + SHIFT + P
  2. Typed: "Tasks Configure Task" ENTER
  3. Selected, the Task I wanted to configure
  4. Modified generated task.json to the following (only added "runOptions"):

image

Now there is a warning:

Incorrect type. Expected "object".

And when I restart Visual Studio I get an error notification and following output:

Error: The pub task detection didn't contribute a task for the following configuration:
{
"type": "pub",
"command": "watch",
"problemMatcher": [
"dart-pub-build_runner"
],
"runOptions": {
"runOn": "folderOpen"
}
}
The task will be ignored.

Similar to this one:
https://github.com/dart-lang/build/issues/1025#issuecomment-435993458

Any idea?

Edited:

  • The same error occurs, when I run the task directly, via command palette.
  • When I delete the task.json file, and run the task vie command palette, everything seems ok.

@HerrNiklasRaab I just did some testing, and it seems like you need to prefix the problemMatcher name with a dollar. The tooltip says you can use strings, but it seems like what it really means is strings that have variables that will be replaced.

{
    "type": "pub",
    "command": "serve",
    "problemMatcher": [
        "$dart-pub-build_runner"
    ],
    "runOptions": {
        "runOn": "folderOpen"
    }
}

I'll fix the definition that's creating it without.

@DanTup Thanks, for the response. But I still get the error, after VS Code startup:

Error: The pub task detection didn't contribute a task for the following configuration:
{
    "type": "pub",
    "command": "watch",
    "problemMatcher": [
        **"$dart-pub-build_runner"**
    ],
    "runOptions": {
        "runOn": "folderOpen"
    }
}
The task will be ignored.

This behavior, disappeared after, adding the "$":

The same error occurs, when I run the task directly, via command palette.

But on the startup, something doesn't seem to work.

Oops, sorry - I was looking at the Incorrect type. Expected "object". issue.

Have you enabled the dart.previewBuildRunnerTasks setting?

Have you enabled the dart.previewBuildRunnerTasks setting?

Yes

@HerrNiklasRaab Would you mind opening an issue about this, and if you're able to attach a folder that repros for you, I can be sure I'm testing with the same thing. Thanks!

Hey @DanTup,

just got the February 2019 VS Code update, and now we the error is gone.

Now the watch task starts automatically on startup, but for every project with build_runner(which are 7 at the moment), I now have to explicitly confirm that i want to delete existing outputs:

[INFO] Generating build script completed, took 674ms
[INFO] Setting up file watchers completed, took 30ms
[INFO] Waiting for all file watchers to be ready completed, took 36ms
[INFO] Building new asset graph completed, took 1.1s
[INFO] Found 1 declared outputs which already exist on disk. This is likely because the.dart_tool/build folder was deleted, or you are submitting generated files to your source repository.
Delete these files?
1 - Delete
2 - Cancel build
3 - List conflicts

Because of this, I just wanted to point out how important a setting like:--delete-conflicting-outputs would be.

But besides this, thanks a lot for your help.

Niklas

@HerrNiklasRaab See https://github.com/Dart-Code/Dart-Code/issues/1415 :)

For anyone who stumbles here through Google. This is now documented: https://dartcode.org/docs/tasks/

Actually, it's not clear what the current state is. This was clearly added as a preview feature and then the preview flag removed. But the "build_runner" tasks don't show up for me in VSC for some reason. 馃し

@eseidel do you have references to build_runner in your pubspec? There's a fairly crude regex check for it in pubspec to enable these tasks:

https://github.com/Dart-Code/Dart-Code/blob/0bc3dec6cba33c600c21bd1351083cf0d90d944f/src/extension/sdk/utils.ts#L399-L405

Task not showing for me either. Dart code version v3.20.1. build_runner is referenced in pubspec. Am I missing something?

@pavlin-filkov do you see any tasks in the Dart or Flutter sections? (note: the build_runner tasks will show up in either the Dart or Flutter sections depending on the projects found in your workspace). If you're seeing pub get and pub upgrade in either but not build_runner, that suggests the regex above is failing. If you're not seeing pub get or pub upgrade in either of them, it seems like something else is going wrong (although I don't have any ideas yet).

Ah, my bad, was looking in the wrong place...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rgb1380 picture rgb1380  路  3Comments

CaferPoyrazoglu picture CaferPoyrazoglu  路  4Comments

DanTup picture DanTup  路  4Comments

ifredom picture ifredom  路  3Comments

mccadi picture mccadi  路  3Comments