x3derr8
x3derr8

Reputation: 63

Dart pub global run can't resolve script name

I have a simple dart project that has one executable in bin folder (test.dart). I have activated it with dart global activate and now I can run it directly with just typing the name of that executable file.

Inside that dart file I would like to know the path of that script. Basically for now I'm just printing something like this:

print('1: ' + Platform.script.toString());
print('2: ' + Platform.script.path);
print('3: ' + Platform.executable);
print('4: ' + Platform.packageRoot);
print('5: ' + Platform.resolvedExecutable);

When I run it directly:

test

or with pub:

pub global run test

or even with package name:

pub global run test:test

I always get the same result:

1: http://localhost:53783/test.dart
2: /test.dart
3: E:\apps\dart-sdk\bin\dart
4:
5: E:\apps\dart-sdk\bin\dart.exe

The issue here is that I can't get the absolute path for test.dart file.

When I run it like this:

dart /path/to/project/bin/test.dart

I get what I need:

1: file:///E:/projects/dart/test/bin/test.dart
2: /E:/projects/dart/test/bin/test.dart
3: dart
4:
5: E:\apps\dart-sdk\bin\dart.exe

Is there a way how to get absolute path for a script that is currently running, regardless of a way how it was executed?

Upvotes: 4

Views: 248

Answers (2)

Natalie Weizenbaum
Natalie Weizenbaum

Reputation: 5964

tl;dr: There's not a great way of doing what you want, but it's in the works.

The notion of a "path for a script that is currently running" is more complicated than it might sound at first blush. There are a number of ways that the Dart ecosystem invokes main(). Off the top of my head, here are a few:

  • Manually running the file with dart.
  • Running the file in an isolate.
  • Compiling the file to a snapshot and either manually running it or running it in an isolate.
  • Automatically compiling the file to a cached executable and running that either in a subprocess or in an isolate.
  • Adding a wrapper script that imports the file and invokes main(), and either running that in a subprocess or in an isolate.
  • Serving the file over HTTP, and running it either in a subprocess or in an isolate.

In some of these cases, the "script that is running" is actually a wrapper, not the original file you authored. In others, it's a snapshot that may have no inherent knowledge of the file from which it was created. In others, the file has been modified by transformers and the actual Dart code that's running isn't on disk at all.

I suspect what you're actually looking for isn't the executable URL itself, but the location of your package's files. We're working on a collection of APIs that will make this possible, as well as a resource package that will provide a nice API for dealing with your packages' resources.

Until that lands, there is a dart:mirrors hack you can use. If you give one of your library files an explicit library tag, say library my.cool.package, you can write:

var libPath = currentMirrorSystem().findLibrary(#my.cool.package).uri.path;

This will give you the path to your library, which you can use to figure out where your package's lib/ files live.

Upvotes: 3

Kevin Moore
Kevin Moore

Reputation: 6161

If you want a reliable way to access the current file while running in pub you'll need to use mirrors.

Here's a sample usage with dartdoc tests - https://github.com/dart-lang/dartdoc/blob/41a5e4d3f6e0084a9bc2af80546da331789f410d/test/compare_output_test.dart#L17

import 'dart:mirrors';

Uri get _currentFileUri =>
    (reflect(main) as ClosureMirror).function.location.sourceUri;

void main() { ... }

Not particularly pretty, but it's easy to just put into a util file.

Upvotes: 1

Related Questions