I've started writing a Perl module with module-starter. Now, I've found that it will depend on a non-core module. Where should I note this dependency?
module-starter creatures an installer (Makefile.PL) that uses ExtUtils::MakeMaker. You'll need to add
PREREQ_PM => {
'Some::Prereq' => 0,
},
to argument list of the call to WriteMakefile therein.
Related
I'm building a Perl module. Makefile.PL has
WriteMakefile(
PREREQ_PM => {
'DBI' => '>= 1.641, < 2',
# etc, ...
},
TEST_REQUIRES => {
'Test::More' => 0,
},
# more stuff ...
);
Recently, my ~/perl5 tree got corrupted (PERL5LIB=~/perl5) so I decided to rebuild it, so I blew it away. Doesn't WriteMakefile() generate some make target that will do this for me with all the modules/packages in PREREQ_PM and TEST_REQUIRES. Instead, it just prints warnings:
Warning: prerequisite DBI >= 1.641, < 2 not found.
So I have to start re-installing all these by hand in order to run tests. For my small project, this isn't such a problem, but what if the project had many dependencies? Isn't there a way to automate this?
There is no Makefile target that will do what you want, but the cpan tool will use the information in the META file created by Makefile.PL to fetch and install dependencies.
If you to use cpan offline, consider cloning CPAN using CPAN::Mini.
I'm considering of using modules to group scripts. I often end up in the scenario that I have one or more scripts that uses a certain module.
Is it possible to pack the scripts together with the module?
Are there any specifics to how to achieve that?
Thanks for your input.
You can include scripts along with your module by including the EXE_FILES directive in a Makefile.PL file, and supplying the relative path to the scripts in an array reference. In the below example, the scripts live in a bin/ directory within the top level of your module's directory. You do not need to have your files in a distribution-like layout, but it helps (see below).
After setting up your directory structure and fiddling with the paths within the Makefile.PL, running make install will install your scripts along with your module.
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => 'My::Module',
VERSION_FROM => 'lib/My/Module.pm',
($] >= 5.005 ?
(ABSTRACT_FROM => 'lib/My/Module.pm',
AUTHOR => 'My Name <email.addr>') : ()),
LIBS => [],
EXE_FILES => [qw(bin/script1 bin/script2)],
DEFINE => '',
INC => '-I.',
PREREQ_PM => {},
);
Personally, I'd recommend turning your module into a full-blown distribution. Here's an example. First, install Module::Starter, then:
module-starter --author="My Name" --email="my#email.com" --module=My::Module --eumm
Now you can copy your module's code to lib/My/Module.pm, create a bin/ directory, put your scripts in it, add the EXE_FILES directive to the Makefile.PL, and you can use the full suite of make commands to make, test and install your modules and the scripts, eg:
perl Makefile.PL
make
make test
make install
Here's a real-world example, one of my own distributions on the CPAN that includes a bundled pinmap Perl script along with the distribution's modules:
The File::ShareDir::Install module represents a practical way of carrying around auxiliary files with a Perl distribution/module. I feel however a bit puzzled on how to include it in the dependencies of my project.
I tried to install my package on a fresh machine (actually a docker container with base OS + Perl + CPAN) and I got the error:
Can't locate File/ShareDir/Install.pm in #INC ... at Makefile.PL line 7.
According to the documentation (perldoc File::ShareDir::Install), the pattern should be, in my Makefile.PL:
use ExtUtils::MakeMaker;
use File::ShareDir::Install;
install_share 'share';
install_share dist => 'dist-share';
install_share module => 'My::Module' => 'other-share';
WriteMakefile( ... ); # As you normaly would
package MY;
use File::ShareDir::Install qw(postamble);
However, by doing so I need File::ShareDir::Install to be pre-installed on my system as requirement to run the Makefile.PL script. Declaring it as dependency will not work, for obvious reasons!
Should I instruct my users to explicitly instasll File::ShareDir::Install before my module? Would it be possible to install it programmatically, within Makefile.PL, by directly calling the CPAN module?
This is what CONFIGURE_REQUIRES is for:
Available in version 6.52 and above.
A hash of modules that are required to run Makefile.PL itself, but not to run your distribution.
This will go into the configure_requires field of your META.yml and the configure of the prereqs field of your META.json.
Defaults to { "ExtUtils::MakeMaker" => 0 } if this attribute is not specified.
The format is the same as PREREQ_PM.
So you would add to your WriteMakefile parameters:
CONFIGURE_REQUIRES => {
"ExtUtils::MakeMaker" => '6.52',
"File::ShareDir::Install" => 0,
},
Then people using cpan or cpanm to install modules will get File::ShareDir::Install installed automatically.
To build the distribution
Make a File::ShareDir::Install a build-time dependency.
CONFIGURE_REQUIRES => {
'ExtUtils::MakeMaker' => '6.52',
'File::ShareDir::Install' => 0,
},
Install File::ShareDir::Install on the machine on which you will build the distribution.
Build the distribution.
This will create a META.yml that includes File::ShareDir::Install as a build-time dependency.
To install the distribution
Just use cpan or cpanm as normal. cpan and cpanm will extract build-time dependencies from META.yml and install them before running Makefile.PL.
I plan on uploading a module to CPAN, shortly. This is the first module I've contributed. I've got the module to what I'd consider a "beta" stage. I'm using ExtUtils::MakeMaker to generate a Makefile through Makefile.PL (I've pasted the contents of it below). The Makefile.PL script has all the prereq modules listed. I'm wondering at which point in the installation process, the prereq modules are installed if they're not present? I'm wondering because I ran Makefile.PL followed by make then make install in a separate environment that's missing some of the prereq modules. However, they were not installed? I was under the impression they would be but maybe im missing something? I'm looking for someone to provide some clarity. Thanks in advance~
Makefile.PL
#!/usr/bin/env perl
use strict;
use warnings;
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => 'Imgur',
VERSION => '0.01',
PREREQ_PM => {
'JSON' => 2.90,
'LWP::UserAgent' => 6.05,
'HTTP::Request::Common' => 6.04,
'Data::Dumper' => 2.154,
'DateTime::Format::ISO8601' => 0.08,
'Config::IniFiles' => 2.86,
'Scalar::Util' => 1.42,
'Class::Std::Utils' => 0.0.3,
'MIME::Base64' => 3.15,
'File::Slurp' => 9999.19
}
);
The Makefile.PL doesn't install prerequisites; it just complains if they're not installed. It's the CPAN client's job to install prerequisites.
Note: Module::Install has an auto_install feature that does this, but the general consensus seems to be that using it is a bad idea.
I've recently started learning XS using perlxstut and the tutorial suggests that I create my module using the old h2xs tool to create an ExtUtils::MakeMaker-based project. However for pure Perl projects, h2xs/EUMM has long been disfavoured in favour of Module::Install, Module::Build or Dist::Zilla.
Is there a more modern way of creating XS projects? Can Module::Starter create XS projects? Can Module::Build or Dist::Zilla build XS projects? Their pod pages are silent on the matter.
On the flip side, does the criticism that was levelled at h2xs/EUMM apply to XS projects? If you need a C compiler anyway, is it reasonable to demand a make tool as well?
EDIT: I see this question answers my question about creating a project. I'd still like to know about building: is EUMM the only option, or are Module::Build and Dist::Zilla also capable of building XS?
It turns out that Module::Build is perfectly capable of compiling XS. Here is a complete Build.PL I managed to scrape together:
use strict;
use Module::Build;
my $build = Module::Build->new(
module_name => 'Chocolate::Belgian',
dynamic_config => 1,
license => 'perl',
requires => {
'Module::Build' => '0.19', # xs
'Test::More' => 0,
},
extra_compiler_flags => '-Iinclude',
extra_linker_flags => '',
c_source => 'src',
needs_compiler => 1,
xs_files => {
'./Belgian.xs' => 'lib/Chocolate/Belgian.xs',
},
);
$build->create_build_script;
This will build a distribution with .h include files (such as ppport.h) in the include/ directory, .c source files in the src/ directory, and an .xs file corresponding to package Chocolate::Belgian in the project base directory.
extra_compiler_flags corresponds to make CCFLAGS, while extra_linker_flags corresponds to LIBS (so you might want -lm there to link the C math library).
Dist::Zilla is not a replacement for EUMM or Module::Build, what it will do is generate a Makefile.Pl (etc) for you, I would not be surprised to hear that it can't do this for an XS project, but there are ways of managing your own for a dzil project. It can work with whatever Makefile.Pl it is provided with (or Build.pl).
So my answer on the Dist::Zilla part of your question is, Dist::Zilla does not fill that role in a project.
I always just use some fairly simple XS distribution as a starting point. h2xs can do some of the XS generation by parsing a header, but most of the time, I found that too limited to be useful.
If you're planning to wrap C++, you may want to take a look at Module::Build::WithXSpp.