Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

The missing link between "you may need to install the module" and "distribution installed" application is running!

by Anonymous Monk
on Oct 24, 2019 at 11:57 UTC ( #11107929=perlmeditation: print w/replies, xml ) Need Help??

You may try a perl app and see Can't locate Foo/Bar.pm in @INC (you may need to install the Foo::Bar module) (@INC contains: ...

So you install the Foo::Bar module and try again and see Can't locate Bar/Baz.pm in @INC (you may need to install the Bar::Baz module) (@INC contains: ...

So you install the Bar::Baz module and the application runs.

Module::Load::Conditional (core) can reduce the pain to:

Install required modules Foo::Bar Bar::Baz from CPAN? (y)/n y
Use 1. cpan or 2. cpanm 1/(2) 2
Successfully installed Foo::Bar
Successfully installed Bar::Baz
Or select 'n' for something more than @INC:
Install required perl modules:
cpan Foo::Bar Bar::Baz 
cpanm -v Foo::Bar Bar::Baz 

Can't locate Foo::Bar Bar::Baz in @INC (@INC contains: ...
Should perl be doing something like this on the core level?

Should monks adopt this mess or fold it into a module so it becomes a best practice?

How could this idea be improved?

Thank you!

#!/usr/bin/perl use strict; use warnings; #use Foo::Bar; #use Bar::Baz; use Module::Load::Conditional 'can_load'; BEGIN { my $modules = [ map {$_} qw[ IPC::Cmd Foo::Bar Bar::Baz ]]; my @install = do { local @_; for my $m (@$modules) { push @_, $m unless can_load(modules => {$m,undef}, autoload => 1)} @_ }; @install and do { print 'Install required modules ', join(' ', @install), ' from CPAN? (y)/n '; my $in = <STDIN>; chomp $in; $in ||= 'y'; my $cpanm = IPC::Cmd::can_run('cpanm'); if (lc $in eq 'y') { if ($cpanm) { print 'Use 1. cpan or 2. cpanm 1/(2) '; my $cpan = do { local $_ = <STDIN>; chomp $_; $_ ||= 2; $_ = 2 unless /^1|2$/; $_ }; if ($cpan == 2) { unless (system $cpanm, '-v', @install) { system 'perl', $0, @ARGV; exit } } } unless (system 'cpan', @install) { system 'perl', $0, @ARGV; exit } } else{ die "Install required perl modules:\n". join ' ', 'cpan', @install, "\n". ($cpanm ? join(' ', 'cpanm', @install) : '')."\n\n". "Can't locate ".join(' ',@install).' in @INC '. '(@INC contains: '.join(' ', @INC).") \n" } }; Bar::Baz->import('Something')}
  • Comment on The missing link between "you may need to install the module" and "distribution installed" application is running!
  • Download Code

Replies are listed 'Best First'.
Re: The missing link between "you may need to install the module" and "distribution installed" application is running!
by haukex (Chancellor) on Oct 24, 2019 at 12:09 UTC
    Should perl be doing something like this on the core level?

    IMHO there are so many different ways to install modules that Perl doing this on its own would probably be too overbearing - better to have a module to do it.

    Should monks adopt this mess or fold it into a module so it becomes a best practice?

    This already exists, see e.g. lazy and the other modules its "See Also" section.

Re: The missing link between "you may need to install the module" and "distribution installed" application is running!
by tobyink (Canon) on Oct 25, 2019 at 12:57 UTC

    Isn't ensuring that the app's dependencies are installed the responsibility of the installer of the app you were trying to run in the first place?

    Your app shouldn't need to check if Foo::Bar is available and install it at run time every time. Your app's installer should check Foo::Bar is installed, then your app can always assume that it's installed.

Re: The missing link between "you may need to install the module" and "distribution installed" application is running!
by dragonchild (Archbishop) on Nov 30, 2019 at 14:46 UTC
    The other answers are a little terse, so let's go into some detail. I run a Devops team, so this question is near-and-dear to my heart.

    The first problem is where should you install the modules from. The obvious answer is CPAN. Except, is it really? My team works really hard to ensure all installations go through our Artifactory. Why? So we can verify the versions of things that are installed are secure and free of malware. Malware in an OSS module?! Oh yes!

    Okay, now you say "Sure, but that should be configured at the system level." Maybe. Maybe not. Maybe it's configured at the source repository level. Maybe your friendly Devops team has configured the development environments so that all development occurs within VMs and containers which mirror how production is built and there isn't an interpreter on the developer's workstation. (Yes, this is exactly what my team does for our developers.) Why? So that no-one thinks they can develop locally in a way that isn't reproducible. "It works on my machine" is a Critical-Severity failure for my team.

    We haven't even started to explore the issue of dependency management. I'm not talking about Perl dependency management. Library dependencies are even harder to get right. And, no, Alien doesn't work. This is a large part of why Devops teams (like mine) really like OS packages (rpms and debs) for installing OSS modules. In fact, we have a habit of repackaging OSS modules as OS packages specifically so we can (as an example) say things like "XML::Parser depends on libexpat" and make sure everything installs properly.

    This doesn't even get into the problem of Perl modules with XS. Does everyone need to have a full build-chain installed? Does that build-chain even run properly? What about those dependencies?!

    Hopefully, this helps you understand exactly why programming language runtimes (like Perl, Python, Ruby, NodeJS, etc) choose not to install libraries on demand. It's not laziness - it's to allow people to be clever.


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: The missing link between "you may need to install the module" and "distribution installed" application is running!
by Anonymous Monk on Oct 24, 2019 at 12:13 UTC

    Should perl be doing something like this on the core level? Should monks adopt this mess or fold it into a module so it becomes a best practice? How could this idea be improved?

    noobs be noobs

    old ideas old

    installers are installers

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://11107929]
Approved by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (6)
As of 2019-12-13 21:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?