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 makestry_compile_runrun 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 thedefinesmethod, or via thewrite_definesmethod.push_args => BOOLβ if true, any ofextra_compiler_flags,extra_linker_flags,include_dirs,libraries,library_dirsordefineswill have its value pushed on success (e.g.push_include_dirsfor theinclude_dirsargument) π
π 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 thedefinesmethod, or via thewrite_definesmethod.
π 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 thedefinesmethod, or via thewrite_definesmethod.
π₯ 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 thedefinesmethod, or via thewrite_definesmethod.
π 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 thedefinesmethod, or via thewrite_definesmethod.
β 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.undefis 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 thedefinesmethod, or via thewrite_definesmethod.
π 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. π«Ά
π COPYRIGHT AND LICENSE π
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
- ubuntu stonking: libextutils-builder-compiler-perl 0.037-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms