Home / Alt manpages / h2xs(1)

  • h2xs(1)
  • User command
  • linux

Build a Perl Extension Skeleton with h2xs

You will finish with a generated Perl extension directory that is ready for you to edit, or with a pure-Perl module skeleton when no C or XS code is needed. The 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. In particular, 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. That is convenient for a new skeleton, but it does not mean that 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 that is 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 require 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 a proof that every generated conversion is correct. Read and edit the XS, typemap, module documentation, and tests before distributing it.

Checkpoint

The important success signal is that perl Makefile.PL, make, and make test complete for your actual toolchain. A generated file list alone proves only that 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 prevents a rerun from 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, inspect git diff if it is tracked, and confirm that 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

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