Giter Site home page Giter Site logo

fornwall / rust-script Goto Github PK

View Code? Open in Web Editor NEW
1.1K 11.0 38.0 771 KB

Run Rust files and expressions as scripts without any setup or compilation step.

Home Page: https://rust-script.org

License: Apache License 2.0

Rust 97.13% Shell 2.87%
rust script cargo

rust-script's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rust-script's Issues

Excessive script overhead

Consider:

# grep . *.rs
h1.rs:fn main() { println!("hi") }
h2.rs:#! /usr/bin/env cargo-eval
h2.rs:fn main() { println!("hi") }
h3.rs:#! /usr/bin/env rust-script
h3.rs:fn main() { println!("hi") }
# rustc h1.rs
# hyperfine --warmup=1 ./h1 ./h2.rs ./h3.rs
Benchmark 1: ./h1
  Time (mean ± σ):       1.2 ms ±   0.1 ms    [User: 0.4 ms, System: 0.9 ms]
  Range (min … max):     0.0 ms …   1.8 ms    1013 runs

Benchmark 2: ./h2.rs
  Time (mean ± σ):       5.8 ms ±   6.9 ms    [User: 2.1 ms, System: 2.7 ms]
  Range (min … max):     1.4 ms …  88.8 ms    402 runs

Benchmark 3: ./h3.rs
  Time (mean ± σ):      99.5 ms ±   3.8 ms    [User: 84.2 ms, System: 14.0 ms]
  Range (min … max):    95.8 ms … 114.0 ms    25 runs

Summary
  './h1' ran
    4.95 ± 5.87 times faster than './h2.rs'
   84.60 ± 10.38 times faster than './h3.rs'

On a good laptop the difference isn't so bad, ./h1 is only 30x faster than ./h3.rs. The times are above are on a server with slow HDD disks.

I was excited to see an actively maintained Rust scripting crate, but this overhead is too much. I also worry that whatever the .json writes are for will be broken if there are many concurrent runs of the script.

Can't build with rustc 1.54

Can't build on macOS with:

  • rustc 1.56.0-nightly (6d64f7f69 2021-08-19)
  • rustc 1.54.0 (a178d0322 2021-07-26)

macOS: 11.5.2 (20G95)

cargo install rust-script
...
  Installing rust-script v0.16.0
   Compiling rust-script v0.16.0
error[E0599]: no method named `multiple` found for struct `Arg` in the current scope
   --> /Users/username/.cargo/registry/src/github.com-1ecc6299db9ec823/rust-script-0.16.0/src/main.rs:125:18
    |
125 |                 .multiple(true)
    |                  ^^^^^^^^ method not found in `Arg<'_>`

error[E0599]: no method named `multiple` found for struct `Arg` in the current scope
   --> /Users/username/.cargo/registry/src/github.com-1ecc6299db9ec823/rust-script-0.16.0/src/main.rs:168:18
    |
168 |                 .multiple(true)
    |                  ^^^^^^^^ method not found in `Arg<'_>`

error[E0599]: no method named `multiple` found for struct `Arg` in the current scope
   --> /Users/username/.cargo/registry/src/github.com-1ecc6299db9ec823/rust-script-0.16.0/src/main.rs:176:18
    |
176 |                 .multiple(true)
    |                  ^^^^^^^^ method not found in `Arg<'_>`

error[E0599]: no method named `multiple` found for struct `Arg` in the current scope
   --> /Users/username/.cargo/registry/src/github.com-1ecc6299db9ec823/rust-script-0.16.0/src/main.rs:184:18
    |
184 |                 .multiple(true)
    |                  ^^^^^^^^ method not found in `Arg<'_>`

error[E0599]: no method named `multiple` found for struct `Arg` in the current scope
   --> /Users/username/.cargo/registry/src/github.com-1ecc6299db9ec823/rust-script-0.16.0/src/main.rs:197:18
    |
197 |                 .multiple(true)
    |                  ^^^^^^^^ method not found in `Arg<'_>`

For more information about this error, try `rustc --explain E0599`.


rustc -V            
rustc 1.56.0-nightly (6d64f7f69 2021-08-19)

Justfile integration

I have a script that works with rust-script:

#!/usr/bin/env rust-script
//! ```cargo
//! [dependencies]
//! dummy = { path = "./dummy" }
//! ```
fn main() {
   dummy::run();
}

It depends on a local crate in the same directory where the script file lives.

I'd like to run it via a runner like just. However when run from the runner, the script location is not in the same directory where the the runner recipe lives and thus the dependencies relative paths no longer work.

demo:
    #!/usr/bin/env rust-script
    //! ```cargo
    //! [dependencies]
    //! dummy = { path = "./dummy" }
    //! ```
    fn main() {
       dummy::run();
    }
$ just demo
error: failed to get `dummy` as a dependency of package `demo v0.1.0 (/Users/mkm/Library/Caches/rust-script/projects/f40865aa4eabcf6c25c2788e)`

Caused by:
  failed to load source for dependency `dummy`

Caused by:
  Unable to update /var/folders/zp/pk0v2q4x39z43k91vst1_jsc0000gn/T/justzxHC7g/dummy

Caused by:
  failed to read `/var/folders/zp/pk0v2q4x39z43k91vst1_jsc0000gn/T/justzxHC7g/dummy/Cargo.toml`

Caused by:
  No such file or directory (os error 2)
error: Could not execute cargo
error: Recipe `demo` failed with exit code 1

The runner runs the script with $PWD set to the place I expect it to be, but rust-script (correctly) uses the location of the rust script to find deps.

Is there a trick I can use in order to fool rust-script about its location (fiddling with argv[0] ?)
Or could we add a flag to tell rust-script to use $PWD as base dir for resolving dependencies?

Adding information to the README

I wonder if I can change the README.md file by adapting information from the docs/README.md, so that people don't have to leave the repository and go to the website to see what this project does.

IDE support

Is there a known way for something like rust-analyzer to work on these scripts? I think if I add a Cargo.toml with all the crates I use in my scripts, I might be able to get some support.

However, that won't work with the special template syntax.

Any tips regarding using IDEs with rust-script? I believe cargo-eval and cargo-script suffer from the same issues.

Friendlier compilation progress

I would like to use rust-script to implement scripts that others will run. Most will not be familiar with Rust let alone rust-script. The default behavior makes it look like the script is hung when compilation is being performed silently. An alternative is to use the --cargo-output option but this is too much output and too foreign for those not familiar with Rust/rust-script.

It would be nice if rust-script could be made (via an option) to print a messages like "Performing an initial one-time compilation..." and "Performing a recompilation..." or similar (maybe just "Building...") to indicate that something is happening.

It would be even nicer if the cargo progress bar could be shown w/o all of the other cargo output. But maybe this needs support from cargo.

Can't install via `cargo install`; Cargo ignores `clap` version

This is a weird one. I can clone the project and build it locally just fine, but if I try and install it from crates.io with cargo install rust-script (or from a local checkout with cargo install --path .) I get a bunch of errors like the following:

   ...
   Compiling clap v3.0.0-rc.0
   ...
   Compiling rust-script v0.18.0
error[E0599]: no method named `about` found for struct `Arg` in the current scope
   --> /home/eap/.cargo/registry/src/github.com-1ecc6299db9ec823/rust-script-0.18.0/src/main.rs:109:18
    |
109 |                 .about("Script file or expression to execute.")
    |                  ^^^^^ method not found in `Arg<'_>`

error[E0599]: no method named `about` found for struct `Arg` in the current scope
   --> /home/eap/.cargo/registry/src/github.com-1ecc6299db9ec823/rust-script-0.18.0/src/main.rs:123:18
    |
123 |                 .about("Execute <script> as a literal expression and display the result.")
    |                  ^^^^^ method not found in `Arg<'_>`
    ...

Looks like Cargo.toml specifies clap-3.0.0-beta.5 which indeed has the Arg::about method, but as you can see above cargo install tries to use clap-3.0.0-rc.0 which does not have Arg::about. Why would Cargo be doing this? Is there a workaround?

Document how to use external modules?

Is it possible to use external modules? If yes, then it may make sense to document how.

Example:

% cat ./main.rs
mod other;

fn main() {
    other::hello();
}

% cat ./other.rs 
pub fn hello() {
    println!("How are you?");
}

For comparison, cargo-play handles it like this. I can run the aforementioned two modules via cargo play *.rs

README says `script-script`

The README demonstrates installing this with cargo install script-script. This is confusing as the project is (now) named rust-script.

rust-script fails to install file association

Hi.

rust-script fails to install file association.

❯ rust-script --install-file-association
error: Found argument '--install-file-association' which wasn't expected, or isn't valid in this context

        If you tried to supply `--install-file-association` as a value rather than a flag, use `-- --install-file-association`

USAGE:
    rust-script [OPTIONS] [--] [script]...

For more information try --help

bin/bin/public on  master [!]
❯ rust-script --version
rust-script 0.21.0
OS: Fedora Linux 36 (Workstation Edition) x86_64
Kernel: 5.19.11-200.fc36.x86_64
Shell: zsh 5.8.1
DE: GNOME 42.5
WM: Mutter

No such file or directory (os error 2)

Version 0.23.0 keeps giving me an error whenever I run a script.

error: No such file or directory (os error 2)

Had to use the previous version for it to work.

Version info:

cargo 1.68.1
rustc 1.68.1 (8460ca823 2023-03-20) (built from a source tarball)

Get readelf -p .comment

String dump of section '.comment':
  [     0]  mold 1.11.0 (compatible with GNU ld)
  [    25]  Android (9352603, based on r450784d1) clang version 14.0.7 (https://android.googlesource.com/toolchain/llvm-project 4c603efb0cca074e9238af8b4106c30add4418f6)

Main function recognition

Description

If I add a space after the function identifier main rust-script will not use the function.

Example

  • This example was taken from the example script in this repository's main readme.
  • The only change was that I added a space between main and ():
#!/usr/bin/env rust-script
//! Dependencies can be specified in the script file itself as follows:
//!
//! ```cargo
//! [dependencies]
//! rand = "0.8.0"
//! ```

use rand::prelude::*;

fn main () {
    let x: u64 = random();
    println!("A random number: {}", x);
}

This can be seen this in the following compiler warnings:

» rust-script script2.rs
warning: unused doc comment
  --> script2.rs:3:5
   |
2  | /      {
3  | |      //! Dependencies can be specified in the script file itself as follows:
   | | _____^
4  | || //!
5  | || //! ```cargo
6  | || //! [dependencies]
7  | || //! rand = "0.8.0"
8  | || //! ```
   | ||_______^
...  |
15 | |  }
16 | |      }
   | |______- rustdoc does not generate documentation for expressions
   |
   = help: use `//` for a plain comment
   = note: `#[warn(unused_doc_comments)]` on by default

warning: function `main` is never used
  --> script2.rs:12:4
   |
12 | fn main () {
   |    ^^^^
   |
   = note: `#[warn(dead_code)]` on by default

Why is this an issue?

In my case, I generate rust scripts externally using quote, which injects these errant spaces into the output TokenStream.

As seen above, this is valid Rust code. I am opening this issue here because I assume it's relevant, but please let me know if I should close it and look somewhere else.

Notes

If you feel this is worth changing, I can try to fix it and open a PR. I'm not sure where to look for this problem though, tbh.

Multiple dependencies not supported

> cargo install rust-script --version 0.22.0
> rust-script -d anyhow -d serde scripts/example.rs 
Hello World

> cargo install rust-script --version 0.23.0
> rust-script -d anyhow -d serde scripts/example.rs 
error: the argument '--dep <dep>' cannot be used multiple times

Usage: rust-script [OPTIONS] [script]...

For more information, try '--help'.

Starting with version 0.23.0, it is no longer possible to pass multiple -d or --dep flags. It appears that clap was upgraded in that version, and I surmise that is somehow responsible.

--gen-pkg-only should print the path to the resulting package

Currently, it's a major hassle to identify the output directory for --gen-pkg-only if I want to build a command for "OK, this 'one-off' script has outgrown a single file. Let's turn it into a full project."

--gen-pkg-only should print the path it's writing to so I can do something like this

outdir="$(rust-script --gen-pkg-only "$1")"
mv "$1" "$2"
cd "$2"
git init
git commit -a -m "Unpack '$1' into its own project"

Maybe also a flag that does similar for the generated binary to streamline the "I want Rust for its cold-cache startup performance. Bypass Cargo entirely" case where you'd otherwise have to use --cargo-output and then copy-paste the path out of it.

Configure the build options

I'd love to be able to use rust-script to run no_std scripts that depend on custom build options, which normally are configured inside the .cargo/config.toml file. e.g.:

[build]
target = "x86_64-unknown-none"
rustflags = ["-C", "link-args=-N", "-C", "relocation-model=static"]

Ideally I'd love to be able to specify a section like this in the header:

//! ```config
//! [build]
//! target = "x86_64-unknown-none"
//! rustflags = ["-C", "link-args=-N", "-C", "relocation-model=static"]
//! ```

and it would be copied to the appropriate place like it happens now with the Cargo.toml.

exe_path is wrong when the script name matches the name of a dependency

This bug still exists in rust-script: DanielKeep/cargo-script#57

Copied:

Can be reproduced with the following script:

Filename: time.rs

#!/usr/bin/env run-cargo-script
// cargo-deps: chrono
extern crate chrono;
fn main() {
    println!("Hello");
}

When trying to execute with ./time.rs or cargo script time.rs, it fails with internal error: Permission denied (os error 13) because it tries to run /home/user/.cargo/binary-cache/release/deps/libtime-2d0d7bb318809c2f.rlib instead of .cargo/binary-cache/release/time.

Some time ago, this worked. I’d guess the error lies in cargo_target_by_message, picking the wrong line because the target.name is the same as the package name.

Workaround: Renaming the script to another name lets it run fine.


(Paths/Invocations should be adjusted for rust-script of course)

Run Hidden (On Windows)

Normally running Rust applications with #![windows_subsystem = "windows"] effectively hides the console window.

It would be nice if there were some config for rust-script or an automated way to detect scripts containing this line and ensure that rust-script itself doesn't create a console window to run the application.

I feel this is important when running automated scripts from Task Scheduler or other scripts. And I think rust-script shouldn't necessarily be popping up a new console window each time when it's undesired that it does so. Since new windows are Focus grabbing and can interfere with other things you may be doing, it would be nice to have an official way around this.

Is it possible to run command (e.g. `cargo tree`) in rust-script script project directory ?

Is it possible to run command (e.g. cargo tree) in rust-script script project directory ?
Otherwise, could support for it be added?

(sometimes running commands inside project directory is very helpful, e.g. for debugging, and having convenient way to run them, or to jump there => e.g. rust-script to print directory path, so one could do cd "$(rust-script --project-dir script.ers) could be very handy!

`rust-toolchain` affects which rustc version is used to execute a script

If I have a script in a directory in my $PATH, say /usr/local/bin/foo, and it starts with #!/usr/bin/env rust-script and it has the executable flag set, then I can invoke that script from anywhere in my system with $ foo. And that usually works fine. When executing the script from a directory that has a rust-toolchain file in it, then -- to my surprise -- rust-script uses the rust toolchain version specified in the rust-toolchain file to execute the script. This feels like a bug to me, since the contents of a directory shouldn't affect what interpreter or compiler is used to run an executable in my $PATH.

An extreme example is this: If I put e.g. 1.10 into the rust-toolchain file, the rust script cannot be executed at all, since rust-script fails with error: Unknown flag: '--target-dir'.

I think I would expect rust-script to always use the default toolchain.

Is this an intended feature? Could this be changed?

no_std support with extern main

This minimal example fails to compile:

#!/usr/bin/env -S rust-script -c
//! ```cargo
//! [dependencies]
//! libc = { version = "0.2", default-features = false }
//! 
//! [profile.release]
//! strip = true
//! lto = true
//! opt-level = "s" # "z"
//! codegen-units = 1
//! panic = "abort"
//! ```

#![no_std]
#![no_main]

#[panic_handler]
fn my_panic(_info: &core::panic::PanicInfo) -> ! {
    loop {}
}

#[no_mangle]
pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize {
    unsafe {
        libc::printf("hello, world\0".as_ptr() as *const _);
    }
    0
}

I've just sent a PR that updates the contains_main_method making the main detection work.

rust-gdb - easy way to run rust-scripts with gdb

rust-gdb -

Could you please add some feature to make it easy to run rust-scripts with gdb ?

I've found flag --debug to build in debug mode. However it : 1. also runs script and 2. still I need to sk cache directory looking for path to debug build binary.

What about flag (maybe with shorter name) --build-only-and-return-absolute-path-to-binary ?

That way I could run rust-gdb "$(rust-script --debug --build-only-and-return-absolute-path-to-binary my_script.rs)" to comfortably run script in debugger ?

error[E0658]: arbitrary expressions in key-value attributes are unstable

$ cargo install rust-script
Updating crates.io index
[...]
[...]
Compiling env_logger v0.9.0
Compiling clap_derive v3.0.0-beta.5
Compiling clap v3.0.0-beta.5
error[E0658]: arbitrary expressions in key-value attributes are unstable
--> /home/flav/.cargo/registry/src/github.com-1ecc6299db9ec823/clap-3.0.0-beta.5/src/lib.rs:8:10
|
8 | #![doc = include_str!("../README.md")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #78835 rust-lang/rust#78835 for more information

error: aborting due to previous error

For more information about this error, try rustc --explain E0658.
error: could not compile clap

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: failed to compile rust-script v0.18.0, intermediate artifacts can be found at /tmp/cargo-installAqSpQJ

Caused by:
build failed

rust-script fails to execute in nix

I've installed rust-script via nix like so:

nix-shell -p rust-script

In that shell, I can run the rust-script executable:

[nix-shell:~]$ rust-script --version
rust-script 0.20.0

However, if I attempt to provide a file, I get an error:

[nix-shell:~]$ rust-script ~/myscript
error: No such file or directory (os error 2)

The same problem happens with the --expr option:

[nix-shell:~]$ rust-script --expr "3"
error: No such file or directory (os error 2)

Here is a full trace:

[nix-shell:~]$ RUST_LOG=rust_script=trace rust-script ~/myscript
[2022-05-21T18:42:48Z INFO  rust_script] Arguments: Args { script: Some("/Users/dta/myscript"), script_args: [], features: None, expr: false, loop_: false, count: false, pkg_path: None, gen_pkg_only: false, cargo_output: false, clear_cache: false, debug: false, dep: [], extern_: [], force: false, unstable_features: [], build_kind: Normal, template: None, list_templates: false, toolchain_version: None }
[2022-05-21T18:42:48Z INFO  rust_script] input: File("myscript", "/Users/dta/myscript", "", 1653158268482)
[2022-05-21T18:42:48Z INFO  rust_script] prelude_items: []
[2022-05-21T18:42:48Z INFO  rust_script] id: "65f3c77206ea3caf68f2d30d"
[2022-05-21T18:42:48Z INFO  rust_script] pkg_path: "/Users/dta/Library/Caches/rust-script/projects/65f3c77206ea3caf68f2d30d"
[2022-05-21T18:42:48Z INFO  rust_script] using_cache: true
[2022-05-21T18:42:48Z INFO  rust_script::manifest] part_mani: Toml("")
[2022-05-21T18:42:48Z INFO  rust_script::manifest] source: "fn main() -> Result<(), Box<dyn std::error::Error+Sync+Send>> {\n    {\n        }\n    Ok(())\n}"
[2022-05-21T18:42:48Z INFO  rust_script::manifest] part_mani: {}
[2022-05-21T18:42:48Z INFO  rust_script::manifest] mani: {"bin": Array([Table({"name": String("myscript_65f3c77206ea3caf68f2d30d"), "path": String("myscript.rs")})]), "dependencies": Table({}), "package": Table({"authors": Array([String("Anonymous")]), "edition": String("2018"), "name": String("myscript"), "version": String("0.1.0")})}
[2022-05-21T18:42:48Z INFO  rust_script::manifest] mani_str: [[bin]]
    name = "myscript_65f3c77206ea3caf68f2d30d"
    path = "myscript.rs"
    
    [dependencies]
    
    [package]
    authors = ["Anonymous"]
    edition = "2018"
    name = "myscript"
    version = "0.1.0"
    
[2022-05-21T18:42:48Z INFO  rust_script] input_meta: PackageMetadata { path: Some("/Users/dta/myscript"), modified: Some(1653158268482), template: None, debug: false, deps: [], prelude: [], features: None, manifest_hash: "a8e53ac300f30974d4a72844ff059f9142643863", script_hash: "56ecf0b760b401c9aa37b7ff226399b2b988b458" }
[2022-05-21T18:42:48Z DEBUG rust_script] meta_path: "/Users/dta/Library/Caches/rust-script/projects/65f3c77206ea3caf68f2d30d/metadata.json"
[2022-05-21T18:42:48Z INFO  rust_script] action: InputAction { cargo_output: false, force_compile: false, emit_metadata: true, execute: true, pkg_path: "/Users/dta/Library/Caches/rust-script/projects/65f3c77206ea3caf68f2d30d", using_cache: true, toolchain_version: None, metadata: PackageMetadata { path: Some("/Users/dta/myscript"), modified: Some(1653158268482), template: None, debug: false, deps: [], prelude: [], features: None, manifest_hash: "a8e53ac300f30974d4a72844ff059f9142643863", script_hash: "56ecf0b760b401c9aa37b7ff226399b2b988b458" }, old_metadata: Some(PackageMetadata { path: Some("/Users/dta/myscript"), modified: Some(1653158268482), template: None, debug: false, deps: [], prelude: [], features: None, manifest_hash: "a8e53ac300f30974d4a72844ff059f9142643863", script_hash: "56ecf0b760b401c9aa37b7ff226399b2b988b458" }), manifest: "[[bin]]\nname = \"myscript_65f3c77206ea3caf68f2d30d\"\npath = \"myscript.rs\"\n\n[dependencies]\n\n[package]\nauthors = [\"Anonymous\"]\nedition = \"2018\"\nname = \"myscript\"\nversion = \"0.1.0\"\n", script: "fn main() -> Result<(), Box<dyn std::error::Error+Sync+Send>> {\n    {\n        }\n    Ok(())\n}", build_kind: Normal }
[2022-05-21T18:42:48Z INFO  rust_script] creating pkg dir...
[2022-05-21T18:42:48Z INFO  rust_script] generating Cargo package...
[2022-05-21T18:42:48Z DEBUG rust_script] overwrite_file("/Users/dta/Library/Caches/rust-script/projects/65f3c77206ea3caf68f2d30d/Cargo.toml", _, Some("a8e53ac300f30974d4a72844ff059f9142643863"))
[2022-05-21T18:42:48Z DEBUG rust_script] .. hashes match
[2022-05-21T18:42:48Z DEBUG rust_script] overwrite_file("/Users/dta/Library/Caches/rust-script/projects/65f3c77206ea3caf68f2d30d/myscript.rs", _, Some("56ecf0b760b401c9aa37b7ff226399b2b988b458"))
[2022-05-21T18:42:48Z DEBUG rust_script] .. hashes match
[2022-05-21T18:42:48Z INFO  rust_script] emitting metadata...
[2022-05-21T18:42:48Z DEBUG rust_script] meta_path: "/Users/dta/Library/Caches/rust-script/projects/65f3c77206ea3caf68f2d30d/metadata.json"
[2022-05-21T18:42:48Z INFO  rust_script] disarming pkg dir cleanup...
[2022-05-21T18:42:48Z INFO  rust_script] running `cargo run`
[2022-05-21T18:42:48Z INFO  rust_script] cleaning cache with max_age: 604800000
[2022-05-21T18:42:48Z INFO  rust_script] cutoff:            1652553768992 ms
[2022-05-21T18:42:48Z INFO  rust_script] checking: "/Users/dta/Library/Caches/rust-script/projects/d2ff9865f1eaa9644ad89e24"
[2022-05-21T18:42:48Z INFO  rust_script] meta_mtime:        1653158506101 ms
[2022-05-21T18:42:48Z INFO  rust_script] checking: "/Users/dta/Library/Caches/rust-script/projects/65f3c77206ea3caf68f2d30d"
[2022-05-21T18:42:48Z INFO  rust_script] meta_mtime:        1653158568990 ms
[2022-05-21T18:42:48Z INFO  rust_script] checking: "/Users/dta/Library/Caches/rust-script/projects/469150566bd728fc90b4adf6"
[2022-05-21T18:42:48Z INFO  rust_script] meta_mtime:        1653157831910 ms
[2022-05-21T18:42:48Z INFO  rust_script] checking: "/Users/dta/Library/Caches/rust-script/projects/e4e0ddc7731ab1b525ef66f2"
[2022-05-21T18:42:48Z INFO  rust_script] meta_mtime:        1653157605894 ms
[2022-05-21T18:42:48Z INFO  rust_script] checking: "/Users/dta/Library/Caches/rust-script/projects/871fdb4f6a736fff1ddcba23"
[2022-05-21T18:42:48Z INFO  rust_script] meta_mtime:        1653158135317 ms
[2022-05-21T18:42:48Z INFO  rust_script] done cleaning cache.
error: No such file or directory (os error 2)

First CLI Argument should contain name of script instead of compiled binary

#!/usr/bin/env rust-script
use std::env;

fn main() {
  let args: Vec<String> = env::args().collect();
  println!("{:?}", args);
}

executing this with rust-script prints out
["/home/chriss/.cache/rust-script/binaries/release/rust-script-test_83ff7425da238fd28ad88049"]
instead, I would expect "./rust-script-test.rs", or whatever the script is called with.

Would this be even possible?

Maybe related:
ps a
also shows script like
879316 pts/5 S+ 0:00 /home/chriss/.cache/rust-script/binaries/release/rust-script-test_83ff7425da238fd28ad88049
instead of the script name. Can this be changed? Should this be a separate issue?

Suggestions for additional running modes

  • Combined --loop and --expr, where the lambda is evaluated once per line, and the return value is printed
  • Related to the above, --loop --flatten, which is the same as above, but the lambda returns an IntoIterator (such as Option<T>) and prints each item once per line
  • --display mode, where Display is used instead of Debug when running in expression mode to print items

Specifying build target

I'm building an OS kernel and use rust-script for some build tasks. However, cargo's config.toml file is still used for the script, and that TOML file contains actions for building parts of the rust standard library (core, alloc, ...). (This is a known issue for cargo.) Is there a way of getting around this? I'm using cargo-make, and I'd explicitly like the build script I use to not be influenced by anything in .cargo/config.toml.

rust-script can leave orphaned child processes when killed on Windows

If you kill the rust-script process it will not pass the kill signal to the child process with a compiled binary. With the way I use rust-script, this leaves me with a few stale processes that I have to clean up manually.

It's easy to address this for unix (although that'll likely disrupt deferred cache cleanup)

Example diff
diff --git a/src/main.rs b/src/main.rs
index 6ea81a3..c97b3fc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -27,6 +27,7 @@ use serde::{Deserialize, Serialize};
 use std::ffi::OsString;
 use std::fs;
 use std::io::{Read, Write};
+use std::os::unix::process::CommandExt;
 use std::path::{Path, PathBuf};
 use std::process::Command;

@@ -481,18 +482,17 @@ fn try_main() -> MainResult<i32> {
         })
     };

-    let exit_code = if action.execute {
+    if action.execute {
         let cmd_name = action.build_kind.exec_command();
         info!("running `cargo {}`", cmd_name);
         let run_quietly = !action.cargo_output;
         let mut cmd = action.cargo(cmd_name, &args.script_args, run_quietly)?;

-        cmd.status().map(|st| st.code().unwrap_or(1))?
+        let err = cmd.exec();
+        Err(MainError::from(err))
     } else {
-        0
-    };
-
-    Ok(exit_code)
+        Ok(0)
+    }
 }

 /**

and not so much for Windows: see implementation used by cargo run or wexecvp-based implementation suggested for exec crate.

Extract more rust-script logic into library convenient to use by rust-analyzer

I made issue asking rust-analyzer to support rust-script , so I would benefit from better Vim support for rust-scripts in the end...

On issue concern, seemed like they would need to replicate rust-script logic:
rust-lang/rust-analyzer#9609 (comment)

Maybe there is option for two project to collaborate and find way how to make it work?
E.g. rust-script exporting some logic into libraries convenient to use by rust-analyzer?

expose a way to show compilation progress?

Currently when I use rust-script in a shebang line, the first execution of the script hangs for quite a while as all the dependencies are being compiled. This is fine for me personally, since I know what it's doing, but I worry that if I shipped a script like that to other users they might think it was broken and Ctrl-C it or similar. Is there an option to tell rust-script to print something to stderr (or just un-suppress Cargo output) when it needs to build?

Add support for offline compilation

I wish to use rust-script with my i3blocks to obtain system temperature. My script works. But it required internet for compilation, and hence I could not run it during startup, and my bar ignored it completely. Can we make use of the cache and offer an offline compilation mode?

cargo-script issue
Modes suggestion

Ability To Specify Script-Relative `include!()` Statement

Doing something like

mod script_module {
    include!("./script-module.rs");
}

does not work.

I came up with the following solution:

mod script_module {
    include!(concat!(env!("PWD"), "/script-module.rs"));
}

But it is not completely cross platform, as PWD is not defined on Windows (I think unless you're in PowerShell or Git BASH).

All of the CARGO_* environment variables point inside the ./.rust-script folder, so there's no way to compose a path that points to the current directory.

I wonder if it's possible to override CARGO_MANIFEST_DIR to point to the directory in which the script is located, or make env!("RUST_SCRIPT_BASE_PATH") work (currently RUST_SCRIPT_BASE_PATH is only defined for the runtime of the script and not during rustc compilation).

scripts can't have flags that rust-script itself has

Consider:

# cat help.rs
#! /usr/bin/env rust-script
fn main() {
    if let Some(arg) = std::env::args().skip(1).next() {
        if arg == "--help" {
            println!("???");
        } else {
            println!("{}", arg);
        }
    }
}
# ./help.rs -V
rust-script 0.17.0
# ./help.rs --unique
--unique
# ./help.rs --help
rust-script 0.17.0

Compiles and runs a Rust script.

USAGE:
    rust-script [OPTIONS] [--] [ARGS]
...

Edition

rust-script is trying to execute my file as 2018 edition which is wrong. I can't find any documentation on getting it to use 2021 edition and this does not work:

/// ```cargo
/// edition = '2021'
/// ```

Option to show macro expansion of input

I'd love a flag that makes this print the macro expansion of the input instead of compiling and running it. This could be done as a flag like --macro-expand that selects the nightly toolchain (if not otherwise set) and runs cargo rustc --profile=check -- -Zunpretty=expanded.

Alternatives considered

rust-script could have a flag for simply changing the cargo command being run, such that if I have cargo-expand installed I could write something like rust-script --cargo-cmd expand script.rs. This is more flexible (e.g. I could also use it to run cargo clippy or cargo check if I'm just trying to see any warnings or errors), though it does require the user to install cargo-expand first.

With this approach the --test and --bench flags could potentially be obsoleted in favor of just specifying the test and bench cargo commands, though in this case the syntax for specifying the command should be simpler. I notice that right now rust-script lists its syntax as rust-script [OPTIONS] [--] [script]... but if I actually run rust-script foo bar it treats foo as a script and ignores bar completely (also it indicates script as being optional and yet it is not). This could be updated to the syntax rust-script [OPTIONS] [--] [cmd] <script> instead such that I could write rust-script test foo.rs to run cargo test or rust-script expand foo.rs to run cargo expand.

Clippy mode

It would be useful to have a clippy mode which runs clippy on the script, ideally clippy args could be supplied (especially as -A has no alternative in a config file).

This could be used to run on purposely "imperfect" code to show the messages that rust compiler/clippy provide for the sample code.

Allow using script with a template instead of just expr

Maybe this is already a feature, but I can't figure out the syntax.

I made a template called sys.rs and put it in the right path, but none of these work:

rust-script myscript -t sys
rust-script -t sys myself

--expr seems required with a --template flag.

Add `--strip` flag

The --strip flag would strip the binary right after compiling it, which increases the time of compiling but reduces the binary size.

A println!("Hello World!") program, for example:

  • 3.3M after compiling.
  • 268KB after stripping.

(I'm willing to implement it.)

rust-script exports CARGO_TARGET_DIR to script process

I have a rust-script that calls cargo install --path . as a child process. I expected that process to create a target directory, but that didn't happen. IIUC, this is because rust-script sets CARGO_TARGET_DIR to ~/.cache/rust-script/binaries. It also seems to set a bunch of other cargo related environment variables.

I think this is a bug, since cargo commands from within a rust-script should work the same way as they would if executed from outside of a rust-script. I would expect rust-script to not modify the environment of the script process in any way. (Except maybe for some variables prefixed with RUST_SCRIPT_ for some reason.) Or is this somehow necessary to make rust-script work?

pub fn main() doesn't work

Looks like only these signatures are supported currently:

let source = if source   
    .lines()   
    .any(|line| line.starts_with("fn main()") || line.starts_with("async fn main()"))

Could we also support pub fn main()? This would make it easier to develop/debug scripts from the IDE, since currently I keep them all in a cargo project.

Running files that include uppercase letter generates warning

Running rust-script in any file that includes uppercase letter generates a crate with the same name, which cargo
complains.

While rust files are usually modules and as such should be lowercase, sometimes the user may choose a name that matches his project better. Also cargo-make uses temporary files that may contain uppercase letters.

My proposed solution would be to convert the file name to snake case when using as the crate name. serde can do this for struct fields, so I suppose a simple solution already exists in the ecosystem. I can give it a try if you would accept.

Script.rs:

fn main() {
    println!("test");
}

Output:

$ rust-script Script.rs 
warning: crate `Script_5920885be5fa777047cfed70` should have a snake case name
  |
  = note: `#[warn(non_snake_case)]` on by default
  = help: convert the identifier to snake case: `script_5920885be5fa777047cfed70`

warning: 1 warning emitted

test

Cache cleanup

I noticed the rust-script cache exploding very quickly in size... Is there a way to clean it up properly?
I just butchered it manually in my files but I'd rather have a command to remove all older versions and only keep the newest.

Also if a script has not been run for a while it would be nice to have it removed completely (with user flag ofc)

`--help` should print usage info for shebang scripts

The --help right now just lists all the flags. It should also include info on how to write shebang scripts, both the cargo manifest version and the cargo-deps: version. This way I don't need to go to the website to remember how to write these, especially as there's no manpage.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.