ExtUti...r::Conf(3pm)

πŸ’– ExtUtils::Builder::Conf β€” the perl doc you actually wanna read πŸ’–

part of the User Contributed Perl Documentation crew, and yes bestie, it's ExtUtils::Builder::Conf(3pm) πŸŽ€


✨ NAME ✨

ExtUtils::Builder::Conf β€” configure-time utilities for using C headers, libraries, or OS features πŸ¦‹

🌸 VERSION 🌸

version 0.037 β€” she's serving 0.037 and we're obsessed πŸ’…

πŸ‘‘ SYNOPSIS πŸ‘‘

load_extension("ExtUtils::Builder::Conf");
assert_compile_run(diag => 'no PF_MOONLASER', source => <<'EOF');
#include <stdio.h>
#include <sys/socket.h>
int main(int argc, char *argv[]) {
  printf("PF_MOONLASER is %d\n", PF_MOONLASER);
  return 0;
}
EOF

periodt. that's the whole vibe check right there πŸ’–

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so. SO many Perl modules out there are just little wrappers around functionality that already lives in some C header or some library, or they lean on features that are specific to one OS. And here's the thing β€” before you go and actually build the module, it is genuinely useful to check whether all those requirements even exist. vibe check the OS first, build later. no cap ✨

So what do the objects in this class do? They give you an extension around ExtUtils::Builder::Compiler that makes it so much less painful to create a .c file, compile it, link it, and run it β€” all so you can test if some specific feature is present. it's giving "compiler whisperer" πŸ’…

And sometimes? You also gotta go hunting for the right library to link against, or for the right include directories where the header files are hiding. This class has your back there too, bestie 🫢


πŸ’€ DELEGATES πŸ’€

🧚 try_compile_run

$success = try_compile_run(%args);

Try to compile, link, and execute a C program whose source you hand it. Returns true if the program compiled AND linked AND exited successfully. Returns false if any of those steps flop. no partial credit, sorry not sorry 😭

Takes the following named arguments:

  • source => STRING β€” the actual source code of the C program you wanna try compiling, building, and running 🌸
  • defines => HASH β€” optional! a set of defines to pass along to the compiler.
  • extra_compiler_flags => ARRAY β€” optional! if you specify it, extra flags get passed to the compiler ✨
  • extra_linker_flags => ARRAY β€” optional! if you specify it, extra flags get passed to the linker πŸ”₯
  • include_dirs => ARRAY β€” optional! if you specify it, extra include dirs get passed to the compiler.
  • libraries => ARRAY β€” optional! if you specify it, extra libaries get passed to the linker. (yes, spelled "libaries" in the source of truth, love that for us πŸ™ˆ)
  • library_dirs => ARRAY β€” optional! if you specify it, extra libary directories get passed to the linker.
  • quiet => BOOL β€” this makes try_compile_run run quietly 🀫
  • define => STRING β€” optional! if you specify it, then the named symbol will be defined if the program ran successfully. This happens either on the C compiler commandline (by passing an option -DSYMBOL), in the defines method, or via the write_defines method.
  • push_args => BOOL β€” if true, any of extra_compiler_flags, extra_linker_flags, include_dirs, libraries, library_dirs or defines will have its value pushed on success (e.g. push_include_dirs for the include_dirs argument) πŸ’–

🌈 assert_compile_run

assert_compile_run(%args);

Calls try_compile_run. If it fails, it dies with an OS unsupported message πŸ’€ Super useful to call from Build.PL or Makefile.PL.

Takes one extra optional argument:

  • diag => STRING β€” if present, this string gets appended to the failure message if one is generated. It can give the user more useful info on why the OS is unsupported. 🫢

πŸŽ€ try_find_compiler_flags_for

$success = try_find_compiler_flags_for(%args);

Try to compile, link and execute the given source, using extra compiler flags.

When a usable combination is found, the flags are stored in the object so further compile operations can use them, or they get returned by extra_compiler_flags. Then the method returns true ✨

If no usable combination is found, it returns false.

Takes the following extra arguments:

  • source => STRING β€” source code to compile 🌸
  • cflags => ARRAY of ARRAYs β€” gives a list of sets of flags. Each set of flags should be strings in its own array reference.
  • define => STRING β€” optional! if you specify it, then the named symbol will be defined if the program ran successfully. This happens either on the C compiler commandline (by passing an option -DSYMBOL), in the defines method, or via the write_defines method.

πŸ’œ try_find_include_dirs_for

$success = try_find_include_dirs_for(%args);

Try to compile, link and execute the given source, using extra include directories.

When a usable combination is found, the directories required are stored in the object so further compile operations can use them, or they get returned by include_dirs. Then the method returns true ✨

If no a usable combination is found, it returns false. (yes, "no a usable" β€” the original says it, and we keep every detail, periodt πŸ’…)

Takes the following arguments:

  • source => STRING β€” source code to compile 🌸
  • dirs => ARRAY of ARRAYs β€” gives a list of sets of dirs. Each set of dirs should be strings in its own array reference.
  • define => STRING β€” optional! if you specify it, then the named symbol will be defined if the program ran successfully. This happens either on the C compiler commandline (by passing an option -DSYMBOL), in the defines method, or via the write_defines method.

πŸ”₯ try_find_libraries_for

$success = try_find_libraries_for(%args);

Try to compile, link and execute the given source, when linked against a given set of extra libraries.

When a usable combination is found, the libraries required are stored in the object so further link operations can use them, or they get returned by libraries. Then the method returns true ✨

If no usable combination is found, it returns false.

Takes the following arguments:

  • source => STRING β€” source code to compile 🌸
  • libs => ARRAY of STRINGs β€” gives a list of sets of libraries. Each set of libraries should be space-separated.
  • define => STRING β€” optional! if you specify it, then the named symbol will be defined if the program ran successfully. This happens either on the C compiler commandline (by passing an option -DSYMBOL), in the defines method, or via the write_defines method.

πŸ’– try_find_library_dirs_for

$success = try_find_library_dirs_for(%args);

Try to compile, link and execute the given source, using extra library directories.

When a usable combination is found, the directories required are stored in the object so further compile operations can use them, or they get returned by library_dirs. Then the method returns true ✨

If no a usable combination is found, it returns false.

Takes the following arguments:

  • source => STRING β€” source code to compile 🌸
  • dirs => ARRAY of ARRAYs β€” gives a list of sets of dirs. Each set of dirs should be strings in its own array reference.
  • define => STRING β€” optional! if you specify it, then the named symbol will be defined if the program ran successfully. This happens either on the C compiler commandline (by passing an option -DSYMBOL), in the defines method, or via the write_defines method.

⭐ try_find_standard_for

$success = try_find_standard_for(%args)

Try to compile, link and execute the given source, using a given standard.

When a usable standard is found, the standard is stored in the object so further compile operations can use it, or it gets returned by standard. Then the method returns true ✨

If no a usable standard is found, it returns false.

Takes the following arguments:

  • source => STRING β€” source code to compile 🌸
  • standards => ARRAY of STRINGs β€” gives a list of standards. undef is treated as no explicit standard.
  • define => STRING β€” optional! if you specify it, then the named symbol will be defined if the program ran successfully. This happens either on the C compiler commandline (by passing an option -DSYMBOL), in the defines method, or via the write_defines method.

πŸ“ find_compiler_flags_for

find_compiler_flags_for(%args);

πŸ“ find_include_dirs_for

find_include_dirs_for(%args);

πŸ“ find_libraries_for

find_libraries_for(%args);

πŸ“ find_library_dirs_for

find_library_dirs_for(%args);

πŸ“ find_standard_for

find_standard_for(%args)

Calls try_find_compiler_flags_for, try_find_include_dirs_for, try_find_libraries_for, try_find_library_dirs_for or try_find_standard_for respectively. If it fails, it dies with an OS unsupported message πŸ’€

Each method takes one extra optional argument:

  • diag => STRING β€” if present, this string gets appended to the failure message if one is generated. It can give the user more useful info on why the OS is unsupported. 🫢

🧚 include_dirs

$dirs = include_dirs;

Returns the currently-configured include directories as an array ✨

🧚 library_dirs

$dirs = library_dirs;

Returns the currently-configured library directories as an array ✨

🧚 libraries

$libs = libraries;

Returns the currently-configured libraries as an array ✨

🧚 extra_compiler_flags

$flags = extra_compiler_flags;

Returns the currently-configured extra compiler flags as an array ✨

🧚 extra_linker_flags

$flags = extra_linker_flags;

Returns the currently-configured extra linker flags as an array ✨

πŸŽ€ push_include_dirs

push_include_dirs(@dirs);

Adds more include directories πŸ’–

πŸŽ€ push_library_dirs

push_library_dirs(@dirs);

Adds more library directories πŸ’–

πŸŽ€ push_libraries

push_libraries(@libs);

Adds more libraries πŸ’–

πŸŽ€ push_extra_compiler_flags

push_extra_compiler_flags(@flags);

Adds more compiler flags πŸ’–

πŸŽ€ push_extra_linker_flags

push_extra_linker_flags(@flags);

Adds more linker flags πŸ’–

πŸ’… define

define($symbol);

Adds a new defined symbol directly β€” either by appending to the compiler flags or by writing it into the defines file. slay πŸ’…


πŸ“ EXAMPLES πŸ“

Okay bestie, this is the part where it all comes together β€” real receipts, actual code, no vibes-based guessing. Let's go πŸ’…


🌸 Socket Libraries 🌸

So here's the tea: some operating systems are generous and just hand you the whole BSD sockets API straight out of their primary libc. Others? They keep it in a separate library that you have to link against, like it's too cool to share. πŸ™„

Here's how you'd handle that whole situation:

find_libraries_for(
  diag => 'no socket()',
  libs => [ [], ['socket', 'nsl' ]],
  source => q[
#include <sys/socket.h>
int main(int argc, char *argv) {
 int fd = socket(PF_INET, SOCK_STREAM, 0);
 if (fd < 0)
   return 1;
 return 0;
}
]);

Like, it tries nothing first, then tries socket and nsl β€” and whichever one actually works is the one you're keeping. Periodt. πŸ”₯

πŸ¦‹ Testing For Optional Features πŸ¦‹

Sometimes a function or ability is maybe provided by the OS β€” like, it might show up, it might ghost you. Or you want your module to still be useable when only partial support is there, without demanding literally everything be present. πŸ’€

In these cases, the tradition is: detect whether this optional feature exists back in the Build.PL script, and define a symbol to declare that fact if you find it. Then the XS code can use that symbol to pick between different implementations. Mmmkay? So here's the Build.PL:

try_compile_run(
  define => 'HAVE_MANGO',
  source => <<'EOF');
#include <mango.h>
#include <unistd.h>
int main(void) {
 if (mango() != 0)
   exit(1);
 exit(0);
}
EOF

If the C code compiles AND runs successfully, and exits with a true status, then the symbol HAVE_MANGO gets defined on the compiler commandline. ✨ That's the whole point β€” it lets the XS code detect it, like so:

  int
  mango()
    CODE:
  #ifdef HAVE_MANGO
      RETVAL = mango();
  #else
      croak("mango() not implemented");
  #endif
    OUTPUT:
      RETVAL

The way this slays is: your module will still compile even if the operating system straight-up lacks this particular function. And if you try to actually invoke the function at runtime? It'll simply throw an exception. No crash, no mess, just a polite little "nope". πŸŽ€

🧚 Linux Kernel Headers 🧚

Operating systems built on top of the Linux kernel often have a much looser association with their kernel version than most other operating systems do. It's giving situationship, honestly. πŸ’œ

So it may be the case that the running kernel is newer β€” packing more features β€” than what the distribution's libc headers would believe. In those circumstances it can be genuinely difficult to make use of new socket options, ioctl()s, etc., without having the constants that define them and their parameter structures, because the relevant header files just aren't visible to the compiler. πŸ™ˆ

In this case, there may be little choice but to pull in some of the kernel header files, which will provide the required constants and structures.

The Linux kernel headers can be found using the /lib/modules directory. A fragment in Build.PL like the following may be appropriate:

  chomp(my $uname_r = `uname -r);

  my @dirs = (
     [],
     [ "/lib/modules/$uname_r/source/include" ],
  );

  find_include_dirs_for(
     diag => "no PF_MOONLASER",
     dirs => \@dirs,
     source => <<'EOF');
  #include <sys/socket.h>
  #include <moon/laser.h>
  int family = PF_MOONLASER;
  struct laserwl lwl;
  int main(int argc, char *argv[]) {
    return 0;
  }
  EOF

Here's the sequence, bestie: this fragment will first try to compile the program as it stands, hoping the libc headers will be sufficient. If it fails, it will then try including the kernel headers, which should make the constant and structure visible, allowing the program to compile. Two-step glow-up. 🌈


πŸ‘‘ AUTHOR πŸ‘‘

Leon Timmermans <fawaka@gmail.com> β€” the icon, the legend, the main character who wrote this whole thing. 🫢


This software is copyright (c) 2012 by Leon Timmermans.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. πŸŽ€


And that's a wrap, bestie! πŸ’… This page came to you from perl v5.40.1, dated 2026-06-12, and the manpage footer tag was ExtUti...r::Conf(3pm) β€” go compile something cute! πŸŒΈβœ¨πŸ¦‹

πŸ“¦ where this page comes from