如何为 Raku CLI 使用包装器脚本
How to use a wrapper script for a Raku CLI
我想知道在 Raku 中创建 CLI 应用程序时推荐使用哪些步骤(例如 shebang 行和包装器脚本)。我对将与 Zef 一起安装的脚本和将单独分发的脚本的信息感兴趣。
文档提供了示例 frobnicate
程序:
# inside "frobnicate.raku"
sub MAIN(Str $file where *.IO.f, Int :$length = 24, Bool :$verbose) { #`(body omitted)}
我可以 运行 和 raku frobnicate.raku
– 脚本的一个很好的解决方案,但对真正的程序来说不是很好。
如果我想让它更像一个标准程序,我可以创建一个 frobnicate
文件,例如:
#!/usr/bin/env raku
sub MAIN(Str $file where *.IO.f, Int :$length = 24, Bool :$verbose) { #`(body omitted)}
我可以使用 chmod +x
使该文件可执行并将其移动到我的 $PATH
中的目录;然后我可以使用命令 frobnicate
进行 frobnicate。到目前为止,所有这些都非常有意义,就像任何其他脚本语言一样。
然而,none 这利用了 Raku 的编译。因此,在 MAIN
中执行更多处理的 CLI 应用程序可能会变得有点慢(即使生成 --help
输出)。所以,下一步是让应用程序被预编译,但我不太确定如何做。
有 Zef
当我查看在使用 Zef 安装 Raku 程序后执行的脚本时,它们几乎都具有以下形式:
#!/usr/bin/env perl6
sub MAIN(:$name, :$auth, :$ver, *@, *%) {
CompUnit::RepositoryRegistry.run-script("frobnicate", :$name, :$auth, :$ver);
}
而且,当我检查包的来源时,这条 CompUnit::RepositoryRegistry.run-script
行不存在。所以我猜 Zef 添加了它?如果是这样,在编写脚本时我需要做些什么来确保 Zef 将使用此包装器并且该包装器可以正常工作吗?
(This comment 有助于理解发生了什么,尽管我仍然不确定我是否 100% 明白了)。
没有 Zef
我想编写用户可以 运行 无需 通过 Zef 安装的脚本(尽管这是我推荐的安装方法)。有没有办法在没有 Zef 的情况下使用上面显示的 run-script
方法?或者我应该做类似下面的事情,我也看到了:
#!/usr/bin/env raku
use Frobnicate::CLI
(然后将实际功能移动到 Frobnicate/CLI.rakumod
文件中)。
如果我走这条路,我需要指导用户下载上面的 frobnicate
包装脚本和 Frobnicate/CLI.rakumod
文件,对吗? (也就是说,没有办法在单个文件中执行此操作,是吗?)
假设我确实需要让我的用户下载两个文件,我应该让他们在哪里安装文件? frobnicate
需要进入他们的 PATH
目录,但是 Frobnicate/CLI.rakumod
呢?是否需要将其复制到他们的 Raku 模块搜索路径中(如果需要,什么命令会向他们显示该路径是什么)?或者我可以以某种方式修改 frobnicate
包装器(可能通过将 raku
更改为 raku -Ilib
或类似的东西吗?)以某种方式让他们将两者都安装到他们 [= 的目录中28=]?
在输入所有这些内容后,我觉得我可能想得太多了。如果是这样,请也让我知道!无论如何,如果我能更好地理解这一点,我很乐意在文档的相关部分添加更多细节。
So I'm guessing Zef adds it?
CompUnit::Repository::Installation adds it
它为什么在那里?一个原因是因为一些包装器需要管理同名的 bin 脚本,如果它们在同一目录中,否则会发生冲突。
Is there some way to use the run-script method shown above without Zef?
run-script is for CompUnit::Repository::Installation only -- 如果您不安装模块,那么 run-script
不会有兴趣
Assuming I do need to have my users download two files, where should I have them install the files?
好吧,recommended/idiomatic 方法是使用核心 raku 功能来安装东西(即使用 zef)。否则你应该放一些代码的地方要么 a) 无关紧要要么 b) 将 mos 完全依赖于你的环境,什么是你的 os 惯用的,等等
Does it need to be copied into their Raku module search path (and, if so, what command would show them what that path is)
echo $RAKULIB
应该足以在 most 个案例中显示模块搜索路径,尤其是当他们对安装路径的位置不感兴趣时。因此,您可以指示用户设置例如RAKULIB=$FROB_LIB_DIR
如果您希望它们能够 运行 您的脚本而无需通过 raku -I../ frobnicate
手动指定它,则指向您的库所在的位置(因此它们不会将代码复制到任何特殊的地方,它们只是指向他们的任何地方,例如克隆你的回购协议)。使用 $PATH
.
也是如此
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?
我建议不要根据 $PATH
中的某些值安装东西。指导用户设置 $PATH
,不要安装东西到 $PATH
.
从技术上讲,您可以将 use lib '../'
添加到您的脚本中,但是在您还希望用户正常安装的脚本中使用 use lib
并不理想,因为它添加了一个未使用的、可能被劫持的模块搜索从这样的安装中 运行 时的路径。
如果你想让你的代码预编译,那么我建议把它放在一个模块中,并指导你的用户,如果他们不打算安装它,通过 raku -I../ ./frobnicate
调用它使用 basis 或 export RAKULIB="$FROB_LIB_DIR,$RAKULIB"
后跟 ./frobnicate
之类的东西以获得更永久的东西。或者,如果有人最终实现了脚本的预编译,那么您可以只使用单文件方法。
关于这个主题的一些评论。
我认为使用 zef
是最佳选择,因为 zef
也会加载依赖项。能够在不使用其他模块的情况下编写 Raku 程序已经很不寻常了,我希望随着更多 Raku 模块的开发,这种情况会变得更加不寻常。
我忘记了我在我的系统上安装了哪些模块,并包含在一个程序中。通过在 META6.json
中指定所有内容,然后在 运行 zef test .
中指定,确保其他人可以下载该模块的机会得到提高。实际上,我发现确保这一点的最佳方法是创建一个 docker 文件并尝试在 docker image/container 中安装一个新模块 - 但这是另一个话题。
我发现(对于 Linux,我无法评论 Windows)如果我:
- 在 Raku 中编写一个可执行文件(见下文),我们称之为
MyWonder
,
- 将它放在
<distribution>/bin
文件夹中,
- 给它 +x 权限,并且
- 在发行版的根
META6.json
文件中指定它
- (发布发行版)
然后当zef
安装发行版时,MyWonder
将在命令行上工作(假设zef
本身在命令行上工作,这意味着PATH
包含zef 的目录)。
调用旨在在命令行上使用或由桌面调用的程序的最佳(对我而言)方式是:
- 将以下内容放入
MyWonder
文件(无需扩展名)
use v6.d;
use MyWonderLife;
- 将所有功能放入
MyWonderLife.rakumod
- 确保
MyWonderLife.rakumod
中至少有一个sub MAIN
- 在
META6.json
文件中指定 MyWonderLife
(这样可以非常灵活地选择将实际 MyWonderLife.rakummod
文件放在哪个目录下;它不必是 lib/
)
- 为分发创建一个简单的测试
t/basic.rakutest
,只有测试 use-ok 'MyWonderLife;
这个配方意味着所有的功能都是由 zef 预编译的,所以当用户调用可执行文件时,会有更快的响应。使用 Raku 时最慢的部分是编译程序。通过使用 zef 安装,这将在安装过程中完成一次。所有语言的程序安装起来都很慢,因此 Raku 程序不会让用户想知道在使用它的那一刻发生了什么。
其次,可以使用几个multi sub MAIN
来处理各种调用情况,并使用现在可以处理的命令行选项范围。虽然这在任何脚本中显然都是可能的,但将它们全部放在 .rakumod
文件中似乎(对我来说)更自然。
我发现在安装模块时进行大量测试是一件很痛苦的事情,所以我开始将大部分开发和维护测试转移到 xt/
并且只在 t/
.
最后,有了这个秘诀(假设您在 META6.json
文件中为发行版指定了名称 MyWonderLife,MyWonder
的安装说明,假设可以调用程序而不用参数很简单:
使用zef安装MyWonderLife,例如
zef install MyWonderLife
并在命令行中使用它,如下所示:
MyWonder
我想知道在 Raku 中创建 CLI 应用程序时推荐使用哪些步骤(例如 shebang 行和包装器脚本)。我对将与 Zef 一起安装的脚本和将单独分发的脚本的信息感兴趣。
文档提供了示例 frobnicate
程序:
# inside "frobnicate.raku"
sub MAIN(Str $file where *.IO.f, Int :$length = 24, Bool :$verbose) { #`(body omitted)}
我可以 运行 和 raku frobnicate.raku
– 脚本的一个很好的解决方案,但对真正的程序来说不是很好。
如果我想让它更像一个标准程序,我可以创建一个 frobnicate
文件,例如:
#!/usr/bin/env raku
sub MAIN(Str $file where *.IO.f, Int :$length = 24, Bool :$verbose) { #`(body omitted)}
我可以使用 chmod +x
使该文件可执行并将其移动到我的 $PATH
中的目录;然后我可以使用命令 frobnicate
进行 frobnicate。到目前为止,所有这些都非常有意义,就像任何其他脚本语言一样。
然而,none 这利用了 Raku 的编译。因此,在 MAIN
中执行更多处理的 CLI 应用程序可能会变得有点慢(即使生成 --help
输出)。所以,下一步是让应用程序被预编译,但我不太确定如何做。
有 Zef
当我查看在使用 Zef 安装 Raku 程序后执行的脚本时,它们几乎都具有以下形式:
#!/usr/bin/env perl6
sub MAIN(:$name, :$auth, :$ver, *@, *%) {
CompUnit::RepositoryRegistry.run-script("frobnicate", :$name, :$auth, :$ver);
}
而且,当我检查包的来源时,这条 CompUnit::RepositoryRegistry.run-script
行不存在。所以我猜 Zef 添加了它?如果是这样,在编写脚本时我需要做些什么来确保 Zef 将使用此包装器并且该包装器可以正常工作吗?
(This comment 有助于理解发生了什么,尽管我仍然不确定我是否 100% 明白了)。
没有 Zef
我想编写用户可以 运行 无需 通过 Zef 安装的脚本(尽管这是我推荐的安装方法)。有没有办法在没有 Zef 的情况下使用上面显示的 run-script
方法?或者我应该做类似下面的事情,我也看到了:
#!/usr/bin/env raku
use Frobnicate::CLI
(然后将实际功能移动到 Frobnicate/CLI.rakumod
文件中)。
如果我走这条路,我需要指导用户下载上面的 frobnicate
包装脚本和 Frobnicate/CLI.rakumod
文件,对吗? (也就是说,没有办法在单个文件中执行此操作,是吗?)
假设我确实需要让我的用户下载两个文件,我应该让他们在哪里安装文件? frobnicate
需要进入他们的 PATH
目录,但是 Frobnicate/CLI.rakumod
呢?是否需要将其复制到他们的 Raku 模块搜索路径中(如果需要,什么命令会向他们显示该路径是什么)?或者我可以以某种方式修改 frobnicate
包装器(可能通过将 raku
更改为 raku -Ilib
或类似的东西吗?)以某种方式让他们将两者都安装到他们 [= 的目录中28=]?
在输入所有这些内容后,我觉得我可能想得太多了。如果是这样,请也让我知道!无论如何,如果我能更好地理解这一点,我很乐意在文档的相关部分添加更多细节。
So I'm guessing Zef adds it?
CompUnit::Repository::Installation adds it
它为什么在那里?一个原因是因为一些包装器需要管理同名的 bin 脚本,如果它们在同一目录中,否则会发生冲突。
Is there some way to use the run-script method shown above without Zef?
run-script is for CompUnit::Repository::Installation only -- 如果您不安装模块,那么 run-script
不会有兴趣
Assuming I do need to have my users download two files, where should I have them install the files?
好吧,recommended/idiomatic 方法是使用核心 raku 功能来安装东西(即使用 zef)。否则你应该放一些代码的地方要么 a) 无关紧要要么 b) 将 mos 完全依赖于你的环境,什么是你的 os 惯用的,等等
Does it need to be copied into their Raku module search path (and, if so, what command would show them what that path is)
echo $RAKULIB
应该足以在 most 个案例中显示模块搜索路径,尤其是当他们对安装路径的位置不感兴趣时。因此,您可以指示用户设置例如RAKULIB=$FROB_LIB_DIR
如果您希望它们能够 运行 您的脚本而无需通过 raku -I../ frobnicate
手动指定它,则指向您的库所在的位置(因此它们不会将代码复制到任何特殊的地方,它们只是指向他们的任何地方,例如克隆你的回购协议)。使用 $PATH
.
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?
我建议不要根据 $PATH
中的某些值安装东西。指导用户设置 $PATH
,不要安装东西到 $PATH
.
从技术上讲,您可以将 use lib '../'
添加到您的脚本中,但是在您还希望用户正常安装的脚本中使用 use lib
并不理想,因为它添加了一个未使用的、可能被劫持的模块搜索从这样的安装中 运行 时的路径。
如果你想让你的代码预编译,那么我建议把它放在一个模块中,并指导你的用户,如果他们不打算安装它,通过 raku -I../ ./frobnicate
调用它使用 basis 或 export RAKULIB="$FROB_LIB_DIR,$RAKULIB"
后跟 ./frobnicate
之类的东西以获得更永久的东西。或者,如果有人最终实现了脚本的预编译,那么您可以只使用单文件方法。
关于这个主题的一些评论。
我认为使用
zef
是最佳选择,因为zef
也会加载依赖项。能够在不使用其他模块的情况下编写 Raku 程序已经很不寻常了,我希望随着更多 Raku 模块的开发,这种情况会变得更加不寻常。我忘记了我在我的系统上安装了哪些模块,并包含在一个程序中。通过在
META6.json
中指定所有内容,然后在 运行zef test .
中指定,确保其他人可以下载该模块的机会得到提高。实际上,我发现确保这一点的最佳方法是创建一个 docker 文件并尝试在 docker image/container 中安装一个新模块 - 但这是另一个话题。我发现(对于 Linux,我无法评论 Windows)如果我:
- 在 Raku 中编写一个可执行文件(见下文),我们称之为
MyWonder
, - 将它放在
<distribution>/bin
文件夹中, - 给它 +x 权限,并且
- 在发行版的根
META6.json
文件中指定它 - (发布发行版)
然后当
zef
安装发行版时,MyWonder
将在命令行上工作(假设zef
本身在命令行上工作,这意味着PATH
包含zef 的目录)。- 在 Raku 中编写一个可执行文件(见下文),我们称之为
调用旨在在命令行上使用或由桌面调用的程序的最佳(对我而言)方式是:
- 将以下内容放入
MyWonder
文件(无需扩展名)
use v6.d; use MyWonderLife;
- 将所有功能放入
MyWonderLife.rakumod
- 确保
MyWonderLife.rakumod
中至少有一个 - 在
META6.json
文件中指定MyWonderLife
(这样可以非常灵活地选择将实际MyWonderLife.rakummod
文件放在哪个目录下;它不必是lib/
) - 为分发创建一个简单的测试
t/basic.rakutest
,只有测试use-ok 'MyWonderLife;
sub MAIN
这个配方意味着所有的功能都是由 zef 预编译的,所以当用户调用可执行文件时,会有更快的响应。使用 Raku 时最慢的部分是编译程序。通过使用 zef 安装,这将在安装过程中完成一次。所有语言的程序安装起来都很慢,因此 Raku 程序不会让用户想知道在使用它的那一刻发生了什么。
其次,可以使用几个
multi sub MAIN
来处理各种调用情况,并使用现在可以处理的命令行选项范围。虽然这在任何脚本中显然都是可能的,但将它们全部放在.rakumod
文件中似乎(对我来说)更自然。我发现在安装模块时进行大量测试是一件很痛苦的事情,所以我开始将大部分开发和维护测试转移到
xt/
并且只在t/
.最后,有了这个秘诀(假设您在
META6.json
文件中为发行版指定了名称 MyWonderLife,MyWonder
的安装说明,假设可以调用程序而不用参数很简单:使用zef安装MyWonderLife,例如
zef install MyWonderLife
并在命令行中使用它,如下所示:
MyWonder
- 将以下内容放入