【问题标题】:How to make "prereqs" of CPAN::Meta::Spec require a distribution instead of a package?如何使 CPAN::Meta::Spec 的“先决条件”需要分发而不是包?
【发布时间】:2019-06-26 07:14:37
【问题描述】:

我正在研究如何打包我的一些 Perl 应用程序并更好地管理它们的依赖项,以使我和我的客户更容易分发,这很可能根本不包括上传到 CPAN。相反,如果需要,我会提供自定义存储库,或者更有可能的是访问 SCM,例如 Subversion。

CPAN::Meta::Spec 似乎提供了我需要描述我的应用程序、它们的依赖关系甚至从何处获取它们的信息,但我想知道的是先决条件的详细程度。 The spec 包含以下句子:

必须将关系集指定为包名称到版本范围的映射。

对于我的需求来说,需要包似乎有点太低了,我更喜欢需要发行版。像 Maven 和 Gradle 这样的级别(根据我的理解)工具几乎可以工作,例如Apache Commons Lang 与 Apache Commons IO 等,而不是像 org.apache.commons.lang3.AnnotationUtilsorg.apache.commons.io.ByteOrderMark 这样的单个类。 OTOH,文档中的示例包含以下几行:

requires => {
  'perl'          => '5.006',
  'File::Spec'    => '0.86',
  'JSON'          => '2.16',
},

包含perl 的行对我来说看起来不像一个包,我在系统上的任何地方都没有找到package perlperl.pm。在我看来,这与示例中的其他事情的处理方式不同。

我有一个系统范围的文件夹,其中包含例如一些实用程序包,对我来说似乎与一些抽象的perl 相当。该文件夹应该被定义为一个发行版,为该文件夹中的所有包维护一个版本号,因此应该允许其他应用程序 require 整个事情。如果我正确理解文档,我不仅需要在文件夹中创建META.yml,还需要创建一些例如sysutils.pm 包含 package sysutils; 并定义了一些版本。

有什么方法可以避免创建该文件并且真的只创建require 分发本身吗?

META.yml 已经包含了它自己的名称和版本,所以看起来像一些抽象的东西,理论上可以require。我认为不需要添加一个额外的.pm-文件来表示发行版本身,只允许require 工作。就我而言,它不包含任何业务逻辑。

谢谢!

【问题讨论】:

    标签: perl cpan metacpan


    【解决方案1】:

    这真的不是你想做的。你想预先请求你实际需要的东西。因此,例如,如果您需要 File::Spec,这就是您所需要的,无论它来自 perl 核心还是来自单独的 CPAN 发行版。

    我见过某些模块从 CPAN 迁移到核心的案例,反之亦然。通过直接要求该模块,您无需仅仅因为您依赖的某个人更改了他们的分发方法就发布了您依赖的发行版的新版本。

    我还看到某些模块在确定它们作为独立模块有价值时从其原始发行版中分离出来的情况。依赖模块意味着您不再为了简单的依赖而拖入一堆其他模块。

    您或多或少地寻找类似于Task::* 模块。其中大多数没有真正的逻辑,只是进一步的依赖列表。

    【讨论】:

    • OTOH,在两个地方维护单个所需的包对我来说没有多大意义,一个是实际需要的包,另一个是 META.yml。在后一种情况下,没有上下文或层次结构表明为什么需要它并且很容易忘记维护。所以我需要一些自动化的过程来维护这些东西,使一切变得更加复杂,同时在具有不同 repos 的分发级别上工作似乎对例如Maven 和 Gradle。
    • 它只会在不再有效之前有效。还有用于维护 META.yml 的 CPAN 工具 - 我自己几乎从未编辑过它,依靠 Module::Build 或类似工具为我做这件事,作为 dist 操作的一部分。
    • Module::Build 也被一些人认为是失败的实验,Maven 和 Gradle 适用于相当大的项目和自动化工具,例如不能在一个应用程序中轻松用于具有不同要求的不同功能之类的东西。我有这样的应用程序需要不同的 3rd 方库,具体取决于运行时配置,例如GD 或 OpenOffice-Libs 或 ...stackoverflow.com/questions/30765522/…
    • 最后,如果它不再在分发级别上工作,我总是可以切换到单个包,但如果 CPAN::Meta::Spec 根本不支持,则不能相反它。因此我的问题。
    • Module::Build 不是唯一可以为您更新 META.yml 的。这只是我记得的那个。
    【解决方案2】:

    Perl 依赖系统完全适用于包名称,在多个级别上。上传 CPAN 发行版时,其中的每个包都由 PAUSE 编制索引,它还会检查上传者是否具有该包的 permissions 以及该包是否具有比 currently indexed package 更新的版本。这些检查都不关心整个分布(尽管索引器会在该级别进行其他检查)。

    然后,当 CPAN 客户端看到依赖项,或者您告诉它安装某些东西时,它会检查该软件包名称的索引,从而告诉它要安装哪个发行版。如果它依赖于某个版本,则根据该软件包中声明的$VERSION 进行检查(如果您已安装它);而一旦安装了一个发行版,它的“版本”就不再被跟踪了。分发级别几乎完全没有意义,只是它最终是为了满足这些依赖而下载和安装的。这很重要,因为模块可以并且确实在发行版之间移动,维护它们的版本增量,并且包索引将始终告诉您哪个发行版可以获得您需要的版本。

    正如您所注意到的,perl 依赖项很奇怪。这是一个一直存在的特殊情况,作为声明您需要的 Perl 版本的约定,您声明运行时要求为perl。它不是索引模块,每个 CPAN 客户端和 CPAN 元数据的其他消费者在特殊情况下要么忽略它,要么将其视为最低 Perl 版本,而不是可以安装的东西。没有办法将其扩展为适用于一般发行版,尝试这样做是个坏主意。

    作为附加说明,CPAN 元规范是 CPAN 发行版中包含的名为 META.json 的文件的规范(META.yml 是旧版本),但此文件是由您的创作工具自动生成的。它永远不应该手动创建,尽管您可以让您的创作工具手动添加某些键(在这种情况下阅读规范很重要),包括prereqs。请参阅neilb's blog post,了解如何为各种创作工具指定依赖项,然后将它们转换为生成的 META 文件,以及如何使用 cpanfiles 指定一般依赖项。

    【讨论】:

    • 提到的博客文章要么写META.*-structures manually in some build tool, where I don't see the need to use that tool at all, or suggests tools others see as deprecated already or mentions tools itself saying those are not recommended anymore. cpanfile` 似乎也没有为META.* 提供任何好处,例如似乎将不同的存储库作为安装源处理,最好为每个发行版定义,例如 Maven 和 Gradle。
    • 我已经从cpanfile 开始我的研究,这使我找到了CPAN::Meta::Spec,我遇到的所有那些提到的构建/创作工具要么不再被推荐,要么根本不符合我的需求关于 repo 定义,在应用程序中正确区分可选功能及其要求等。这整个主题目前似乎有很多多余的方法,对我来说混合了高低级别。我或多或少似乎只需要像 Maven 或 Gradle 这样的方法。
    猜你喜欢
    • 1970-01-01
    • 2019-06-27
    • 2017-07-17
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    • 1970-01-01
    • 2016-08-28
    • 2021-07-20
    相关资源
    最近更新 更多