dev_build package helpers
package:dev_build reads pubspec.yaml, analysis_options.yaml and
.dart_tool/package_config.json as plain maps, walks folder trees to find
packages, edits versions and dependencies in place, and wraps dart pub global. All of it is for VM scripts (tool/*.dart, bin/*.dart, tests).
import 'package:dev_build/build_support.dart';
Future<void> main() async {
var pubspec = await pathGetPubspecYamlMap('.');
print(pubspecYamlGetPackageName(pubspec)); // my_package
print(pubspecYamlGetVersion(pubspec)); // 1.2.3 (pub_semver Version)
print(pubspecYamlSupportsFlutter(pubspec)); // false
}
Guidelines
Imports
package:dev_build/build_support.dart: pubspec/analysis_options/
package_config readers (pathGet*, pubspecYaml*,
packageConfigGetPackages, pathGetResolvedPackagePath), package root
lookups (isPubPackageRoot, isPubPackageRootSync, getPubPackageRoot,
getPubPackageRootSync), VersionBoundaries, pubspec editing
(pathPubspecAddDependency, pathPubspecRemoveDependency,
pathPubspecGetDependencyLines), project creation (dartCreateProject,
flutterCreateProject), checkAndActivatePackage,
checkAndActivateWebdev, checkOrPubActivateDevBuild,
isFlutterSupportedSync, isNodeSupportedSync, nodeSetupCheck.
package:dev_build/package.dart: re-exports package:pub_semver
(Version), DartPackageReader, DartPackageIo, recursivePubPath,
iteratePubPath, IteratePubPathOptions, recursivePackagesRun,
FilterDartProjectOptions, PubGlobalPackage*,
PubGlobalPackageService, checkOrPubActivateHostedPackage, plus the
CI entry points (packageRunCi, see the dev-build-run-ci skill).
package:dev_build/shell.dart is package:process_run/shell.dart:
Shell, run, which/whichSync, dartVersion, dartExecutable,
ShellException, shellArgument, ShellEnvironment, prompt.
package:dev_build/menu/menu_run_ci.dart exports PubIoPackage and
PubIoPackageOptions (a package with pub get/upgrade/downgrade,
format, dependency listing).
Reading pubspec.yaml
await pathGetPubspecYamlMap(dir) returns Map<String, Object?>; pass it
to the pubspecYaml* functions instead of re-reading. Same for
pathGetAnalysisOptionsYamlMap(dir). They throw if the file is missing.
pubspecYamlGetVersion(map) throws when version: is absent (workspace
root, application); use pubspecYamlGetVersionOrNull(map) when unsure.
pubspecYamlGetSdkBoundaries(map) returns VersionBoundaries? from
environment: sdk:. VersionBoundaries.parse('>=3.0.0 <4.0.0'),
.parse('^3.2.0'), .matches(dartVersion), .min/.max
(VersionBoundary with value and include), toShortString(),
toMinMaxString(), toYamlString().
- Dependency checks:
pubspecYamlHasAnyDependencies(map, ['test']) looks
in dependencies, dev_dependencies and dependency_overrides. Prefix
a name with direct:, dev: or override: to restrict the section.
pubspecYamlGetDependenciesMap(map, kind: PubDependencyKind.dev) and
pubspecYamlGetDependenciesPackageName(map, kind: ...) list a section
(direct is the default kind).
- Flags:
pubspecYamlSupportsFlutter (depends on flutter),
pubspecYamlSupportsWeb (build_web_compilers),
pubspecYamlSupportsNode (build_node_compilers),
pubspecYamlSupportsTest (test), pubspecYamlIsWorkspaceRoot
(workspace: key), pubspecYamlHasWorkspaceResolution
(resolution: workspace).
DartPackageReader.pubspecString(content) /
DartPackageReader.pubspecYaml(map) wrap a map with getVersion() and
getDependencyObject(dependency: 'path') (returns {'path': <spec>} or
null). Use it for in-memory or test content.
Locating packages
await isPubPackageRoot(dir) is true when dir/pubspec.yaml exists and
its sdk constraint matches the running Dart. Pass
filterDartProjectOptions: FilterDartProjectOptions(ignoreSdkConstraints: true) (or minSdk/maxSdk) to change the filter. isPubPackageRootSync
only checks the file.
await getPubPackageRoot(anyPathInside) walks up to the nearest package
root and throws if none is found (getPubPackageRootSync likewise).
await recursivePubPath(['.']) lists every package folder under the
given folders, including the folders themselves, sorted and without
duplicates. Hidden folders, build, deploy, node_modules are not
visited; links are followed. dependencies: ['direct:sembast'] keeps
only packages depending on it; readConfig: true also matches
transitive dependencies through package_config.json.
iteratePubPath(['.'], onPubPath: (path) => true, options: IteratePubPathOptions(recursive:, dependencies:, readConfig:, filterDartProjectOptions:)) scans lazily; return false from the
handler to stop early.
Resolved dependencies
await pathGetPackageConfigMap(dir) reads the package config after
pub get (workspace resolution handled); packageConfigGetPackages(map)
lists package names; await pathGetResolvedPackagePath(dir, 'sembast')
returns the absolute folder of a dependency or null. These throw
UnsupportedError('dart pub get is needed') before a pub get.
PubIoPackage(dir): await package.ready then isFlutter,
isWorkspace, dofPub (dart pub or flutter pub), pubGet(),
pubUpgrade(), pubDowngrade() (all with offline:), format(),
checkFormat() (throws when a file is not formatted),
getResolvedDependencies(), getResolvedPackagePath(name),
dumpDeps(), getWorkspaceRootPath(), versionOrNull.
Editing a package
DartPackageIo(dir): await package.ready, package.getVersion(),
package.setVersion(Version(1, 0, 1)) (returns true if changed),
await package.write(). await package.writeVersion(version) does the
three steps and returns true if the file changed. Only the version:
line is rewritten, the rest of the file is preserved.
await pathPubspecAddDependency(dir, 'sembast', dependencyLines: ['path: ../sembast']) inserts under dependencies: when absent (true
when added); pathPubspecRemoveDependency(dir, name) removes it;
pathPubspecGetDependencyLines(dir, name) returns the lines or null.
Text based: it does not reorder or reformat the file.
DartPackageIo(dir).compiledExe(script: 'bin/main.dart', minVersion: Version(1, 2, 0)) runs dart compile exe into
build/<linux|macos|windows>/<name> when missing or when
<exe> --version is older than minVersion, and returns
DartPackageIoCompiledExe(path, version).
dartCreateProject(path: 'out/app', template: dartTemplateConsole) and
flutterCreateProject(path:, template: flutterTemplateApp, platforms:)
wrap dart create / flutter create (templates: dartTemplateConsole,
dartTemplatePackage, dartTemplateWeb, flutterTemplateApp,
flutterTemplatePackage).
pub global packages
await checkOrPubActivateHostedPackage('webdev', versionBoundaries: VersionBoundaries.parse('^3.0.0')) activates a hosted package when it is
missing or its activated version is out of the boundaries.
checkOrPubActivateDevBuild() does it for dev_build itself.
PubGlobalPackageService(): getActivatedPackage(name) parses
dart pub global list into a PubGlobalHostedPackage,
PubGlobalGitPackage or PubGlobalPathPackage (name, version,
source); activateGlobalPackage(PubGlobalGitPackageInstall(name, gitUrl:, gitPath:, gitRef:)) / PubGlobalPathPackageInstall(name, path:) / PubGlobalHostedPackageInstall(name, versionBoundaries:);
deactivateGlobalPackage(name). Both accept dryRun: and verbose:.
checkAndActivatePackage('webdev') is the older helper (activate if
not listed, no version check); checkAndActivateWebdev() also upgrades
an old webdev.
Platform
- Everything here needs
dart:io. pathGetPubspecYamlMap,
pathGetPackageConfigMap, pathGetAnalysisOptionsYamlMap and
pathGetResolvedPackagePath compile on the web but throw
UnsupportedError('... io only') there.
Examples
Print information about the packages of a repository
import 'package:dev_build/build_support.dart';
import 'package:dev_build/package.dart';
import 'package:path/path.dart';
Future<void> main() async {
for (var dir in await recursivePubPath(['.'])) {
var pubspec = await pathGetPubspecYamlMap(dir);
var name = pubspecYamlGetPackageName(pubspec);
var version = pubspecYamlGetVersionOrNull(pubspec);
var sdk = pubspecYamlGetSdkBoundaries(pubspec);
var flutter = pubspecYamlSupportsFlutter(pubspec) ? ' (flutter)' : '';
print('${normalize(absolute(dir))}: $name $version sdk: $sdk$flutter');
}
}
Bump the patch version of a package
import 'package:dev_build/package.dart';
Future<void> bumpPatch(String dir) async {
var package = DartPackageIo(dir);
await package.ready;
var version = package.getVersion();
var next = Version(version.major, version.minor, version.patch + 1);
if (await package.writeVersion(next)) {
print('$dir: $version -> $next');
}
}
Packages depending on a given package, transitively
import 'package:dev_build/package.dart';
Future<List<String>> usersOf(String package, {String root = '.'}) =>
recursivePubPath([root], dependencies: [package], readConfig: true);
Stop at the first Flutter package found
import 'package:dev_build/build_support.dart';
import 'package:dev_build/package.dart';
Future<String?> firstFlutterPackage(String root) async {
String? found;
await iteratePubPath(
[root],
onPubPath: (dir) async {
var pubspec = await pathGetPubspecYamlMap(dir);
if (pubspecYamlSupportsFlutter(pubspec)) {
found = dir;
return false; // stop
}
return true;
},
);
return found;
}
Where is a dependency installed?
import 'package:dev_build/build_support.dart';
Future<void> main() async {
// Requires a previous `dart pub get`
var path = await pathGetResolvedPackagePath('.', 'path');
print(path); // /home/me/.pub-cache/hosted/pub.dev/path-1.9.1
}
Add a path dependency and run pub get
import 'package:dev_build/build_support.dart';
import 'package:dev_build/menu/menu_run_ci.dart' show PubIoPackage;
Future<void> main() async {
var dir = 'packages/app';
var added = await pathPubspecAddDependency(
dir,
'my_lib',
dependencyLines: ['path: ../my_lib'],
);
if (added) {
var package = PubIoPackage(dir);
await package.ready;
await package.pubGet();
}
}
Make sure a global tool is installed before using it
import 'package:dev_build/package.dart';
import 'package:dev_build/shell.dart';
Future<void> main() async {
await checkOrPubActivateHostedPackage(
'webdev',
versionBoundaries: VersionBoundaries.parse('>=3.0.0 <4.0.0'),
);
await run('dart pub global run webdev --version');
}
Compile a package binary once and reuse it
import 'package:dev_build/package.dart';
import 'package:dev_build/shell.dart';
Future<void> main() async {
var exe = await DartPackageIo('.').compiledExe(
script: 'bin/main.dart',
minVersion: Version(1, 0, 0),
);
await run('${shellArgument(exe.path)} --help');
}
Version boundaries
import 'package:dev_build/build_support.dart';
import 'package:dev_build/shell.dart' show dartVersion;
void main() {
var boundaries = VersionBoundaries.parse('^3.2.0');
print(boundaries.toMinMaxString()); // >=3.2.0 <4.0.0
print(boundaries.matches(dartVersion)); // true on Dart 3.x >= 3.2
print(VersionBoundaries.parse('>=1.0.0 <2.0.0').toShortString()); // ^1.0.0
}
Common mistakes
- Importing
package:dev_build/package.dart for pubspecYamlGetPackageName
or pathGetPubspecYamlMap: they are in build_support.dart.
- Calling
pubspecYamlGetVersion on a workspace root or an app without
version:: it throws, use pubspecYamlGetVersionOrNull.
- Reading
package_config.json helpers before pub get: they throw.
- Using
DartPackageIo without awaiting ready first.
- Expecting
recursivePubPath to return packages whose sdk constraint does
not match the running Dart: pass FilterDartProjectOptions( ignoreSdkConstraints: true) to list them.
1---2name: dev-build-package3description: Use when a Dart script needs to read or edit pubspec.yaml, find packages in a folder tree, resolve dependency paths, bump versions, or manage pub global packages with package:dev_build: pathGetPubspecYamlMap, pubspecYamlGetPackageName, pubspecYamlGetVersion, pubspecYamlSupportsFlutter, pubspecYamlHasAnyDependencies, VersionBoundaries, isPubPackageRoot, getPubPackageRoot, recursivePubPath, iteratePubPath, DartPackageIo, DartPackageReader, PubIoPackage, pathGetResolvedPackagePath, pathPubspecAddDependency, compiledExe, PubGlobalPackageService, checkOrPubActivateHostedPackage, checkAndActivatePackage, and the package:dev_build/shell.dart re-export of process_run.4---56# dev_build package helpers78`package:dev_build` reads `pubspec.yaml`, `analysis_options.yaml` and9`.dart_tool/package_config.json` as plain maps, walks folder trees to find10packages, edits versions and dependencies in place, and wraps `dart pub11global`. All of it is for VM scripts (`tool/*.dart`, `bin/*.dart`, tests).1213```dart14import 'package:dev_build/build_support.dart';1516Future<void> main() async {17 var pubspec = await pathGetPubspecYamlMap('.');18 print(pubspecYamlGetPackageName(pubspec)); // my_package19 print(pubspecYamlGetVersion(pubspec)); // 1.2.3 (pub_semver Version)20 print(pubspecYamlSupportsFlutter(pubspec)); // false21}22```2324## Guidelines2526### Imports2728* `package:dev_build/build_support.dart`: pubspec/analysis_options/29 package_config readers (`pathGet*`, `pubspecYaml*`,30 `packageConfigGetPackages`, `pathGetResolvedPackagePath`), package root31 lookups (`isPubPackageRoot`, `isPubPackageRootSync`, `getPubPackageRoot`,32 `getPubPackageRootSync`), `VersionBoundaries`, pubspec editing33 (`pathPubspecAddDependency`, `pathPubspecRemoveDependency`,34 `pathPubspecGetDependencyLines`), project creation (`dartCreateProject`,35 `flutterCreateProject`), `checkAndActivatePackage`,36 `checkAndActivateWebdev`, `checkOrPubActivateDevBuild`,37 `isFlutterSupportedSync`, `isNodeSupportedSync`, `nodeSetupCheck`.38* `package:dev_build/package.dart`: re-exports `package:pub_semver`39 (`Version`), `DartPackageReader`, `DartPackageIo`, `recursivePubPath`,40 `iteratePubPath`, `IteratePubPathOptions`, `recursivePackagesRun`,41 `FilterDartProjectOptions`, `PubGlobalPackage*`,42 `PubGlobalPackageService`, `checkOrPubActivateHostedPackage`, plus the43 CI entry points (`packageRunCi`, see the `dev-build-run-ci` skill).44* `package:dev_build/shell.dart` is `package:process_run/shell.dart`:45 `Shell`, `run`, `which`/`whichSync`, `dartVersion`, `dartExecutable`,46 `ShellException`, `shellArgument`, `ShellEnvironment`, `prompt`.47* `package:dev_build/menu/menu_run_ci.dart` exports `PubIoPackage` and48 `PubIoPackageOptions` (a package with `pub get`/`upgrade`/`downgrade`,49 format, dependency listing).5051### Reading pubspec.yaml5253* `await pathGetPubspecYamlMap(dir)` returns `Map<String, Object?>`; pass it54 to the `pubspecYaml*` functions instead of re-reading. Same for55 `pathGetAnalysisOptionsYamlMap(dir)`. They throw if the file is missing.56* `pubspecYamlGetVersion(map)` throws when `version:` is absent (workspace57 root, application); use `pubspecYamlGetVersionOrNull(map)` when unsure.58* `pubspecYamlGetSdkBoundaries(map)` returns `VersionBoundaries?` from59 `environment: sdk:`. `VersionBoundaries.parse('>=3.0.0 <4.0.0')`,60 `.parse('^3.2.0')`, `.matches(dartVersion)`, `.min`/`.max`61 (`VersionBoundary` with `value` and `include`), `toShortString()`,62 `toMinMaxString()`, `toYamlString()`.63* Dependency checks: `pubspecYamlHasAnyDependencies(map, ['test'])` looks64 in `dependencies`, `dev_dependencies` and `dependency_overrides`. Prefix65 a name with `direct:`, `dev:` or `override:` to restrict the section.66 `pubspecYamlGetDependenciesMap(map, kind: PubDependencyKind.dev)` and67 `pubspecYamlGetDependenciesPackageName(map, kind: ...)` list a section68 (`direct` is the default kind).69* Flags: `pubspecYamlSupportsFlutter` (depends on `flutter`),70 `pubspecYamlSupportsWeb` (`build_web_compilers`),71 `pubspecYamlSupportsNode` (`build_node_compilers`),72 `pubspecYamlSupportsTest` (`test`), `pubspecYamlIsWorkspaceRoot`73 (`workspace:` key), `pubspecYamlHasWorkspaceResolution`74 (`resolution: workspace`).75* `DartPackageReader.pubspecString(content)` /76 `DartPackageReader.pubspecYaml(map)` wrap a map with `getVersion()` and77 `getDependencyObject(dependency: 'path')` (returns `{'path': <spec>}` or78 null). Use it for in-memory or test content.7980### Locating packages8182* `await isPubPackageRoot(dir)` is true when `dir/pubspec.yaml` exists and83 its `sdk` constraint matches the running Dart. Pass84 `filterDartProjectOptions: FilterDartProjectOptions(ignoreSdkConstraints:85 true)` (or `minSdk`/`maxSdk`) to change the filter. `isPubPackageRootSync`86 only checks the file.87* `await getPubPackageRoot(anyPathInside)` walks up to the nearest package88 root and throws if none is found (`getPubPackageRootSync` likewise).89* `await recursivePubPath(['.'])` lists every package folder under the90 given folders, including the folders themselves, sorted and without91 duplicates. Hidden folders, `build`, `deploy`, `node_modules` are not92 visited; links are followed. `dependencies: ['direct:sembast']` keeps93 only packages depending on it; `readConfig: true` also matches94 transitive dependencies through `package_config.json`.95* `iteratePubPath(['.'], onPubPath: (path) => true, options:96 IteratePubPathOptions(recursive:, dependencies:, readConfig:,97 filterDartProjectOptions:))` scans lazily; return `false` from the98 handler to stop early.99100### Resolved dependencies101102* `await pathGetPackageConfigMap(dir)` reads the package config after103 `pub get` (workspace resolution handled); `packageConfigGetPackages(map)`104 lists package names; `await pathGetResolvedPackagePath(dir, 'sembast')`105 returns the absolute folder of a dependency or null. These throw106 `UnsupportedError('dart pub get is needed')` before a `pub get`.107* `PubIoPackage(dir)`: `await package.ready` then `isFlutter`,108 `isWorkspace`, `dofPub` (`dart pub` or `flutter pub`), `pubGet()`,109 `pubUpgrade()`, `pubDowngrade()` (all with `offline:`), `format()`,110 `checkFormat()` (throws when a file is not formatted),111 `getResolvedDependencies()`, `getResolvedPackagePath(name)`,112 `dumpDeps()`, `getWorkspaceRootPath()`, `versionOrNull`.113114### Editing a package115116* `DartPackageIo(dir)`: `await package.ready`, `package.getVersion()`,117 `package.setVersion(Version(1, 0, 1))` (returns true if changed),118 `await package.write()`. `await package.writeVersion(version)` does the119 three steps and returns true if the file changed. Only the `version:`120 line is rewritten, the rest of the file is preserved.121* `await pathPubspecAddDependency(dir, 'sembast', dependencyLines:122 ['path: ../sembast'])` inserts under `dependencies:` when absent (true123 when added); `pathPubspecRemoveDependency(dir, name)` removes it;124 `pathPubspecGetDependencyLines(dir, name)` returns the lines or null.125 Text based: it does not reorder or reformat the file.126* `DartPackageIo(dir).compiledExe(script: 'bin/main.dart', minVersion:127 Version(1, 2, 0))` runs `dart compile exe` into128 `build/<linux|macos|windows>/<name>` when missing or when129 `<exe> --version` is older than `minVersion`, and returns130 `DartPackageIoCompiledExe(path, version)`.131* `dartCreateProject(path: 'out/app', template: dartTemplateConsole)` and132 `flutterCreateProject(path:, template: flutterTemplateApp, platforms:)`133 wrap `dart create` / `flutter create` (templates: `dartTemplateConsole`,134 `dartTemplatePackage`, `dartTemplateWeb`, `flutterTemplateApp`,135 `flutterTemplatePackage`).136137### pub global packages138139* `await checkOrPubActivateHostedPackage('webdev', versionBoundaries:140 VersionBoundaries.parse('^3.0.0'))` activates a hosted package when it is141 missing or its activated version is out of the boundaries.142 `checkOrPubActivateDevBuild()` does it for `dev_build` itself.143* `PubGlobalPackageService()`: `getActivatedPackage(name)` parses144 `dart pub global list` into a `PubGlobalHostedPackage`,145 `PubGlobalGitPackage` or `PubGlobalPathPackage` (`name`, `version`,146 `source`); `activateGlobalPackage(PubGlobalGitPackageInstall(name,147 gitUrl:, gitPath:, gitRef:))` / `PubGlobalPathPackageInstall(name,148 path:)` / `PubGlobalHostedPackageInstall(name, versionBoundaries:)`;149 `deactivateGlobalPackage(name)`. Both accept `dryRun:` and `verbose:`.150* `checkAndActivatePackage('webdev')` is the older helper (activate if151 not listed, no version check); `checkAndActivateWebdev()` also upgrades152 an old webdev.153154### Platform155156* Everything here needs `dart:io`. `pathGetPubspecYamlMap`,157 `pathGetPackageConfigMap`, `pathGetAnalysisOptionsYamlMap` and158 `pathGetResolvedPackagePath` compile on the web but throw159 `UnsupportedError('... io only')` there.160161## Examples162163### Print information about the packages of a repository164165```dart166import 'package:dev_build/build_support.dart';167import 'package:dev_build/package.dart';168import 'package:path/path.dart';169170Future<void> main() async {171 for (var dir in await recursivePubPath(['.'])) {172 var pubspec = await pathGetPubspecYamlMap(dir);173 var name = pubspecYamlGetPackageName(pubspec);174 var version = pubspecYamlGetVersionOrNull(pubspec);175 var sdk = pubspecYamlGetSdkBoundaries(pubspec);176 var flutter = pubspecYamlSupportsFlutter(pubspec) ? ' (flutter)' : '';177 print('${normalize(absolute(dir))}: $name $version sdk: $sdk$flutter');178 }179}180```181182### Bump the patch version of a package183184```dart185import 'package:dev_build/package.dart';186187Future<void> bumpPatch(String dir) async {188 var package = DartPackageIo(dir);189 await package.ready;190 var version = package.getVersion();191 var next = Version(version.major, version.minor, version.patch + 1);192 if (await package.writeVersion(next)) {193 print('$dir: $version -> $next');194 }195}196```197198### Packages depending on a given package, transitively199200```dart201import 'package:dev_build/package.dart';202203Future<List<String>> usersOf(String package, {String root = '.'}) =>204 recursivePubPath([root], dependencies: [package], readConfig: true);205```206207### Stop at the first Flutter package found208209```dart210import 'package:dev_build/build_support.dart';211import 'package:dev_build/package.dart';212213Future<String?> firstFlutterPackage(String root) async {214 String? found;215 await iteratePubPath(216 [root],217 onPubPath: (dir) async {218 var pubspec = await pathGetPubspecYamlMap(dir);219 if (pubspecYamlSupportsFlutter(pubspec)) {220 found = dir;221 return false; // stop222 }223 return true;224 },225 );226 return found;227}228```229230### Where is a dependency installed?231232```dart233import 'package:dev_build/build_support.dart';234235Future<void> main() async {236 // Requires a previous `dart pub get`237 var path = await pathGetResolvedPackagePath('.', 'path');238 print(path); // /home/me/.pub-cache/hosted/pub.dev/path-1.9.1239}240```241242### Add a path dependency and run pub get243244```dart245import 'package:dev_build/build_support.dart';246import 'package:dev_build/menu/menu_run_ci.dart' show PubIoPackage;247248Future<void> main() async {249 var dir = 'packages/app';250 var added = await pathPubspecAddDependency(251 dir,252 'my_lib',253 dependencyLines: ['path: ../my_lib'],254 );255 if (added) {256 var package = PubIoPackage(dir);257 await package.ready;258 await package.pubGet();259 }260}261```262263### Make sure a global tool is installed before using it264265```dart266import 'package:dev_build/package.dart';267import 'package:dev_build/shell.dart';268269Future<void> main() async {270 await checkOrPubActivateHostedPackage(271 'webdev',272 versionBoundaries: VersionBoundaries.parse('>=3.0.0 <4.0.0'),273 );274 await run('dart pub global run webdev --version');275}276```277278### Compile a package binary once and reuse it279280```dart281import 'package:dev_build/package.dart';282import 'package:dev_build/shell.dart';283284Future<void> main() async {285 var exe = await DartPackageIo('.').compiledExe(286 script: 'bin/main.dart',287 minVersion: Version(1, 0, 0),288 );289 await run('${shellArgument(exe.path)} --help');290}291```292293### Version boundaries294295```dart296import 'package:dev_build/build_support.dart';297import 'package:dev_build/shell.dart' show dartVersion;298299void main() {300 var boundaries = VersionBoundaries.parse('^3.2.0');301 print(boundaries.toMinMaxString()); // >=3.2.0 <4.0.0302 print(boundaries.matches(dartVersion)); // true on Dart 3.x >= 3.2303 print(VersionBoundaries.parse('>=1.0.0 <2.0.0').toShortString()); // ^1.0.0304}305```306307## Common mistakes308309* Importing `package:dev_build/package.dart` for `pubspecYamlGetPackageName`310 or `pathGetPubspecYamlMap`: they are in `build_support.dart`.311* Calling `pubspecYamlGetVersion` on a workspace root or an app without312 `version:`: it throws, use `pubspecYamlGetVersionOrNull`.313* Reading `package_config.json` helpers before `pub get`: they throw.314* Using `DartPackageIo` without awaiting `ready` first.315* Expecting `recursivePubPath` to return packages whose sdk constraint does316 not match the running Dart: pass `FilterDartProjectOptions(317 ignoreSdkConstraints: true)` to list them.