Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a Perl 6 module containing Perl 5 utility scripts in bin/

Tags:

raku

Perl 6 script in a Perl 5 module distribution

I can include a Perl 6 script in a Perl 5 module distribution:

# Create a new module
dzil new My::Dist
cd My-Dist/

# Add necessary boilerplate
echo '# ABSTRACT: boilerplate' >> lib/My/Dist.pm

# Create Perl 6 script in bin directory
mkdir bin
echo '#!/usr/bin/env perl6' > bin/hello.p6
echo 'put "Hello world!";' >> bin/hello.p6

# Install module
dzil install

# Test script
hello.p6
    # Hello world!

# See that it is actually installed
which hello.p6
    # ~/perl5/perlbrew/perls/perl-5.20.1/bin/hello.p6

Perl 5 script in a Perl 6 module distribution

However, I'm having a hard time including Perl 5 scripts in a Perl 6 distribution.

In the module directory is a META6.json file and a subdirectory called bin. In bin is a Perl 5 file called hello.pl.

zef install . runs without error in the top directory. But when trying to run hello.pl, I get an error. Come to find out, a Perl 6 wrapper script had been installed for hello.pl and that is what is giving me the error. If I run the original hello.pl directly, it works fine.

META6.json

{
"perl"         : "6.c",
"name"         : "TESTING1234",
"license"      : "Artistic-2.0",
"version"      : "0.0.2",
"auth"         : "github:author",
"authors"      : ["First Last"],
"description"  : "TESTING module creation",
"provides"     : {
                 },
"depends"      : [ ],
"test-depends" : [ "Test", "Test::META"  ]
}

bin/hello.pl

#!/usr/bin/env perl
use v5.10;
use strict;
use warnings;

say 'Hello world!';

This installs without error, but when I try to run hello.pl, I get the following error:

===SORRY!===
Could not find Perl5 at line 2 in:
    /home/username/.perl6
    /path/to/perl6/rakudo-star-2017.07/install/share/perl6/site
    /path/to/perl6/rakudo-star-2017.07/install/share/perl6/vendor
    /path/to/perl6/rakudo-star-2017.07/install/share/perl6
    CompUnit::Repository::AbsolutePath<64730416>
    CompUnit::Repository::NQP<43359856>
    CompUnit::Repository::Perl5<43359896>

which hello.pl from the command line indicated that it was installed in /path/to/perl6/rakudo-star-2017.07/install/share/perl6/site/bin/hello.pl. That file is actually the following code:

/path/to/perl6/rakudo-star-2017.07/install/share/perl6/site/bin/hello.pl

#!/usr/bin/env perl6
sub MAIN(:$name is copy, :$auth, :$ver, *@, *%) {
    CompUnit::RepositoryRegistry.run-script("hello.pl", :dist-name<TESTING1234>, :$name, :$auth, :$ver);
}

I filed a Rakudo bug report (https://rt.perl.org/Ticket/Display.html?id=131911), but I'm not totally convinced that there isn't a simple work around.

like image 857
Christopher Bottoms Avatar asked Aug 16 '17 18:08

Christopher Bottoms


1 Answers

As an example, I created a simple cat replacement in Perl 5 and created a Perl 6 module that "wrapped" around it (see the GitHub repository for it if you'd like to download the code and try it yourself).

Below are copies of the relevant files. After creating these files, running zef install . installs fine with my Rakudo Star 2017.07 installation. This installs a run_cat executable in your Rakudo bin directory.

It seemed like the secret was to make a Perl 6 module file to wrap the Perl 5 script and a corresponding Perl 6 script to use the Perl 6 module.


Perl 5 script

resources/scripts/cat.pl

#!/bin/env perl
use v5.10;
use strict;
use warnings;

while(<>) {
    print;
}

Wrapper scripts

module: lib/catenate.pm6

unit module catenate;

sub cat ($filename) is export {
    run('perl',%?RESOURCES<scripts/cat.pl>,$filename);
}

executable: bin/run_cat

#!/bin/env perl6
use catenate;

sub MAIN ($filename) {
    cat($filename);
}

Boilerplate and tests

META6.json`

{
"perl"         : "6.c",
"name"         : "cat",
"license"      : "Artistic-2.0",
"version"      : "0.0.9",
"auth"         : "github:author",
"authors"      : ["First Last"],
"description"  : "file catenation utility",
"provides"     : { "catenate" : "lib/catenate.pm6" },
"test-depends" : [ "Test", "Test::META"  ],
"resources"    : [ "scripts/cat.pl" ]
}

t/cat.t

#!/bin/env perl6
use Test;

constant GREETING = 'Hello world!';
my $filename = 'test.txt';
spurt($filename, GREETING);

my $p5 = qqx{ resources/scripts/cat.pl $filename };
my $p6 = qqx{ bin/run_cat              $filename };

is $p6, $p5, 'wrapped script gives same result as original';

is $p6, GREETING, "output is '{GREETING}' as expected";

unlink $filename;

done-testing;

Thanks @moritz and @ugexe for getting me pointed in the right direction!

like image 80
Christopher Bottoms Avatar answered Nov 18 '22 08:11

Christopher Bottoms