Dart pub global run can't resolve script name - dart

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?

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.

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.

Related

trying to run an .exe file in lua

recently i have been trying to run a script in lua that through os.execute() will execute a script in C# compiled into an executablethat is in the same directory as my script.
In my first attempt adding the entire directory until the executable worked:
os.execute("C:\\ServerTest\\test\\tex\\testcode.exe")
however I need this script to work on other computers, which means I can't add the entirely path to the file.I tried countless methods to execute the .exe file inside the same directory without using the entire path and none of the methods worked
os.execute("./testcode")
os.execute [[".\testcode.exe"]]
os.execute(".\\testcode.exe")
os.execute "testcode.exe"
I even tried to create an environment variable and run the entire directory from it xD
os.execute("set wTest=%cd%")
os.execute("%wTest%\\testcode.exe")
but nothing worked. I also tried to use io.popen() but didn't get results either (because the executable will close a computer process, it does not give any output :V)
does anyone know how I can do this?????

How to embed a script in electron binary?

I'm doing long-running computations in an electron app. I'm "forking" the node process using child_process.fork to execute a script in a separate process not to block the renderer process.
The app is working fine provided that the script I'm launching with child_process.fork is in the directory I'm launching it from. What I'd like to do instead is to ship the script inside the binary (I'm using electron-builder to build one).
I've found out that the builder packs everything (including the script I'm interested in) into an .asar archive - can it be accessed by the binary at runtime?
child_process.spawn and using a language other than JS is an option too, but the problem persists - I don't know how to embed the script into the binary.
I solved the problem thanks to this response from another question.
I've added
node: {
__dirname: true,
},
to webpack.config.js and used process.resourcesPath to resolve the file path.
child_process.fork can utilize the asar library, if given a script path inside an asar archive. To achieve this I used roughly
import path from 'path';
import { fork } from 'child_process';
const scriptPath = path.join(process.resourcesPath!, 'app.asar', fileName);
const args = [];
const process = fork(scriptPath, args);
child.execFile on the other hand can utilize the asar library to spawn a process of the binary contained in an asar archive. Note that it can only resolve the binary, not its parameters, so if you wanted to embed say a Python interpreter and a Python script in your electron app, you should package it in a single binary or extract the script to the file system and execute using the embedded Python binary or load its content to a variable and execute directly using python -c "print(44)" with your script content as a -c argument parameter.

How do I get the script path in Dart?

I need to find out the directory in which the Dart script (which is currently running) is located. How do I go about doing this?
Previously, this was possible through new Options().script, but that class is no more. The arguments list from main(args) doesn't help, since it only contains arguments, not the executed Dart file (at least on Mac OS X).
According to BREAKING CHANGE: dart:io Platform and Options are deprecated, and will be removed and Breaking Change: Platform.script is a Uri, dart:platform library is gone new Options().script should be replaced by Platform.script.
Note that Platform.script returns an Uri and you should consider using toFilePath to get the file path from the file URI.
As noted the simple method is:
import 'dart:io';
print(Platform().script);
> file:///home/..../dcli_unit_tester/bin/dcli_unit_tester.dart
This is a file url, so to get the actual path use:
import 'dart:io';
print(Platform().script.toFilePath());
Of course you wanted the directory rather than the script so:
import 'dart:io';
import 'package:path/path.dart';
final pathToScript = Platform().script.toFilePath();
final pathToDirectory = dirname(pathToScript);
print(pathToDirectory);
> /home/..../dcli_unit_tester/bin
There are a few things you should understand when attempting to get the directory of the script in that the directory will change depending on how you run the script.
In particular if running your script from a globally activated package then you might not (should not) want to use the script's dirirectory for storing things.
execute .dart from cli
Here is the output from Platform if you run it from the cli:
dart bin/dcli_unit_tester.dart -p
executable: dart
script: file:///home/..../dcli_unit_tester/bin/dcli_unit_tester.dart
execute script when globally activated
Now if you run the same script from a globally activated package:
pub global activate dcli_unit_tester
dcli_unit_tester -p
executable: dart
script: file:///home/..../.pub-cache/global_packages/dcli_unit_tester/bin/dcli_unit_tester.dart-2.14.2.snapshot
In this case the directory is in pub-cache which by nature is transitory, so don't store anything that you want to get back later.
execute from compiled script
Now if you compile the script:
dart compile exe bin/dcli_unit_tester.dart
bin/dcli_unit_tester.exe -p
executable: bin/dcli_unit_tester.exe
script: file:///home/..../dcli_unit_tester/bin/dcli_unit_tester.exe
execute from within a unit test
If you run the same test from a unit test the script will be the test.dll file not you script.
I will update this answer once I work out how to get the script directory when running under unit tests (if it is even possible).
using dcli
If you are building a console app you can use the dcli package:
import 'package:dcli/dcli.dart'
print(DartScript.self.pathToScript);
print(DartScript.self.pathToScriptDirectory);
> /home/..../dcli_unit_tester/bin/dcli_unit_tester.dart
> /home/..../dcli_unit_tester/bin

customize dart compilation (paths in script element)

I was wondering if it is possible to customise how dart tool compiles the app. In particular I am interested in customizing the paths that appear in script elements.
At the moment I have my app in "app/src" folder. I run the following command from the folder above "app/src", let's call it root.
dart --package-root=app/packages/ app/packages/web_ui/dwc.dart --out tmp app/src/testapp.html
I send the output to a tmp folder in that root folder. The problem is that evey time I compile the app, the paths in script element have "../app/src" prepended to the path. So instead of having a
"packages/browser/dart.js" path I end up with "../app/src/packages/browser/dart.js". Is there a way to configure this and avoid getting this "app/src" prefixes.
Ok, I haven't found a solution to my problem using the dart tools configuration so I had to use the old friend - sed.
sed "s/../app/src/packages/packages/g" ${OUT_DIR}/test.html > ${OUT_DIR_SERVER}/test.html

how to have libraries import libraries from the same package?

The dart page http://pub.dartlang.org/doc/#adding-a-dependency describes how you can have a dart file (parser_test.dart) import files from its own package using the 'import "package:..." style of import. It seems to imply this is a good thing - better than using relative paths. This example shown is for a file in test which appears to be special. But, then why does it not make sense for importing same package lib files from a lib in the package. Maybe it does make sense, but if so the pub update does not make it convenient.
foo/
/lib/
foo_lib_1.dart
foo_lib_2.dart
src/
foo_lib_1/
foo_lib_1_impl.dart
foo_lib_2/
foo_lib_2_impl.dart
Assume foo_lib_2 uses foo_lib_1. There are two options for foo_lib_2.dart:
import "../foo_lib_1.dart";
import "packages:foo/foo_lib_1.dart";
My guess is the suggested approach is the first for any such import that resides under lib. The reason I think this is pub update seems to automagically provide a soft link in the packages folder of any of bin, test, or example to foo, like foo -> ../lib. Yet, it does not do the same for the packages folder in top level foo. This means to get the second type of import (i.e. the packages import) to work you need to add:
foo:
path: lib
to the dependencies of foo in the pubspec.yaml. Is there any advantage or disadvantage for a library to use the package style import to import another library (not in test, bin, or example) from its own package? Is there a reason for the apparent inconsistency?
After accepting the answer below, I still am not seeing it. Here is what I'm seeing in a shell session and I would like to reconcile this behavior with the answer. Any explanations appreciated. I am using emacs instead of DartEditor, thus the old-school command line approach here.
### Show all files, one dart library file and one yaml, plus empty
### lib and test folders
user#user-thinkpad:/tmp/uml_codegen_sample$ ls -R
.:
lib pubspec.yaml test
./lib:
plusauri.dart
./test:
### Show contents of pubspec
user#user-thinkpad:/tmp/uml_codegen_sample$ cat pubspec.yaml
name: domain_model
version: 0.0.1
description: >
Auto-generated support from /home/user/plusauri/modeling/plusauri.xmi.json
dependencies:
ebisu:
path: /home/user/open_source/codegen/dart/ebisu
### Run pub install and show the changes. Note there is a soft
### link to packages from test, but not lib.
user#user-thinkpad:/tmp/uml_codegen_sample$ pub install
Resolving dependencies...
Dependencies installed!
Some packages that were installed are not compatible with your SDK version 0.4.7+5.r21658 and may not work:
- 'pathos' requires >=0.5.0+1
You may be able to resolve this by upgrading to the latest Dart SDK
or adding a version constraint to use an older version of a package.
user#user-thinkpad:/tmp/uml_codegen_sample$ ls -R
.:
lib packages pubspec.lock pubspec.yaml test
./lib:
plusauri.dart
./packages:
domain_model ebisu pathos
./test:
packages
### Note here the program does not work, and suspiciously pub
### install put no packages link under lib like it did test
user#user-thinkpad:/tmp/uml_codegen_sample$ dart lib/plusauri.dart
Unable to open file: /tmp/uml_codegen_sample/lib/packages/ebisu/ebisu_utils.dart'file:///tmp/uml_codegen_sample/lib/plusauri.dart': Error: line 5 pos 1: library handler failed
import "package:ebisu/ebisu_utils.dart" as EBISU_UTILS;
^
### Copy the same dart file to test to show that it can run there
### just fine
user#user-thinkpad:/tmp/uml_codegen_sample$ cp lib/plusauri.dart test/
user#user-thinkpad:/tmp/uml_codegen_sample$ dart test/plusauri.dart
Main for library plusauri
user#user-thinkpad:/tmp/uml_codegen_sample$
### Finally, manually create the soft link in lib, to show it will
### then run
user#user-thinkpad:/tmp/uml_codegen_sample$ ln -s ../packages lib/packages
user#user-thinkpad:/tmp/uml_codegen_sample$ dart lib/plusauri.dart
Main for library plusauri
Actually, you can definitely import using the package:foo/foo_lib_1.dart syntax without needing to change your pubspec.yaml or even creating a pubspec.yaml in the first place!
You can see that this is true from a language level, in this test: https://github.com/dart-lang/bleeding_edge/blob/master/dart/tests/standalone/package/packages/package1.dart
and an example of this in the wild is: https://github.com/kevmoo/hop.dart/blob/master/lib/hop_tasks.dart#L17
I do not think there is any benefit from writing one way or another except that writing relative paths is slightly shorter.
From a project structure point of view, I would use relative path imports when I am drilling into subdirectories that are not going to be exposed to the user. src is generally seen as implementation specific details that won't be visible to external users, so use relative paths to your heart's content.
However, if you're working within multiple directories, then you should use package: imports to reinforce the idea that the parts are stand-alone and interchangeable. Within the lib directory itself, you want to say that these two libraries, although they might rely on each other, can live separately and are not bound by their physical location.
I would recommend not ever using ../ in your imports, as that is fragile and may break in strange ways if/when you modify directory structure or deploy.

Resources