如何在macOS上安装Perl模块?

7

这个帖子 perl如何将perl脚本的列表格式系统调用的STDOUT追加到文件中 带来了以下解决方案:use IPC::Run qw( run );。但是,在我的macOS 10.14.6上运行perl 5.18.4时,会出现错误:Can't locate IPC/Run.pm in @INC (you may need to install the IPC::Run module)。因此,遵循最简单的方式安装缺少的Perl模块是什么?,我执行了以下操作

> cpan IPC::Run
<snip: 403 lines later>
Appending installation info to /Users/BNW/perl5/lib/perl5/darwin-thread-multi-2level/perllocal.pod
  TODDR/IPC-Run-20180523.0.tar.gz
  /usr/bin/make install  -- OK

我重新启动了我的MacBookPro电脑。我编辑了我的Perl脚本bosswrap.pl,以开始执行。

#!/usr/bin/perl
use strict; use warnings;
use IPC::Run qw( run );

但是这似乎又引发了之前相同的错误:

> bosswrap.pl
Can't locate IPC/Run.pm in @INC (you may need to install the IPC::Run module) (@INC contains: /sw/lib/perl5/darwin-thread-multi-2level /sw/lib/perl5 /sw/lib/perl5/darwin /Library/Perl/5.18/darwin-thread-multi-2level /Library/Perl/5.18 /Network/Library/Perl/5.18/darwin-thread-multi-2level /Network/Library/Perl/5.18 /Library/Perl/Updates/5.18.4 /System/Library/Perl/5.18/darwin-thread-multi-2level /System/Library/Perl/5.18 /System/Library/Perl/Extras/5.18/darwin-thread-multi-2level /System/Library/Perl/Extras/5.18 .) at /Users/BNW/u/kh/bin/bosswrap.pl line 3.
BEGIN failed--compilation aborted at /Users/BNW/u/kh/bin/bosswrap.pl line 3.

我做错了什么?或者说,我应该怎样做才能让它正常工作?

看起来它被安装在非标准目录中(为了避免需要 root 权限),但 Perl 没有被告知在那里查找模块。set | grep ^PERL; echo 'o conf' | cpan 的输出是什么? - ikegami
简而言之,我认为需要将/Users/BNW/perl5/lib添加到环境变量PERL5LIB中。 - ikegami
@ikegami 显然对于Apple的macOS Perl(在Ventura上经过验证),标准的非sudo [local::lib] PERL5LIB包含路径应该是/Users/USERNAME/perl5/lib/perl5。并且,你观察到的PERL5LIB在运行环境中可能不存在,也被确认会产生问题中所述的错误。很可能cpan首次运行的环境变量,通常会附加到终端资源文件(包括PERL5LIB),在jacob-wegelin的运行场景中不存在。 - marc-medley
6个回答

6

尝试以下操作:

sudo perl -MCPAN -e 'install -force Net::ARP'

1
这也只是 cpan -f Net::ARP。然而,强制安装某些东西并不能使其神奇般地运作。有时问题出在测试上,但在尝试强制安装之前最好了解情况。 - brian d foy

0

0

你需要看哪些代码?我保存了所有的CPAN输出,共412行,可以将它们发布出来。 - Jacob Wegelin
可能是前12行。 - JTS

-1
如何在macOS上安装Perl模块?
通过确保适用的Perl模块已安装通用二进制文件,本地arm64和启用Rosetta的x86_64的macOS机器避免了指令集架构(ISA)冲突。
进行通用二进制Perl模块安装的一种方法如下:
sudo env ARCHFLAGS='-arch arm64 -arch arm64e -arch x86_64' cpan App::cpanminus
sudo env ARCHFLAGS='-arch arm64 -arch arm64e -arch x86_64' cpanm Test2
sudo env ARCHFLAGS='-arch arm64 -arch arm64e -arch x86_64' cpanm Finance::Quote
sudo env ARCHFLAGS='-arch arm64 -arch arm64e -arch x86_64' cpanm JSON::Parse

如果已经安装了非通用二进制安装程序,则需要先卸载该安装程序,因为标准的Perl安装/更新仅检查版本号,而不检查任何底层ISA集。

有关详细信息,请参见如何安装和更新Perl模块为“通用”(x86_64,arm64)?


-1
短答案:OP的提示 `> cpan IPC::Run` 表明这是一个标准的 macOS 用户级别 Perl 模块安装。如果在运行环境中,cpan 首次运行追加到 .zshrc(或等效文件)的标准环境变量不存在,将会出现所述错误。 macOS 用户级别的 cpan IPC::Run 命令可以正常工作,只要满足以下条件:
  • 打开一个新的终端窗口,以便预期的 Perl 环境变量存在
  • 或者将缺失的环境变量行添加到终端资源文件中

.zshrc 添加的行

PATH="/Users/USERNAME/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/Users/USERNAME/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/Users/USERNAME/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/Users/USERNAME/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/Users/USERNAME/perl5"; export PERL_MM_OPT;

检查活动环境

echo $PATH
# /Users/USERNAME/perl5/bin:/usr/local/bin:…
set | grep ^PERL               
# PERL5LIB=/Users/USERNAME/perl5/lib/perl5
# PERL_LOCAL_LIB_ROOT=/Users/USERNAME/perl5
# PERL_MB_OPT='--install_base "/Users/USERNAME/perl5"'
# PERL_MM_OPT='INSTALL_BASE=/Users/USERNAME/perl5'

TL;DR

以下是针对以下问题改写的发现:《如何在苹果的 macOS Perl 中安装和使用 CPAN 模块?》

注意:下面的详细信息是通过重新创建和评估原始问题的错误以及寻求理解我在 Ventura 上使用的 macOS Perl 的 cpan 安装模块时遇到的一些问题而找到并记录的。

苹果的 Pearl 定制

苹果的 Perl(从早期的 Mac OS X 至少到 macOS Ventura 13.4)有定制功能。关于这些定制的信息可以在 perlmacosx 手册页中找到:

Apple的Perl自定义包括:

  • AppendToPathPrependToPath以将路径添加到模块搜索路径(@INC
  • ARCHFLAGS用于构建多个指令集架构

安装位置

cpan的第一次运行将确定CPAN模块安装的基本路径。

cpan IPC::Run
# …
# CPAN.pm requires configuration, but most of it can be done automatically.
# …
# To install modules, you need to configure a local Perl library directory or
# escalate your privileges.  CPAN can help you by bootstrapping the local::lib
# module or by configuring itself to use 'sudo' (if available).  You may also
# resolve this problem manually if you need to customize your setup.

# What approach do you want?  (Choose 'local::lib', 'sudo' or 'manual')

根据提示的选择,生成基本安装路径如下:
  • [local::lib] - Users/USERNAME/Perl5 … 默认和操作者的使用情况。
  • sudo - /Library/Perl
  • manual - /some/user/chosen/path

模块使用

在干净的 macOS Ventura Perl 安装上进行初始的 cpan 运行,包括以下提示问题:"…将其附加到…"

# …
# Appending installation info to /Users/USERNAME/perl5/lib/perl5/darwin-thread-multi-2level/perllocal.pod
# 
# Would you like me to append that to /Users/USERNAME/.zshrc now? [yes] 
# Running install for module 'IPC::Run'
# …

请注意,接受提示的[yes]并不提供关于追加了什么内容或原因的额外信息。很容易忽视这一点。然而,请看看追加了什么内容...。 .zshrc 追加的行
PATH="/Users/USERNAME/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/Users/USERNAME/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/Users/USERNAME/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/Users/USERNAME/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/Users/USERNAME/perl5"; export PERL_MM_OPT;

如果在同一个终端窗口中运行bosswrap.pl(没有更新.zshrc),那么会重新创建OP的错误。
#  ./Build install  -- OK
./bosswrap.pl 
# Can't locate IPC/Run.pm in @INC (you may need to install the IPC::Run module)
# (@INC contains: /Library/Perl/5.30/darwin-thread-multi-2level … 
#  … <snip> …
#  …) at ./bosswrap.pl line 3.
# BEGIN failed--compilation aborted at ./bosswrap.pl line 3.

然而,如果打开一个新的终端窗口,将应用 .zshrc 的更新,那么 bosswrap.pl 就可以无错误地运行。
./bosswrap.pl 
# silent return. no errors.

看起来,通过在运行环境中使用提供的PATHPERL5LIBPERL_LOCAL_LIB_ROOTPERL_MB_OPTPERL_MM_OPT,可以解决OP特定的错误场景。可能只需打开一个新的终端窗口以使附加的值生效。或者,如果最初的cpan“...添加到...`步骤被拒绝|忽略”,可以手动将变量添加到shell资源文件中。

一般来说,如果选择在非标准位置安装Perl模块,Apple提供了全局机制,可以使用AppendToPathPrependToPath来添加@INC搜索路径。

所以,对于macOS(例如Ventura),有两种方法可以将目录添加到运行时包含路径(@INC)中,而不会干扰Perl脚本文件。
  • 环境变量:PERL5LIB
    • 注意需要正确设置PATHPERL_LOCAL_LIB_ROOTPERL_MB_OPTPERL_MM_OPT
  • "/Library/Perl"系统范围内的第三方模块AppendToPath|PrependToPath

然而,如果希望在单个脚本基础上添加@INC搜索路径,则可以将use lib qw(/some/other/path);语句添加到Perl脚本本身。

运行时架构

一般来说,相对于 macOS 可能需要的用于带有启用了 rosetta 的 x86_64 的本机 arm64 机器的二进制文件,CPAN 安装是天真的。这实际上是一台多架构机器。只安装一种 ISA 架构可能会导致运行时冲突,当一个 Perl 应用程序使用 x86_64,而另一个 Perl 应用程序使用 arm64(arm64e)作为两者共同使用的 Perl 二进制模块时。
一些 Perl CPAN 模块将安装二进制的 *.bundle 可执行文件。例如,Financle::Quote 模块安装后会有 5 个 *.bundle 文件。
#MY_PERL_INSTALL="/Library/Perl"
MY_PERL_INSTALL="/Users/USERNAME/Perl5"
find "$MY_PERL_INSTALL" -name "*.bundle"
# /Users/USERNAME/Perl5/lib/perl5/darwin-thread-multi-2level/auto/Test/LeakTrace/LeakTrace.bundle
# /Users/USERNAME/Perl5/lib/perl5/darwin-thread-multi-2level/auto/Date/Simple/Simple.bundle
# /Users/USERNAME/Perl5/lib/perl5/darwin-thread-multi-2level/auto/Sereal/Encoder/Encoder.bundle
# /Users/USERNAME/Perl5/lib/perl5/darwin-thread-multi-2level/auto/Sereal/Decoder/Decoder.bundle
# /Users/USERNAME/Perl5/lib/perl5/darwin-thread-multi-2level/auto/List/SomeUtils/XS/XS.bundle

在Perl模块安装树中添加file命令,以确定是否存在不一致的二进制ISA切片集:

MY_PERL_INSTALL="/Users/USERNAME/Perl5"
find "$MY_PERL_INSTALL" -name "*.bundle" | xargs file

# /Library/Perl/5.30/…/Readonly/XS/XS.bundle: Mach-O universal binary with 3 architectures: [x86_64:Mach-O 64-bit bundle x86_64] [arm64:Mach-O 64-bit bundle arm64] [arm64e:Mach-O 64-bit bundle arm64e]
# ...
# /Library/Perl/5.30/…/Date/Simple/Simple.bundle: Mach-O 64-bit bundle x86_64
# /Library/Perl/5.30/…/Sereal/Encoder/Encoder.bundle: Mach-O 64-bit bundle arm64

Apple的Perl自定义提供了环境变量ARCHFLAGS,以便让Perl安装通用二进制模块。

enter image description here

ARCHFLAGS可以在使用cpan时按如下方式使用:

env ARCHFLAGS='-arch arm64 -arch arm64e -arch x86_64' cpan Test2
env ARCHFLAGS='-arch arm64 -arch arm64e -arch x86_64' cpan Finance::Quote

请注意:如果已经安装了非通用二进制文件,需要先卸载该安装,因为标准的 Perl 安装/更新只会检查版本号,而不会检查任何底层 ISA 二进制切片。
有关通用二进制 Perl 模块的更详细问题和答案,请参阅如何安装和更新“通用”(x86_64、arm64)Perl 模块?

-1

鉴于情况如下:在 macOS 上找出如何重现 OP 相同的错误之后,很可能 OP 的运行环境中没有初始 cpan 运行时通常添加的环境变量。我的发现细节已经记录为答案。致以最诚挚的问候。 - marc-medley
FYI:在弄清楚如何在 macOS 上重新创建 OP 相同的错误后,很可能 OP 的运行环境中没有初始 cpan 运行时通常添加的环境变量。我的发现细节已记录为答案。致以最诚挚的问候。 - undefined
看起来你走了一条绕远路的路径才找到我已经建议过的东西:你必须告诉你的脚本在哪里找到这些模块。 - brian d foy
看起来你走了一个绕远路才找到我已经建议过的方法:你必须告诉你的脚本在哪里找到这些模块。 - undefined
..."走了条绕路啊",是的,同意。Perl不是我主要的编程语言之一。我需要学习和解决许多Perl的概念和问题……这是一次漫长的徒步旅行,为了建立一个整体的理解。 - marc-medley
“...走了一条绕远路的路线...”,是的。同意。Perl并不是我核心语言之一。我需要学习和解决一系列Perl的概念和问题...这是一次漫长的徒步旅行,为了建立一个整体的理解。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接