7

The thread perl how can I append STDOUT of list form system call of perl script to a file led to the following solution: use IPC::Run qw( run );. On my macos 10.14.6 running perl 5.18.4, this threw an error: Can't locate IPC/Run.pm in @INC (you may need to install the IPC::Run module). Accordingly, following What's the easiest way to install a missing Perl module?, I did

> 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

and rebooted my MacBookPro. And I edited my perl script, bosswrap.pl, to start

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

but this again throws apparently the same error as before:

> 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.

What am I doing wrong, or rather, how can I get this to work?

Jacob Wegelin
  • 1,304
  • 11
  • 16
  • It looks like it was installed in a non-standard directory (to avoid requiring root), but that Perl wasn't told to look there for modules. What's the output of `set | grep ^PERL; echo 'o conf' | cpan` – ikegami Nov 24 '19 at 00:06
  • In short, I think `/Users/BNW/perl5/lib` needs to be added to env var `PERL5LIB`. – ikegami Nov 24 '19 at 00:15
  • @ikegami Apparently for Apple's macOS Perl (verified on Ventura), the standard non-sudo [local::lib] PERL5LIB include path would be /Users/USERNAME/perl5/lib/perl5. And, your observation that PERL5LIB was likely not present in the runtime env, was also confirmed to produce the error as stated in the question. It's likely that the cpan first-run environment variables which would normally be appended the Terminal resource file (including PERL5LIB) were not present in the jacob-wegelin runtime scenario. – marc-medley Jun 08 '23 at 17:59

4 Answers4

6

try the following :

sudo perl -MCPAN -e 'install -force Net::ARP'
Asmoun
  • 1,417
  • 5
  • 20
  • 53
Baranidharan S
  • 105
  • 1
  • 9
  • 1
    This is also just `cpan -f Net::ARP`. However, force installing something doesn't make it magically work. Sometimes it's the tests that are the problem, but that's something you want to know before trying force. – brian d foy May 30 '23 at 14:01
0

http://triopter.com/archive/how-to-install-perl-modules-on-mac-os-x-in-4-easy-steps/ gives an in-depth tutorial. As far as I can tell some CPAN Config lines may be needed however there is not enough code provided to say that is the cause of the issue. In any event here is the CPAN config code.

$ sudo perl -MCPAN -e shell
perl> o conf init
JTS
  • 41
  • 10
-1

The problem seems to be that you installed the module under your user directory, /Users/BNW/perl5/lib, but you did not include that path in @INC array that Perl uses to find libraries.

One way to do this is add the installation path to @INC through use lib in your bosswrap.pl program:

use lib qw(/Users/BNW/perl5/lib/perl5);

See also:

brian d foy
  • 129,424
  • 31
  • 207
  • 592
  • As FYI: After figuring out how to recreate the the OP's same error on macOS, it's likely that the environment variables normally added by an initial cpan run on macOS had not been present in the OP's runtime environment. My finding details are documented as an answer. Best regards. – marc-medley Jun 07 '23 at 23:51
  • It looks like you took the long route to get to what I already recommended: you have to tell your script where to find the modules. – brian d foy Jun 08 '23 at 03:06
  • "… took the long route …", yes. Agreed. Perl has not been one of my core languages. I was having a range of Perls concepts to learn and issues to sort out … a long hike to map out an overall understanding. – marc-medley Jun 08 '23 at 03:13
-1

Short answer: The OP's prompt > cpan IPC::Run indicates a standard macOS user level Perl module install. The stated error will occur if the standard environment variables appended to .zshrc (or equivalent) by a cpan first run .are.not. present in the runtime environment.

A macOS user level cpan IPC::Run command can work OK, provided that …

  • a new Terminal window is opened so that the expected Perl environment variables are present
  • or, the missing environment variable lines are added to the Terminal resource file

.zshrc added lines

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;

check active environment

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

Below are some findings for the question paraphrased as: "How to install and use CPAN modules with Apple's macOS Perl?"

Note: The details below were found & documented as a combination of both recreating & evaluating the OP's error, and of seeking to understand some issues I was also having with the macOS Perl cpan installed modules on Ventura.

Apple's Pearl Customization

Apple's Perl (from early Mac OS X to at least macOS Ventura 13.4) has customizations. Information on these customizations is provided in the perlmacosx manpage:

Apple's Perl customizations include:

  • AppendToPath and PrependToPath to add paths to the module search path (@INC)
  • ARCHFLAGS to build for multiple instruction set architectures

Install Location

The first run of cpan will determine the base path for CPAN module installations.

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')

Resulting base install path, according to the prompted choice:

  • [local::lib] - Users/USERNAME/Perl5 … default and OP's use case.
  • sudo - /Library/Perl
  • manual - /some/user/chosen/path

Module Use

An initial cpan run (on clean a macOS Ventura Perl installation) includes the following "…append that to…" prompted question:

# …
# 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'
# …

Notice that accepting the prompted [yes] provides not additional information about what was appended or why. Easy to not pay much attention to this. Yet, look at what was appended…

.zshrc appended lines

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;

If bosswrap.pl is run in the same terminal window (without the .zshrc updates), then the OP's error is recreated:

#  ./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.

However, if a new terminal window is opened, which will have the .zshrc updates applied, then bosswrap.pl runs without error.

./bosswrap.pl 
# silent return. no errors.

It appears that the OP's particular error scenario can be resolved by use of the provided PATH, PERL5LIB, PERL_LOCAL_LIB_ROOT, PERL_MB_OPT, and PERL_MM_OPT in the runtime environment. Possibly by simply opening a new Terminal window for the appended values to take effect. Or, by manually adding the variables to the shell resource file, if the initial cpan '… append that to …` step had been declined|missed.

In general, if one chooses to install Perl modules in a non-standard location, then Apple provides a global mechanism to add @INC search paths with AppendToPath and PrependToPath.

So, for macOS e.g. Ventura, there are two approaches for adding directories to the runtime include path (@INC) without intrusion into the Perl script files.

  • Environment variable: PERL5LIB
    • note that PATH, PERL_LOCAL_LIB_ROOT, PERL_MB_OPT, PERL_MM_OPT also need to be properyly set.
  • "/Library/Perl" AppendToPath|PrependToPath system wide 3rd party modules

However, if one wishes to add @INC search paths on an individual script basis, then the use lib qw(/some/other/path); statement can be added to the Perl script itself.

Runtime Architecture

In general, a CPAN install is naive relative to the binaries that macOS might need for a native arm64 machine with rosetta x86_64 enabled. This is effectively a multi-architecture machine. An only-one-ISA-architecture install can result in runtime conflicts when one Perl application uses x86_64 and another Perl application uses arm64 (arm64e) for a Perl binary module common to both.

Some Perl CPAN Modules will install binary *.bundle executables. For example, a Financle::Quote module install will end up with 5 *.bundle files.

#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

Add the file command to determine if the Perl module install tree has an inconsistent set of binary ISA slices:

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's Perl customization provides the environment variable ARCHFLAGS to allow Perl to install Universal Binary modules.

enter image description here

The ARCHFLAGS can be used with cpan as follows:

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

Note: If a non-universal binary install is already in place, that install will need to be uninstalled first because standard Perl install/update only checks the version number and not any underlaying ISA binary slices.

See Install & update a Perl module as "universal" (x86_64, arm64)? for more detailed Q&A on Universal Binary Perl modules.

marc-medley
  • 8,931
  • 5
  • 60
  • 66