views:

78

answers:

3

I've recently started learning XS using perlxstut and the tutorial suggests that I create my module using the old h2xs tool to create an ExtUtils::MakeMaker-based project. However for pure Perl projects, h2xs/EUMM has long been disfavoured in favour of Module::Install, Module::Build or Dist::Zilla.

Is there a more modern way of creating XS projects? Can Module::Starter create XS projects? Can Module::Build or Dist::Zilla build XS projects? Their pod pages are silent on the matter.

On the flip side, does the criticism that was levelled at h2xs/EUMM apply to XS projects? If you need a C compiler anyway, is it reasonable to demand a make tool as well?

EDIT: I see this question answers my question about creating a project. I'd still like to know about building: is EUMM the only option, or are Module::Build and Dist::Zilla also capable of building XS?

+2  A: 

Dist::Zilla is not a replacement for EUMM or Module::Build, what it will do is generate a Makefile.Pl (etc) for you, I would not be surprised to hear that it can't do this for an XS project, but there are ways of managing your own for a dzil project. It can work with whatever Makefile.Pl it is provided with (or Build.pl).

So my answer on the Dist::Zilla part of your question is, Dist::Zilla does not fill that role in a project.

xenoterracide
Thanks for this, it has clarified dzil greatly in my mind. Investigating further identifies Dist::Zilla::Plugin::MakeMaker::Awesome which claims partial XS capability.
Philip Potter
+1  A: 

I always just use some fairly simple XS distribution as a starting point. h2xs can do some of the XS generation by parsing a header, but most of the time, I found that too limited to be useful.

If you're planning to wrap C++, you may want to take a look at Module::Build::WithXSpp.

tsee
Thanks for your answer. What do you use to build your distribution?
Philip Potter
I started out using MakeMaker since that seemed the simplest. Nowadays, I usually use Module::Build (which, I'd say, has a bit more of a learnig curve for XS/C stuff) because I feel it gives me more flexibility without having to hack Makefiles. It was also fairly easy to extend to do the crazy magic in Module::Build::WithXSpp.
tsee
could you provide a Module::Build example for XS or review the one in my answer? I'm new to this and I'm trying to find best practices for creating XS projects.
Philip Potter
I'll point to only modules that I know because I'm too lazy to do much research. That obviously usually means my modules. They don't necessarily reflect best practices. If you plan to use XS++, then this is as simple as it gets: http://search.cpan.org/~smueller/Math-ThinPlateSpline-0.05/ For plain XS, I have no utterly vanilla Build.PL. This is a complicated example, but you can simply remove all the special logic: http://search.cpan.org/~smueller/SOOT-0.09/ Here's an example of using Module::Install (from Daisuke Maki): http://search.cpan.org/~dmaki/ZeroMQ-0.02/
tsee
+2  A: 

It turns out that Module::Build is perfectly capable of compiling XS. Here is a complete Build.PL I managed to scrape together:

use strict;
use Module::Build;

my $build = Module::Build->new(
    module_name  => 'Chocolate::Belgian',
    dynamic_config => 1,
    license      => 'perl',
    requires     => {
        'Module::Build' => '0.19', # xs
        'Test::More' => 0,
    },
    extra_compiler_flags => '-Iinclude',
    extra_linker_flags   => '',
    c_source     => 'src',
    needs_compiler => 1,
    xs_files     => {
        './Belgian.xs' => 'lib/Chocolate/Belgian.xs',
    },

   );

$build->create_build_script;

This will build a distribution with .h include files (such as ppport.h) in the include/ directory, .c source files in the src/ directory, and an .xs file corresponding to package Chocolate::Belgian in the project base directory.

extra_compiler_flags corresponds to make CCFLAGS, while extra_linker_flags corresponds to LIBS (so you might want -lm there to link the C math library).

Philip Potter
Since you were asking for feedback in a comment: This looks fine after a quick inspection. Nits: Maybe add a dependency on ExtUtils::CBuilder (needs_compiler might be doing this already). Are you quite certain you need dynamic_config: 1? I bet you don't. Furthermore, you may want to add Module::Build to configure_requires instead of requires. I believe it automatically adds a dependency on the most recent version if it doesn't find it at all. Try removing that line, running "./Build dist" and inspecting the generated META.yml/META.json for mention of Module::Build.
tsee
@tsee: thanks very much for your review. I've made it community wiki, so you can put in any changes you want if you like.
Philip Potter