Home / Alt manpages / h2xs(1)

  • h2xs(1)
  • User command
  • linux

Build a Perl Extension Skeleton with h2xs

Starting a Perl module from a blank directory is fiddly enough that most people reach for h2xs to generate the boilerplate first. You will end up with a generated extension directory ready for you to edit, or a pure-Perl module skeleton when no C or XS code is needed. Examples match h2xs 1.23 from the installed perl package version 5.38.2-3.2ubuntu0.6.

Allow about fifteen minutes for the skeleton and its first inspection. You need Perl, a shell, and a writable working directory. The normal workflow is unprivileged. Do not run h2xs with sudo: it creates source files in the current directory, and root-owned output is awkward to repair.

1. Check the installed command

Start with read-only checks so you know which executable and option syntax you are using:

$ command -v h2xs
/usr/bin/h2xs
$ dpkg-query -W -f='${Package} ${Version}\n' perl
perl 5.38.2-3.2ubuntu0.6
$ h2xs -h
h2xs [OPTIONS ... ] [headerfile [extra_libraries]]
version: 1.23
...

The help output is the installed program's contract. h2xs uses -n to set the Perl module name, -X to omit the XS portion, and -O to permit overwriting an existing extension directory.

Checkpoint

If command -v finds nothing, stop and install or enable Perl through your normal system-management process. Do not copy a random h2xs script into a project.

2. Create a pure-Perl module skeleton

Use -X when you want a module layout without generated C binding code. Give the module an explicit name so the directory and package name are predictable:

$ mkdir -p ~/src/perl-modules
$ cd ~/src/perl-modules
$ h2xs -X -n Demo::Widget
Defaulting to backwards compatibility with perl 5.38.2
Writing Demo-Widget/lib/Demo/Widget.pm
Writing Demo-Widget/Makefile.PL
Writing Demo-Widget/README
Writing Demo-Widget/t/Demo-Widget.t
Writing Demo-Widget/Changes
Writing Demo-Widget/MANIFEST
$ find Demo-Widget -maxdepth 3 -type f -print | sort
Demo-Widget/Changes
Demo-Widget/MANIFEST
Demo-Widget/Makefile.PL
Demo-Widget/README
Demo-Widget/lib/Demo/Widget.pm
Demo-Widget/t/Demo-Widget.t

The hyphenated top-level directory is a distribution directory, while the module file follows the Perl namespace under lib/. The generated module has a placeholder version, documentation and package boilerplate: edit those before treating the result as a finished module.

-X implicitly enables the options that omit constants and force creation. Convenient for a new skeleton, but it does not mean an existing directory is safe to replace.

3. Generate an XS extension from a header

For a C library, pass the header file and name the Perl module separately. Replace the placeholder with a real header readable from the standard include paths, or from the location your build expects:

$ cd ~/src/perl-modules
$ h2xs -n Demo::Greeting /path/to/greeting.h
Writing Demo-Greeting/lib/Demo/Greeting.pm
Writing Demo-Greeting/Greeting.xs
Writing Demo-Greeting/Makefile.PL
Writing Demo-Greeting/README
Writing Demo-Greeting/t/Demo-Greeting.t
Writing Demo-Greeting/Changes
Writing Demo-Greeting/MANIFEST

h2xs scans header declarations and creates Perl code for constants it can find. It does not understand every C interface well enough to produce a finished binding: function declarations, pointer ownership, arrays, and address-and-length pairs can all need hand-written XS and typemap work.

If the extension links an extra library, put compiler-style library arguments after the header, for example -lm or -L/opt/example/lib -lexample. h2xs records these for the generated Makefile.PL, which later checks how the library can be loaded. Do not add library flags just because a package name sounds related.

4. Make a deliberately empty extension skeleton

When you have C and header files to copy into the extension directory first, use a dummy run to establish the layout:

$ cd ~/src/perl-modules
$ h2xs -Afn Demo::Greeting
Defaulting to backwards compatibility with perl 5.38.2
Writing Demo-Greeting/lib/Demo/Greeting.pm
Writing Demo-Greeting/Makefile.PL
Writing Demo-Greeting/README
Writing Demo-Greeting/t/Demo-Greeting.t
Writing Demo-Greeting/Changes
Writing Demo-Greeting/MANIFEST

Copy your .h and .c files into Demo-Greeting, then regenerate the autogenerated files with:

$ cd Demo-Greeting
$ h2xs -O -xan Demo::Greeting greeting.h
$ perl Makefile.PL
$ make
$ make test

-x asks h2xs to generate XSUBs from function declarations and requires the C::Scan package. The result is a starting point, not proof that every generated conversion is correct. Read and edit the XS, typemap, module documentation and tests before distributing it.

Checkpoint

The real success signal is that perl Makefile.PL, make and make test complete for your actual toolchain. A generated file list only proves h2xs wrote files.

5. Protect existing work

h2xs refuses to overwrite a pre-existing extension directory unless you pass -O. That refusal is useful: it stops a rerun silently replacing edits to XS, Perl, tests or documentation.

$ h2xs -X -n Demo::Widget
Won't overwrite existing Demo-Widget
$ printf 'exit status: %s\n' "$?"
exit status: 2

Warning

-O is destructive to the generated directory. Before using it, commit or copy the directory, check git diff if it is tracked, and confirm the module name and destination are correct. There is no h2xs undo command; recovery means restoring your backup or version-control revision.

Prefer a new module name or a fresh working directory while experimenting. If you need to rerun generation after editing a header, make a distribution archive early with make dist, as the manpage recommends, so your edits can be compared with the regenerated skeleton.

6. Handle the options that commonly mislead

Use -b VERSION when the generated module must be compatible with an older Perl. The installed h2xs defaults to compatibility with the Perl used to run it, and the generated Makefile.PL records that version. A compatibility version newer than the running Perl has no effect.

Use -v VERSION for the module version. The default is 0.01, or 0.00_01 with -B. The supplied version should be numeric: do not confuse this with the h2xs program version shown by -h.

Use -c to omit the constant mechanism, -A to omit autoload facilities as well, and -P to omit the generated POD stub. These change the template. They do not make an otherwise unsafe or incomplete C interface safe.

Done means

  • Version confirmed. You checked the installed h2xs is version 1.23 from Perl 5.38.2.
  • Right skeleton chosen. You chose -X for a pure-Perl skeleton, or supplied a real header for an XS extension.
  • Output reviewed. You inspected the generated module, Makefile, tests and documentation.
  • Build proven. You ran the generated build and tests before relying on the extension.
  • Overwrite protected. You kept the output unprivileged and did not use -O without a recoverable backup.