7

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?

Community
  • 1
  • 1
Philip Potter
  • 8,975
  • 2
  • 37
  • 47

3 Answers3

4

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
  • 8,975
  • 2
  • 37
  • 47
  • 1
    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 Aug 29 '10 at 14:48
  • @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 Aug 29 '10 at 14:58
  • Hmmm... The Module::Build::API page says that needs_compiler is available after M::B version .36, and that it is set to true automatically if c_source exists or xs code is found somewhere. If true, it automatically adds ExtUtils::CBuilder as a build_requires item. – Nate Glenn Aug 20 '12 at 17:36
2

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
  • 16,274
  • 24
  • 118
  • 243
  • 1
    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 Aug 28 '10 at 21:19
1

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
  • 5,034
  • 1
  • 19
  • 27
  • Thanks for your answer. What do you use to build your distribution? – Philip Potter Aug 28 '10 at 21:21
  • 1
    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 Aug 29 '10 at 12:00
  • 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 Aug 29 '10 at 12:46
  • 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 Aug 29 '10 at 14:44