Perl構建和打包自己的模塊


當寫好一個或多個模塊后,可以將它構建、打包成"tar.gz",以便讓別人安裝或者上傳到CPAN(如果願意的話)。對於模塊的使用者來說,也不用再使用use lib 'LIB_PATH'來找pm文件,安裝后一般都會安裝到@INC路徑下,然后直接使用use MODULE即可。

Module::Starter

在很早以前,使用h2xz工具,但它實在太古老了。現在很多人使用Dist::Zilla模塊來創建並安裝模塊。不過本文只是基礎,只介紹Module::Starter構建和打包的方法。

先安裝:

$ cpan -i Module::Starter

Module::Starter模塊提供了一個命令行程序module-starter,它可以用來構建模塊。

例如,構建一個名為My::Number::Utilities的模塊(模塊可以不用存在,它會自動創建一些文件結構)

$ module-starter --module "My::Number::Utilities" --author="ma long shuai" --email="79123@qq.com"

上面第一條命令將會創建如下的目錄樹:

$ tree My-Number-Utilities
My-Number-Utilities
├── Changes
├── ignore.txt
├── lib
│   └── My
│       └── Number
│           └── Utilities.pm
├── Makefile.PL
├── MANIFEST
├── README
├── t
│   ├── 00-load.t
│   ├── manifest.t
│   ├── pod-coverage.t
│   └── pod.t
└── xt
    └── boilerplate.t

其中:

  • Changes:包含程序版本的變化信息
  • MANIFEST:列出發布的模塊版本中必須包含的每個文件
  • Makefile.PL:是Perl程序創建的Makefile,Makefile文件中包含了如何編譯和構建程序的說明。如果不是非常熟悉Makefile格式,千萬不能修改,一個tab和空格的不同可能都會導致編譯出錯。
  • README:包含了如何構建和安裝程序的文檔,一般來說,程序的說明文檔會嵌入在此文件中。
  • ignore.txt:是類似於git/svn版本控制系統的文件忽略模板,你可能會經常拷貝該文件到你的版本控制系統中。
  • lib/:該目錄包含了實際要安裝的模塊。
  • t/:該目錄包含了模塊測試相關的文件。

上面的文件可能已經包含了一些內容,例如lib/My/Number/Utilities.pm文件中已經自動包含了一些編譯指示,還包含了默認的pod文檔。

$ head -n 10 My-Number-Utilities/lib/My/Number/Utilities.pm 
package My::Number::Utilities;

use 5.006;
use strict;
use warnings;

=head1 NAME

My::Number::Utilities - The great new My::Number::Utilities!

默認情況下,Module::Starter構建的模式是Makefile.PL,如果想要構建Build.PL,可以加上--builder=Module::Build或者無需選項參數的選項--mb

$ module-starter --builder=Module::Build --module "My::Number::Utilities" --author="ma long shuai" --email="79123@qq.com"
$ module-starter --mb --module "My::Number::Utilities" --author="ma long shuai" --email="79123@qq.com"

因為每次在module-starter命令行上都寫author和email選項很麻煩,可以在家目錄下創建一個文件$HOME/.module-starter/config(該目錄可由環境變量MODULE_STARTER_DIR設置,只需在該環境變量指定的目錄下包含config文件即可。例如windows下.module-starter目錄可能會有些問題),包含每次想要在命令行中省略的選項即可,例如:

author: ma long shuai
email: 79123@qq.com
builder: Module::Build
verbose: 1

以后再執行module-stater時,只需一個--module選項即可:

module-starter --module=My::Module

現在,只需將自己寫的pm模塊文件拷貝覆蓋到My-Number-Utilities/lib/My/Number/Utilities.pm,將獨立的pod文檔放到pm同目錄下即可。然后就可以編譯、安裝模塊了。

perl Makefile.PL
make
make test
make install

# 或者
perl Build.PL
./Build
./Build test
./Build install

上面的過程中,只要不是error,出現了warning可以忽略。

最后,執行下面兩種命令,可將模塊打包成".tar.gz"格式的文件。

make dist
./Build dist

例如,生成Build格式的包:

$ ./Build dist
Created META.yml and META.json
Creating Cat-New-0.01
Creating Cat-New-0.01.tar.gz

Makefile.PL和Build.PL

雖然Makefile.PL和Build.PL不建議修改,但小心翼翼點也可以修改。

Makefile.PL

先看Makefile.PL文件的前幾行:

use 5.006;
use strict;
use warnings;
use ExtUtils::MakeMaker;

WriteMakefile(
    NAME             => 'My::Number::Utilities',
    AUTHOR           => q{ma long shuai <79123@qq.com>},
    VERSION_FROM     => 'lib/My/Number/Utilities.pm',
    ABSTRACT_FROM    => 'lib/My/Number/Utilities.pm',
    LICENSE          => 'artistic_2',
    PL_FILES         => {},
    MIN_PERL_VERSION => '5.006',
    CONFIGURE_REQUIRES => {
        'ExtUtils::MakeMaker' => '0',
    },
    BUILD_REQUIRES => {
        'Test::More' => '0',
    },
    PREREQ_PM => {
        #'ABC'              => '1.6',
        #'Foo::Bar::Module' => '5.0401',
    },
    dist  => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
    clean => { FILES => 'My-Number-Utilities-*' },
);

主要是其中的PREREQ_PM項,它表示安裝此模塊時所依賴的模塊,也就是要安裝此模塊,必須先安裝該項指定的模塊。它是一個hash結構,每個模塊名是鍵,其值是模塊的版本號,表示最低要安裝該版本的模塊。

此外,如果想要安裝一些perl程序文件,而非模塊文件,可以如下書寫:

WriteMakefile(
    ...
    EXE_FILES => [ qw( scripts/barnyard.pl ) ],
    ...
);

上面的要求是將barnyard.pl程序文件放在scripts目錄下。通過這種方式,即使是沒有包含任何模塊,也能構建perl程序包。在安裝模塊的時候,這個文件會放進/usr/local/bin目錄下。

Build.PL

再看Build.PL文件的前幾行:

use 5.006;
use strict;
use warnings;
use Module::Build;

my $builder = Module::Build->new(
    module_name         => 'Cat',
    license             => 'artistic_2',
    dist_author         => q{ma long shuai <79123@qq.com>},
    dist_version_from   => 'lib/Cat.pm',
    release_status      => 'stable',
    configure_requires => {
        'Module::Build' => '0',
    },
    build_requires => {
        'Test::More' => '0',
    },
    requires => {
        #'ABC'              => '1.6',
        #'Foo::Bar::Module' => '5.0401',
    },
    add_to_cleanup     => [ 'Cat-*' ],
);

$builder->create_build_script();

主要是其中的requires項,它表示安裝此模塊時所依賴的模塊。

此外,如果想要安裝一些perl程序文件,而非模塊文件,可以如下書寫:

my $builder = Module::Build->new(
    ...
    script_files => [ qw(scripts/barnyard.pl) ],
    ...
);

上面的要求是將barnyard.pl程序文件放在scripts目錄下。

當執行Module::Starter的module-starter時,會調用ExtUtil::Makefile

構建多個模塊

如果想一次性構建多個模塊,且知道各模塊名稱,則可以:

$ module-starter --module=Animal,Cow,Horse,Mouse

它會以第一個模塊名稱作為頂級目錄,然后在lib中創建各模塊文件。

參考如下目錄結構:

$ tree Animal/
Animal/
├── Changes
├── lib
│   ├── Animal.pm
│   ├── Cow.pm
│   ├── Horse.pm
│   └── Mouse.pm
├── Makefile.PL
├── MANIFEST
├── README
├── t
│   ├── 00-load.t
│   ├── manifest.t
│   ├── pod-coverage.t
│   └── pod.t
└── xt
    └── boilerplate.t

如果模塊是多層次的(包含雙冒號的),則構建的目錄結構如下:

$ module-starter --module=Animal::Rule,Cow::Rule,Horse,Mouse

$ tree Animal-Rule
Animal-Rule/
├── Changes
├── lib
│   ├── Animal
│   │   └── Rule.pm
│   ├── Cow
│   │   └── Rule.pm
│   ├── Horse.pm
│   └── Mouse.pm
├── Makefile
├── Makefile.PL
├── MANIFEST
├── MYMETA.json
├── MYMETA.yml
├── README
├── t
│   ├── 00-load.t
│   ├── manifest.t
│   ├── pod-coverage.t
│   └── pod.t
└── xt
    └── boilerplate.t

添加新模塊

如果想要向已有模塊目錄添加一個新模塊,需要使用Module::Starter::AddModule插件,不過得先安裝:

$ cpan -i Module::Starter::AddModule

然后在Module::Starter的配置文件$HOME/.module-starter/config中加入一行:

author: ma long shuai
email: 79123@qq.com
verbose: 1
plugins: Module::Starter::AddModule  # 新加此行

然后就可以添加新模塊:

$ module-starter --module=Sheep --dist=Animal-Rule

其中--dist指定要添加到的模塊目錄,如果已經在Animal-Rule目錄下,則使用相對路徑--dist=.即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM