RFC: cargo-script by epage · Pull Request #3502 · rust-lang/rfcs · GitHub
source link: https://github.com/rust-lang/rfcs/pull/3502
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
RFC: cargo-script #3502
Conversation
eRFC #3424 was previously approved without any direction on syntax or behavior having been decided. This RFC is to finalize the decisions made through the implementation to prepare the way for stabilization as we work through the remaining tasks in rust-lang/cargo#12207
#3503 covers the T-lang side of this conversation
Example:
#!/usr/bin/env cargo
```cargo
[dependencies]
clap = { version = "4.2", features = ["derive"] }
```
use clap::Parser;
#[derive(Parser, Debug)]
#[clap(version)]
struct Args {
#[clap(short, long, help = "Path to config")]
config: Option<std::path::PathBuf>,
}
fn main() {
let args = Args::parse();
println!("{:?}", args);
}
$ ./prog --config file.toml
Args { config: Some("file.toml") }
Note: most of this is available behind -Zscript
(see rust-lang/cargo#12207 for limitations). Support for the code-fence frontmatter was added in rust-lang/cargo#12681 and it may be a couple of days before cargo's submodule in rust-lang/rust gets updated and built into a nightly.
added the T-cargo Relevant to the cargo subteam, which will review and decide on the RFC. label
This comment was marked as resolved.
Outdated
This RFC adds support for single-file bin packages in cargo. |
||
Single-file bin packages are `.rs` files with an embedded manifest and a |
||
`main`. |
||
These will be accepted with just like `Cargo.toml` files with |
Contributor
Author
"These will be accepted with just like Cargo.toml files" doesn't read right.
I've moved this thread to the context to make it easier to follow.
Could you clarify why you feel this isn't right?
"This RFC adds support for single-file bin packages in cargo. Single-file bin packages are .rs files with an embedded manifest and a main. cargo will be modified to accept cargo .rs as a shortcut to cargo run --manifest-path .rs; this allows placing cargo in a #! line for directly running these files."
Above I've deleted the 3rd sentence. The above paragraph communicates clearly to me the goal of being able to type cargo myfile.rs
and have it do something useful. I have no idea what the 3rd sentence is trying to add. I suspect it makes sense only if you are aware of some cargo internal details. Specifically the phrase "with just like X" makes no sense.
Contributor
Author
I've pushed a change that tries to clarify that sentence:
These files will be accepted by cargo commands as
--manifest-path
just likeCargo.toml
files.
Removing things isn't always the best solution when they aren't clear. This isn't focused on some kind of cargo internals but core aspects of how you interact with it. This is saying that these files are interchangeable with Cargo.toml
and you can run commands like cargo test --manifest-path foo.rs
.
Show resolved
Outdated
3. third-party commands |
||
To allow the xor, we enforce that |
||
- manifests must be passed in as `Cargo.toml`, `foo.rs`, or have a `/` in them |
And may not have a .
in the filename unless they end in .rs
:
> cat test.hello
#!/usr/bin/env -S cargo -Zscript
fn main() {
println!("hello world");
}
> ./test.hello
error: the manifest-path must be a path to a Cargo.toml file
(assuming the current implementation has the intended semantics here)
Contributor
Author
It says it must be foo.rs
. I've clarified that by shifting from an example to saying "with a .rs
extension".
Member
It still reads to me as if ‘./hello.test‘ would be allowed because it matches the third clause, but it's not because only extensionless filenames are checked for ‘/‘. (OT: fun, they seem to have disabled backticks in the iPad keyboard...)
Contributor
Author
I see. This is specifically referring to disambiguating cargo foo
.
When not on mobile, ill need to check if there is another place where we talk about how to parse the file.
Contributor
Author
a4763f1 updated the section on this matching the current implementation in cargo.
Contributor
The frontmatter syntax wouldn't need to be added to Rust's grammar, correct? In other words, the frontmatter parsing would be a preprocessing stage solely within Cargo, which would strip out the frontmatter before passing it to rustc? |
Member
I think it should be forbidden to publish a script crate without an edition specified. Otherwise we're inevitably looking at a crate that builds when it's published and fails to build later on. |
Contributor
Author
This is what cargo master is doing but
|
Contributor
Author
Publish is out of scope for this RFC. There are other aspects of the design that will play into this that a conversation will need to consider. For example, I expect it to turn it into a mult-file package which will require setting the edition. |
Member
I now see that note towards the top. It was the mention of |
Contributor
Does the "but" here indicate that the goal would be to get this syntax into Rust's grammar? If so, then I'd like to consider the alternative of stuffing this data into comments rather than introducing new syntax. |
Example: |
||
````rust |
||
#!/usr/bin/env cargo |
||
```cargo |
cargo
has been specified in the shebang above already. Why does the user need to specify it twice? It could just allow a naked ``` fence instead (at least if a shebang is present). We know that we are in a cargo-script file in that instance, so we have the freedom to set a "default" case for what to do with fences that have no specifier.
IMO defaulting them to the manifest does not paint us in a corner while saving us character overhead.
Contributor
Author
This is more of a #3503 question. I have it noted as a future possibility to make cargo
the default (forgot to put that in originally). We need to positively identify the frontmatter format. We can make cargo
the default but we wanted to start with the more strict syntax and loosen it over time as we can't go back the other direction. As for inferring it from the shebang ... I'm trying to avoid being in the business of parsing shebangs (there is a stackoverflow about what perl does for this)
Specifying it leaves us much more room for future expansion, such as embedding other associated files or serving as frontmatter for other purposes. And it will make the job of syntax highlighters much easier.
If we want less appearance of redundancy, at the expense of more characters, we could use manifest
or similar. But that doesn't seem worth it.
Member
The start choice tends to stick around. In response to my suggestion in rust-lang/cargo#12301 , I have seen concerns that it's an unfamiliar way of specifying the edition. compare it to the PR from when the edition mechanism was introduced, there one of the comments against was into a similar direction as the reason you give why cargo
defaulting is now rejected: that we don't know if we want to make 2018-pre
a thing or not. Not that I agree with them but a similar effect might occur if we require the cargo specifier to be present.
Regarding whether it should be discussed in #3503 or not, IMO that RFC should not be as restricted to precisely what cargo needs, but be more generic. Ideally when we add support for non manifest embeddings, we shouldn't have to make another lang RFC but handle it wholly inside cargo-script.
Contributor
Author
Ideally when we add support for non manifest embeddings, we shouldn't have to make another lang RFC
i doubt we'd need an RFC; likely a change proposal would do.
Contributor
Author
#3503 is the RFC for the syntax, as referred to in the PR description and in the embedding syntax section of rationale. This solution was what we came up with in discussions with a subset of the cargo team, rust educators, and the language team. It was started and finished on zulip with the middle being handled at RustConf. |
Ah, yes, I missed some sections when removing publish support from the RFC. |
Did we can If I have more than one cargo script and most of them have common functions/structs/enums/types or traits, it will be more convenient if I can put them into a separate cargo script that doesn't have necessary have a main function and it just defines these common things and export them as pubic items, so I can I think that we can't use the |
Contributor
Author
At this point you should either
|
Comment on lines
+113 to +117
### Creating a New Package |
||
*(Adapted from [the cargo book](https://doc.rust-lang.org/cargo/guide/creating-a-new-project.html))* |
||
To start a new [package][def-package] with Cargo, create a file named `hello_world.rs`: |
on first glance I find it confusing to call this a "package"
the def-package
link says:
A package is a collection of source files and a Cargo.toml manifest file which describes the package.
granted "a collection of source files" includes just having a single source file, but I still find this a bit confusing. IMHO it would be better to keep the term "script" for this and have "packages" refer to real packages as we've had them up to this point.
Contributor
Author
In other places, I refer to it as a "single file package" and within the context of cargo concepts and literature, these are a form of a package. While we might find places we want to use a term like "script" for these (which I personally am hesitant on, only using it for historical connection to cargo-script
), we shying away from calling these "packages" could end up making things more confusing.
Granted, this gets into whether a looser or more strict term is appropriate when we finally document this and I think that is something to work out over time and likely will evolve.
Show resolved
Outdated Show resolved
Outdated Show resolved
Outdated Show resolved
Questions |
||
- Should we do this implicitly with the `.rs` extension? |
||
- If we have a flag, what should we name it? |
I'd go with --script
, though I'm not sure if cargo new
really needs to support it if the goal is to be as boilerplate-free as possible
Contributor
Author
I'd go with --script,
Thats something we can work out if/when we get to this. Personally, I've not liked tying the connotation of this feature to the term "script".
though I'm not sure if cargo new really needs to support it if the goal is to be as boilerplate-free as possible
I originally held off on cargo new
to help drive the boiler plate to a minimum. I do admit it can be annoying to write out the shebang and set the executable bit; I tend to copy/paste files (though I also tend to share dependencies).
A single-file package may only be a `[bin]` or a `[lib]` and not both. |
||
We would support depending on these, publishing them, etc. |
publishing them means that the packages would be published without readme and license files and most likely other metadata though, so I'm a bit hesitant regarding this...
Contributor
Author
As this is a future possibility, this is more helpful to add flavor / context for discussions and decisions. We can work those issues out if/when we come to this.
Outdated Show resolved
Outdated Show resolved
Comment on lines
+1103 to +1104
- We would need to decide what to do for lockfiles and `stdin` (another future possibility) without conflicting |
||
with parallel runs |
the current plan is apparently to use a hash of the file path, but that would also be difficult for stdin
. would it make sense to hash the file content instead?
Contributor
Author
Yes, that is a possibility As this is a future possibility, the point is more to highlight the idea for us to include in consideration. I don't think we need to work out all the details at this time.
In case people find it of interest, the Python community has a parallel effort to this with two competing solutions and Microsoft paid for some user interviews to be done. Maybe I overlooked something but unfortunately there wasn't much that seemed relevant to us as it seemed more focused on the differences in formats inside of the frontmatter and is more akin to manifest subset vs |
Thank you for your diligence and patience to take on so many points of view. |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
No one assigned
Status: Unreviewed
No milestone
Successfully merging this pull request may close these issues.
None yet
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK