=pod

=for comment
DO NOT EDIT. This Pod was generated by Swim v0.1.31.
See http://github.com/ingydotnet/swim-pm#readme

=encoding utf8

=head1 NAME

Inline::Module::Tutorial - Make "XS" modules for CPAN. The easy way!

=head1 OVERVIEW

This tutorial will teach you how to write "extension" modules for CPAN using
L<Inline::Module>. The old way to do this is with "XS", Perl's mechanism for
binding C and C++ code to Perl. Inline::Module lets you do this much easier,
avoiding the need to learn XS, but delivering results that are as robust as
hand-written XS.

=head1 BASICS

The tutorial starts by showing you how an example module (that is actually on
CPAN), was created with Inline::Module. The module is called
L<Acme::Math::XS>, and its purpose (besides trivial math functions) is to
demonstrate how to do this.

=head2 The Makefile.PL

No matter which framework you use to make modules (L<ExtUtils::MakeMaker>,
L<Dist::Zilla>) etc, you'll need to add a little B<metadata> to the controls.
For now we'll just show C<Makefile.PL> (L<ExtUtils::MakeMaker>) way:

    use lib 'inc';
    use ExtUtils::MakeMaker;
    use Inline::Module;

    WriteMakefile(
      NAME => 'Acme::Math::XS',
      ...
      postamble => {
        inline => {
          module => 'Acme::Math::XS',
          stub => 'Acme::Math::XS::Inline',
          ilsm => 'Inline::C',
        },
      },
    );

So you need to C<use Inline::Module> and add a C<postamble> section with an
C<inline> section (with at least a C<module> name) to C<WriteMakefile>. The
arguments specify the information that L<Inline::Module> needs to do the right
things. The C<stub> and C<ilsm> values above are the defaults, so not really
needed in that example. All the values for those keys can be either a string
or an array ref of strings (ie single or multiple values).

NOTE: You also need to add C<inc> to @INC, even if doesn't exist while you are
      developing and testing. It will exist when you ship it to CPAN, and the
      C<make install> process needs it to work properly. The Makefile.PL or
      Build.PL will actually die if you don't put C<inc> first in C<@INC>.

See L<Alt::Acme::Math::XS::EUMM> for a working example on CPAN.

=head2 Meta Values

Just to reiterate, whether you are using L<ExtUtils::MakeMaker>,
L<Module::Build>, L<Module::Install>, L<Dist::Zilla> or L<Zilla::Dist>, you
need to specify 3 Meta values:

=over

=item C<module>

One or more module names that live under the C<lib> directory and use Inline
inside. This value is required in all cases (no default).

=item C<stub>

One or more names of I<stub> modules, that are referenced in the C<module>
modules listed above. The default is to add '::Inline' to each value of the
C<module> keyword.

=item C<ilsm>

A list of the Inline Language Support Modules (ILSMs) needed. Usually just one
of L<Inline::C> (the default) or L<Inline::CPP>.

=back

Each framework list above has a slightly different way to express the values,
but they will all seem normal in that framework. See below.

=head2 The Module

Next we'll "inline" some C code into a Perl module called
C<lib/Acme/Math/XS.pm>. Here is the real module, but condensed a bit:

    use strict; use warnings;
    package Acme::Math::XS;
    our $VERSION = '1.2.3';
    use Exporter 'import';
    our @EXPORT = qw(add subtract);
    use Acme::Math::XS::Inline C => <<'...';
    long add(long a, long b) { return a + b; }
    long subtract(long a, long b) { return a - b; }
    ...
    1;

Normally you use L<Inline::C> like this:

    use Inline C => '<... c code ...>';

but here we just change C<Inline> to C<Acme::Math::XS::Inline>. This is the
key part of how Inline::Module works. Since we want to I<use> Inline but not
I<depend> on it when the user installs this module, we do this trick. The
C<::Inline> module is a little generated B<stub> that knows how to do all the
right magics.

=head2 The Inline Stub Module

Next you'll need to actually generate the stub module. Run this command:

    perl -MInline::Module=makestub,Acme::Math::XS::Inline

You'll get a C<lib/Acme/Math/XS/Inline.pm> that looks like this:

    use strict; use warnings;
    package Acme::Math::XS::Inline;
    use Inline::Module stub => 'v2';
    1;

The astute tutorialist will note that this module depends on
C<Inline::Module>, and that's a no-no. That's because this stub is used for
author side development and testing, and another stub replaces it at module
release time.

The replacement stub will look like this:

    use strict; use warnings;
    package Acme::Math::XS::Inline;
    use base 'DynaLoader';
    bootstrap Acme::Math::XS::Inline;
    1;

And everything is fine. We are just using Dynaloader, the age old loader of
extension libraries. As long the shared library stuff gets built into the
C<blib> directory at user build time (and it does!) we are good to go.

=head2 Automatic Stub Generation

The stub module is generated code, and many people don't like to commit
generated code. There are a couple ways to deal with this.

The first is just to commit it anyway, because it only has to change very
rarely; when you install a new Inline::Module whose API version has changed.
You will get an error telling you to regenerate the stub. One main advantage
of this is that your project collaborators don't need to know about
generating the stub.

The second way is to ignore it in your source control (ie C<.gitignore> file).

=head2 Testing

There are a few ways to test stuff and I'll describe them here. They should be
familiar to most module authors.

=over

=item C<prove -l t/>

This is the easiest and most common method of testing for B<non>-XS module
authors. Since Inline is involved, the compilation steps just work.

With XS, you typically need to run C<perl Makefile.PL && make> first, and you
also need to add the C<-b> flag to C<prove> to tell it to look in the new
C<blib>. Then you need to continually make sure to repeat this every time you
change C code. With Inline, you can relax a bit.

=item C<perl Makefile.PL && make test>

You can also use the XS style. It all works out the same.

=item C<prove -b t/>

In this style, you are just invoking the C<blib> results directly, and Inline
is not involved. Use this if you want to know that no nothing is up a sleeve,
but don't forget that auto-compilation can't happen this way.

=back

=head2 Making a Distribution (Tarball)

Now it's time to make the final product and ship it to CPAN. The mechanics are
dead simple:

    perl Makefile.PL
    make dist

Same as any other module. Some magic is happening though to make it all work.
You asked for this magic in your C<Makefile.PL> changes!

C<Inline::Module> modifies 2 targets in the Makefile:

=over

=item C<distdir>

This is the target that buils the distribution directory (before it is
tarred up).

=item C<pure_all>

This odd sounding rule is actually the primary/default rule. It gets invoked
when you run:

    make

without arguments. In other words, the build step.

=back

In the C<distdir> phase, we need to:

=over

=item * Add the C<Inline> modules that control building, under C<inc/>:

=over

=item * Inline::Module

=item * Inline

=item * Inline::C

=item * a few helper modules

=back

=back

We also need to move the test/build stub module under C<inc/> and put the
C<Dynaloader> version in its place under C<lib>.

The C<pure_all> phase is simply tweaked to rearrange the exact location of
things that get generated under C<blib>. Then they are ready to be installed
properly/normally by C<make install>.

=head2 Ship It

Assuming you've done all the other parts of normal CPAN modules authoring, we
are done here. Upload your module and watch CPAN Testers for results on tons
of different platforms.

=head1 USING OTHER CPAN BUILD PLATFORMS

This section will describe how to do everything we just did, using the other
popular CPAN build systems, like L<Dist::Zilla>.

=head2 L<Dist::Zilla>

For L<Dist::Zilla>, install L<Dist::Zilla::Plugin::InlineModule> and add this
to your C<dist.ini> file:

    [InlineModule]
    module = Acme::Math::XS
    stub = Acme::Math::XS::Inline
    ilsm = Inline::C

Again, the last 2 lines are defaults. You can use any of the keywords
multiple times.

See L<Alt::Acme::Math::XS::DistZilla> for a working example on CPAN.

=head2 L<Module::Build>

Install L<Module::Build::InlineModule> and write a C<Build.PL> file that looks
like this:

    use lib 'inc';
    use Module::Build::InlineModule;

    Module::Build::InlineModule->new(
      dist_name => 'Alt-Acme-Math-XS-ModuleBuild',
      ...
      inline => {
        module => 'Acme::Math::XS',
        stub => 'Acme::Math::XS::Inline',
        ilsm => 'Inline::C',
      },
    )->create_build_script();

See L<Alt::Acme::Math::XS::ModuleBuild> for a working example on CPAN.

=head2 L<Module::Install>

Install L<Module::Build::InlineModule> and write a C<Makefile.PL> that looks
like this:

    use inc::Module::Install;

    name 'Alt-Acme-Math-XS-ModuleInstall';
    ...
    inline
      module => 'Acme::Math::XS',
      stub => 'Acme::Math::XS::Inline',
      ilsm => 'Inline::C';

    WriteAll;

See L<Alt::Acme::Math::XS::ModuleInstall> for a working example on CPAN.

=head2 L<Zilla::Dist>

Just add these lines to your Meta file:

    =zild:
      inline:
        module: Acme::Math::XS
        stub: Acme::Math::XS::Inline
        ilsm: Inline::C

See L<Alt::Acme::Math::XS::ZillaDist> for a working example on CPAN.

=head1 EXTERNAL FILES

Putting a lot of C code in your Perl might be too messy. You can just move it
to a C<.c> file, and then change your Perl to this:

    use Acme::Math::XS::Inline C => 'lib/Acme/Math/XS.c';

Note: You can put the C<.c> file anywhere you want, except at the top level.
      Doing that will confuse the Makefile. If you put it under C<lib> like
      above, it will get installed like C<.pm> files. This might be desirable
      since it opens all your source (just lie when it's actually I<inline>).

=head1 INLINE::CPP SPECIFICS

Under the hood, L<Inline::Module> does quite a few things different when you
use L<Inline::CPP>, but this should be mostly transparent to you. Just make
sure you declare your C<ilsm> keyword to be C<Inline::CPP> and everything
should work fine.

=head1 USING LANGUAGES OTHER THAN C<C> AND C<C++>

It I<may> be possible (though highly experimental) to use other Inline
Language Support Modules (ILSMs), like Java or Python. Simply list your ILSM
of choice in the Meta section, and see what happens.

Report any issues to: L<https://github.com/ingydotnet/inline-module-pm/issues>

=head1 DOCUMENT STATUS

This document reflects the current state of C<Inline::Module>. At this time,
it is brand new, so please report any bugs and/or misgivings.

=head1 AUTHORS

=over

=item * Ingy döt Net <ingy@cpan.org>

=item * David Oswald <davido@cpan.org>

=back

=head1 COPYRIGHT

Copyright 2014. Ingy döt Net.

=cut
