--- name: Installing and finding modules --- # Installing, and finding what you installed ```{index} single: --cpan; arguments ``` ## The command Everything after `--cpan` goes to the CPAN client, so any option of the `cpan` command you already know still works: `-T` to skip the tests, `-f` to force an install. ```bash pperl --cpan Text::CSV pperl --cpan Plack Starman pperl --cpan -T Try::Tiny ``` ```{index} single: --cpan; git repository ``` Besides module names, `--cpan` takes a git repository: a URL that starts with `git:` or ends in `.git`. It is cloned and installed from the clone. Append `@` and a branch, tag or commit to install that revision. ```bash pperl --cpan https://github.com/example/Some-Dist.git pperl --cpan https://github.com/example/Some-Dist.git@v1.2 ``` With nothing to install, it says so rather than guessing: ```bash pperl --cpan # pperl: --cpan: nothing to install: pperl --cpan Module::Name [...] ``` ```{index} single: PPERL_HOME single: --cpan; install location single: --cpan; --system ``` ## Where it goes Modules land in a pperl-owned tree, never in a perl5 one. The base is `$PPERL_HOME`, or `~/.pperl` if that is unset: ```text ~/.pperl/ ├── lib/perl5/ <- the modules └── cpan/ <- the installer's downloads and builds ``` `--cpan --system` writes to `/usr/local/share/pperl` instead, for a machine-wide install. That path needs the privileges you would expect. Keeping the tree separate is deliberate. A machine commonly has both pperl and a real perl5, and a module built for one has no business being found by the other. ```{index} single: PPERL5LIB single: PERL5LIB; vs PPERL5LIB single: @INC; order ``` ## Making pperl see it An install does not put itself on the search path. The last line of a successful run tells you what to set: ```bash pperl --cpan Text::CSV # pperl: installed into /home/you/.pperl/lib/perl5 # pperl: add it to your path with PPERL5LIB=/home/you/.pperl/lib/perl5 ``` `PPERL5LIB` is the pperl-private twin of `PERL5LIB`: same syntax, colon-separated, but read **only** by pperl. Put it in your shell profile and be done: ```bash export PPERL5LIB="$HOME/.pperl/lib/perl5" ``` It is honoured ahead of `PERL5LIB` and ahead of every system tree, so a module you installed for pperl outranks a same-named copy belonging to the host perl. You can see the effect directly: ```bash pperl -e 'print "$_\n" for @INC' # /usr/share/perl5/site_perl # /usr/lib/perl5/5.42/site_perl # ... PPERL5LIB=/home/you/.pperl/lib/perl5 pperl -e 'print "$_\n" for @INC' # /home/you/.pperl/lib/perl5 <- first # /usr/share/perl5/site_perl # ... ``` Why a separate variable rather than reusing `PERL5LIB`: on a machine running both interpreters, `PERL5LIB` is usually already pointing at the host perl's trees. Overloading it would force you to choose between the two. Both are read, `PPERL5LIB` first. ```{index} single: architecture directory single: @INC; system trees ``` ## Why pperl reads the system trees at all pperl searches the host perl's directories because a pure-Perl module found there runs perfectly well under pperl. That is free inventory and there is no reason to refuse it. What pperl does **not** search is any architecture directory. Those hold compiled extensions, which pperl cannot load. This matters more than it sounds, and [the no-XS rule](no-xs) explains where it bites. ```{index} single: --cpan; offline install single: PERL_MM_USE_DEFAULT single: NONINTERACTIVE_TESTING ``` ## Installing without a network A distribution archive or an unpacked directory on disk installs without a download of its own. Name a directory with a leading `./` or `/`, so that it cannot be taken for a module name: ```bash pperl --cpan ./Some-Dist-1.23.tar.gz pperl --cpan ~/src/Some-Dist ``` The client still fetches the CPAN index on its first run, and any dependency that is not installed yet. Tests run non-interactively: `PERL_MM_USE_DEFAULT` and `NONINTERACTIVE_TESTING` are both set, so a distribution that would otherwise stop to ask a question takes its own default instead of hanging.