如何使用多个版本的 Perl 在 Perl 模块中安装脚本?

Posted

技术标签:

【中文标题】如何使用多个版本的 Perl 在 Perl 模块中安装脚本?【英文标题】:How do I handle installing scripts in Perl modules with multiple versions of Perl? 【发布时间】:2021-03-23 00:20:08 【问题描述】:

我不认为这是一个重复的问题。这专门针对 Perl 模块附带的脚本。

通常,在安装多个 Perl 版本时,您可以将 perl 可执行文件标记为版本号 (perl5.32),这样它们就可以在/whatever/bin 中并排放置。我需要对模块附带的脚本做同样的事情。示例:perltidy。所以:

当我构建 perl 时,我可以在配置中添加一个设置,它会自动 [原文如此] 创建“版本化”脚本名称吗?

或者,当我构建脚本以创建“版本化”脚本名称时,我可以在调用 perl Makefile.PLperl Build.PL 时进行设置吗?

是的,有plenvperlbrew,但我不想在生产端使用它们,但是在我的生产机器上会有一段时间同时存在两个版本。我将随着时间的推移迁移程序;我不会在某一天晚上“大刀阔斧”地切换到新版本。

【问题讨论】:

【参考方案1】:

我在Make links to per-version tools 中写了更多关于此的内容。

我安装了大约 30 个 perls,我手动安装了每个:

$ ./Configure -des -Dprefix=/usr/bin/perls/perl-5.x.y
$ make test install

现在有 /usr/bin/perls/perl-5.x.y/bin/perl 之类的东西。如果我想为此安装模块或脚本,我会使用 cpan:

$ /usr/bin/perls/perl-5.x.y/bin/cpan ...

当您通过普通 Perl 工具链安装时,shebang 行指向安装它的 perl(有关更多信息,请参阅 Perl.com 最近的文章 Bang Bang):

#!/usr/local/perls/perl-5.32.0/bin/perl
    eval 'exec /usr/local/perls/perl-5.32.0/bin/perl -S $0 $1+"$@"'
    if $running_under_some_shell;
#!/usr/local/bin/perl

这充分划分了不同的程序,每个程序都知道应该运行哪个perl

当然,那些长路径太多了,无法输入,所以我有一个程序可以在~/bin 中创建符号链接,这样~/bin/cpan-5.x.y 就会指向它。同一个程序采用它在/usr/bin/perls/perl-5.x.y/bin 中找到的任何程序并创建类似的符号链接。

rhich 是我自己的类似which 的程序,它采用正则表达式:

$ rhich 5.32.0 | head -4
/Users/brian/bin/perls/pod_cover5.32.0 → /usr/local/perls/perl-5.32.0/bin/pod_cover
/Users/brian/bin/perls/ppodchecker5.32.0 → /usr/local/perls/perl-5.32.0/bin/ppodchecker
/Users/brian/bin/perls/prove5.32.0 → /usr/local/perls/perl-5.32.0/bin/prove
/Users/brian/bin/perls/plackup5.32.0 → /usr/local/perls/perl-5.32.0/bin/plackup

除此之外,它还会生成使用 -latest 而不是版本的链接,因此我不必记住我拥有的内容:

$ rhich latest | head -5
/Users/brian/bin/latest_sha1.pl
/Users/brian/bin/perls/perl-latest → /usr/local/perls/perl-5.32.0/bin/perl
/Users/brian/bin/perls/ptar-latest → /usr/local/perls/perl-5.32.0/bin/ptar
/Users/brian/bin/perls/ttree-latest → /usr/local/perls/perl-5.30.1/bin/ttree
/Users/brian/bin/perls/dprofpp-latest → /usr/local/perls/perl-5.14.4/bin/dprofpp

在那里的某个地方,我也只是让裸命令名指向最新的,这是我大部分时间想要的:

/Users/brian/bin/perls/perl → /Users/brian/bin/perls/perl-latest

perltidy

​​>

还有,这是我所有的 perltidy 安装:

$ rhich perltidy
/Users/brian/bin/perls/perltidy5.30.1 → /usr/local/perls/perl-5.30.1/bin/perltidy
/Users/brian/bin/perls/perltidy5.30.0 → /usr/local/perls/perl-5.30.0/bin/perltidy
/Users/brian/bin/perls/perltidy-latest → /usr/local/perls/perl-5.32.0/bin/perltidy
/Users/brian/bin/perls/perltidy5.28.0 → /usr/local/perls/perl-5.28.0/bin/perltidy
/Users/brian/bin/perls/perltidy5.26.1 → /usr/local/perls/perl-5.26.1/bin/perltidy
/Users/brian/bin/perls/perltidy5.30.2 → /usr/local/perls/perl-5.30.2/bin/perltidy
/Users/brian/bin/perls/perltidy5.32.0 → /usr/local/perls/perl-5.32.0/bin/perltidy
/Users/brian/bin/perls/perltidy → /Users/brian/bin/perls/perltidy-latest

【讨论】:

在我发布这个之后,我发现了 INSTALLSITEBIN,Perl 模块应该使用哪些来安装它们的脚本。我决定添加一个处理步骤,在 /usr/local/bin 中创建脚本的“版本化”链接。然后我阅读了这个答案并阅读了关于 rhich 的内容,这应该可以帮助我向我的经理验证是否确实这样做了。别担心,他几乎不是 PHM;他是 CPAN 的作者。 :-) 是的,等你找到解决方案后再回来告诉我们你做了什么。 Re "它还会围绕符号链接进行洗牌,因此您可以“切换”到特定版本。",不,它没有。它只是更改当前 shell 中的 PATH。这些都不会影响脚本,因为脚本的安装程序将硬编码用于安装的perl 的路径,与使用perlbrew 安装的perl 一样多,就像普通的perl 一样。 perlbrew 上的部分是下铺。 $my_last_comment =~ s/当前shell/shells正在加载perlbrew/ 是的,很长时间没有看 perlbrew,所以也许我应该只是 stfu。 :)【参考方案2】:

更新:重新阅读您的问题后,我想我第一次看错了。我将在最后包含我的第一个解释,因为它可能有用。

据我了解,您希望安装/usr/bin/yourapp-1.1,然后当人们升级时,您希望安装/usr/bin/yourapp-1.2

首先,这似乎是一个经过深思熟虑的想法。如果您的脚本依赖于 Your::Module,那么按照正常的 Perl 模块安装,Your::Module 1.2 将替换系统上的 Your::Module 1.1,因此如果 /usr/bin/yourapp-1.1 运行,它将使用 Your:: 运行模块 1.2。 (除非你把它打包,我猜。)

但这当然是可能的。

简单的方法是使用 Makefile.PL 中的 File::Copy 将未版本控制的脚本复制到包含版本号的新文件名,然后让 MakeMaker 执行它的操作。


较早的答案

如果您的脚本包含这样的 shebang:

#!perl

然后 ExtUtils::MakeMaker 将在构建发行版时自动将其重写为指向当前版本的 Perl。

如果您的脚本包括:

#!/usr/bin/env perl

然后它不会被重写,并且脚本将针对运行时在 $PATH 环境变量中找到的任何版本的 perl 运行,这可能不是您想要的。

【讨论】:

> 据我了解,您希望安装 /usr/bin/yourapp-1.1,然后当人们升级时,您希望安装 /usr/bin/yourapp-1.2?不完全是。您的第一个答案更接近我的需要。 :-) 假设 App::Mine 提供脚本 mine.pl。如果我在 Perl 5.16 下安装它,那么我希望安装产生“/usr/bin/mine5.16.pl”。如果我在 Perl 5.32 下安装它,那么我希望安装产生 '/usr/bin/mine5.32.pl'。 @mpersico 然后我会执行我提到的 File::Copy 操作,但将脚本复制到包含 Perl 版本号而不是模块版本号的文件名。 tobyink - 是的,当然。我现在看到我在原始描述中并不清楚。我试图保留多个 Perl 版本。通过添加 Perl 版本,作为一个额外的好处,我可以在一个 Perl 版本下升级模块,同时在另一个版本下保持它的固定。 Alos 了解我这样做是为了安装所有模块,而不仅仅是我正在编写的模块。我不太确定您的 File::Copy 解决方案是否适用,因为 a) 我没有打开我下载的每个模块来修改 Makefile.PL b) 不是每个模块都使用 Makefile.PL;我需要为我找到的每一种 tom-dick-and-harry 安装方法都这样做。我敢肯定 99.999% 是 Makefile.PL 或 Build.PL,但容纳尾部将是 PITA。

以上是关于如何使用多个版本的 Perl 在 Perl 模块中安装脚本?的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何分发预构建的 perl 模块,以及我构建的 perl 版本是啥?

如何找到已安装的 Perl 模块的版本?

如何查看perl cgi.pm的版本

Perl6 如何决定加载哪个版本的模块?

如何管理 Perl 模块依赖项?

在 Perl 中使用多个包使用 JSON::RPC::Server 编写 API 服务器模块