I am wondering what steps, (such as shebang lines and wrapper scripts) are recommended when creating a CLI application in Raku. I am interested in info both for scripts that will be installed with Zef and those that will be distributed separately.
The docs provide the example frobnicate
program:
# inside "frobnicate.raku"
sub MAIN(Str $file where *.IO.f, Int :$length = 24, Bool :$verbose) { #`(body omitted)}
which I could run with raku frobnicate.raku
– a fine solution for scripts, but not great for a real program.
If I want this to be a bit more of a standard program, I could create a frobnicate
file such as this:
#!/usr/bin/env raku
sub MAIN(Str $file where *.IO.f, Int :$length = 24, Bool :$verbose) { #`(body omitted)}
I can make that file executable with chmod +x
and move it to a directory in my $PATH
; then I can frobnicate with the command frobnicate
. So far, all of this makes perfect sense and is just like any other scripting language.
However, none of this takes advantage of Raku's compilation. As a result, CLI apps that do more processing in MAIN
can get a bit slow (even for generating --help
output). So, the next step is to allow the app to be precomplied, but I'm not quite sure how to do so.
With Zef
When I look at the scripts that I execute after installing a Raku program with Zef, they pretty much all have the form:
#!/usr/bin/env perl6
sub MAIN(:$name, :$auth, :$ver, *@, *%) {
CompUnit::RepositoryRegistry.run-script("frobnicate", :$name, :$auth, :$ver);
}
And, when I check the package's source, this CompUnit::RepositoryRegistry.run-script
line isn't there. So I'm guessing Zef adds it? If so, is there anything I need to do when writing my script to make sure that Zef will use this wrapper and that the wrapper will work?
(This comment was helpful in understanding what was going on, though I still am not sure I 100% get it).
Without Zef
I would like to write scripts that users can run without needing to install them through Zef (though that would be my recommended installation method). Is there some way to use the run-script
method shown above without Zef? Or should I do something like the following, which I`ve also seen:
#!/usr/bin/env raku
use Frobnicate::CLI
(And then move the actual functionality into a Frobnicate/CLI.rakumod
file).
If I go this route, I'll need to instruct users to download both the frobnicate
wrapper script above and the Frobnicate/CLI.rakumod
file, right? (That is, there's no way to do this in a single file, is there?)
Assuming I do need to have my users download two files, where should I have them install the files? frobnicate
needs to go into a directory in their PATH
, but what about Frobnicate/CLI.rakumod
? Does it need to be copied into their Raku module search path (and, if so, what command would show them what that path is)? Or can I modify the frobnicate
wrapper in some way (maybe by changing raku
to raku -Ilib
or something like that?) in a way that would let them install both to directory on their PATH
?
After typing all this out, it strikes me as possible that I'm dramatically over-thinking this. If so, please let me know that as well! In any event, I'd be happy to add a few more details to the relevant section of the docs if I come to understand this a bit better.