Perl 使用ExtUtils::MakeMaker/Dist::Zilla(dzil)在安装时安装其他文件

Perl 使用ExtUtils::MakeMaker/Dist::Zilla(dzil)在安装时安装其他文件,perl,makemaker,dist-zilla,Perl,Makemaker,Dist Zilla,tl;dr我想在我的Perl库中附带一个包.json,运行warn install(或者在安装过程中运行npm install),并使用Perl模块安装下载的JavaScript依赖项 我有以下dist.ini: name = Foobar version = 1.2.3 license = Perl_5 copyright_holder = Yours Truly copyright_year = 2018 [@Filter] -bundle = @Basic -remove = Gat

tl;dr我想在我的Perl库中附带一个
包.json
,运行
warn install
(或者在安装过程中运行
npm install
),并使用Perl模块安装下载的JavaScript依赖项

我有以下
dist.ini

name = Foobar
version = 1.2.3
license = Perl_5
copyright_holder = Yours Truly
copyright_year   = 2018

[@Filter]
-bundle = @Basic
-remove = GatherDir
[Git::GatherDir]

[Web::FileHeader]
header_filename = EMM-include.pm
file_match = ^Makefile\.PL$
文件
EMM include.pm
包含
MY::postmble
方法:

package MY;

use strict;

use Cwd qw(abs_path);
use File::Spec;

sub postamble {
    my ($self) = @_;

    my $here = Cwd::abs_path();
    my $libdir = File::Spec->catdir($here, 'lib', 'Foobar');
    chdir $libdir or die;
    0 == system 'yarn', 'install' or die;
    chdir $here or die;

    return '';
}
插件
[Web::FileHeader]
获取文件并将其修补到
Makefile.PL
的开头

然后是一个
lib/Foobar/package.json

{
  "name": "foobar",
  "version": "1.2.3",
  "main": "index.js",
  "dependencies": {
    "ajv": "^6.5.4"
  }
}
EMM include.pm的
MY::postamble
部分调用
warn install
(如果您没有
warn
,请将其替换为
npm install
),并使用
ajv
及其依赖项填充目录
lib/Foobar/node_模块

最后,必须有一个模块
lib/Foobar.pm

package Foobar;
# ABSTRACT: Just a test.
1;
这几乎可以按预期工作:可以使用
dzil build
创建发行版。在分发目录中,
perl Makefile.PL
调用
warn install
,目录
lib/Foobar/node\u modules
被填充,但其中的文件没有安装
make install

如果我再次运行
perlmakefile.PL
,一切都会正常工作,JavaScript依赖项将其放入
blib/
中,
makeinstall
将在perl模块旁边安装JavaScript模块

将JavaScript依赖项与发行版一起提供不是一个选项。它们已经太多了,并且可能有冲突的许可证(我在这里使用的是GPLv3)。由于缺少特权,在安装后的运行时下载DEP通常会失败

诚然,这与
Dist::Zilla
没有多大关系,而是
ExtUtils::MakeMaker
的问题。但实际上我在这里使用的是
Dist::Zilla


如果重要的话,真正的发行版是,撰写本文时的最后一次提交是。

首先,不要使用[Web::FileHeader]来更改Makefile.PL,而是将[MakeMaker](由@Basic使用)替换为[MakeMaker::Awesome],这允许您直接修改Makefile.PL,并正确启用动态配置,因为您的发行版需要它。另外,不要给include文件一个.pm扩展名,因为它不是一个perl模块,并将其从收集到生成的发行版中排除,以免意外安装

[@Filter]
-bundle = @Basic
-remove = GatherDir
-remove = MakeMaker
[Git::GatherDir]
exclude_filename = EMM-include
[MakeMaker::Awesome]
header_file = EMM-include
我强烈建议使用my而不是过时的@Basic,但如果不是的话,至少要添加[MetaJSON],这样您就有了现代元数据

[@Starter::Git]
revision = 3
installer = MakeMaker::Awesome
Git::GatherDir.exclude_filename[] = EMM-include
MakeMaker::Awesome.header_file = EMM-include

关于安装时需要执行的操作。首先,我要提醒大家的是,安装时需要连接到互联网,这并不是你可以一直依赖的,当然也没有现成的纱线。但是用于安装外部库的一系列模块经常会做这种事情。由于您不需要编译这段代码,您可能不需要整个Alien::Build/Alien::Base设置,但它可能比下面描述的Makefile黑客攻击更容易解决问题。基本上,您将首先发布一个外来发行版,该发行版将在必要时安装您的javascript库,然后此发行版将依赖它来加载库。如果你决定沿着这个方向走,请查看IRC频道



ExtUtils::MakeMaker的postamble部分不用于运行任意代码;用于将自定义规则添加到生成的Makefile中;这是您需要影响制作过程的方式。我对Makefiles知之甚少,所以我不能在这里进一步帮助您,我所能建议的就是阅读所有的,并注意postmble是一个函数,您可以覆盖它来添加文本,以及来自MM_Any和MM_Unix的其他选项。你可以在IRC频道上找到帮助你的人。

我明天的下一次尝试是找到由
warn/npm
安装的所有文件,然后将它们添加到
Makefile
变量
以安装PM
。我走对了吗?或者有更简单的方法吗?我知道安装需要互联网连接,但事实就是这样,如果我需要外部文件,我无能为力。我已经做了快速检查,你的建议会奏效。当然,关于postmble,您是对的,我将把代码移到方法之外。我的例子只是想重现这个问题。我已经有了一个
META.json
,并且
EMM include.pm
已经从安装中排除。构建似乎不适合我的用例,但这是另一个问题。谢谢你的回答!