Config-AutoConf-0.21/000755 000765 000024 00000000000 12061106415 014436 5ustar00ambsstaff000000 000000 Config-AutoConf-0.21/Changes000644 000765 000024 00000007324 12056667403 015754 0ustar00ambsstaff000000 000000 Revision history for Config-AutoConf 0.21 Dec 2, 2012 - Flag -lm tests as 'TODO' as they might fail in some Windows machines 0.20 Nov 9, 2012 - Add stdint.h into check_default_headers - Make POD tests author only. 0.19 Feb 7, 2012 - Added new method, check_lm 0.18 Feb 2, 2012 - msg_methods msg prefix can be configured. - Added new methods: (Jens Rehsack) check_alignof_type, check_alignof_types, check_sizeof_type, check_sizeof_types, compute_int, lang_build_bool_test, check_dirent_header, push_compiler_flags, push_includes, push_libraries, push_library_paths, push_link_flags, push_preprocess_flags. 0.17 Jan 4, 2012 - Re-fixed tests that do not run in <= v5.010 0.17_02 Jan 3, 2012 - Fixed tests that do not run on older Perl version. 0.17_01 Jan 2, 2012 - New object oriented interface (Jens Rehsack) - Added new methods: (Jens Rehsack) cache_val, check_all_headers, check_cached, check_decl, check_decls, check_default_headers, check_lib, check_member, check_members, check_stdc_headers, check_type, check_types, compile_if_else, define_var, lang_build_program, lang_call, link_if_else, msg_checking, msg_error, msg_failure, msg_notice, msg_result, msg_warn, pop_lang, push_lang, search_libs, write_config_h - check_headers rewritten (Jens Rehsack) - Use proper 'extern "C"' code 0.16 Sep 23, 2010 - Config::AutoConf::Linker moved to ExtUtils::LibBuilder. 0.15 Mar 8, 2010 - Config::AutoConf::Linker more silent. 0.14 Feb 14, 2010 - Added rewind to Linker.pm module. This code is still under heavy tests. 0.13 Jun 2, 2009 - First stable release with code to detect how to build a C dynamic library. 0.12_3 Jun 1, 2009 - Trying other way arround to change LD_LIBRARY_PATH under t/04, that was failing under FreeBSD. 0.12_2 May 19, 2009 - Added t/04 that was missing from MANIFEST 0.12_1 May 18, 2009 - Added code to detect how to build a library. It is a big, really big hack. Still not documented. 0.11 January 9, 2009 - check_prog with better support for Windows machines. 0.10 September 3, 2008 - Removed the tilde on my name, from Makefile.PL. Was generating some weird results on VMS and Solaris. 0.09 April 23, 2008 - Added 'check_headers?' methods to check for C heading files; - fixed the deletion of .c files created by failing tests; - Require perl 5.8.1 and ExtUtils::CBuilder 0.23 0.08 March 29, 2008 - require a 5.8 Perl 0.07 March 21, 2008 - re-factored some tests to make them Win-aware 0.06 March 19, 2008 - added -quiet option to ExtUtils::CBuilder for less noise when detecting things. 0.05 March 18, 2008 - added 'check_prog_yacc' method to check for a yacc implementation (see POD) 0.04 March 18, 2008 - adapt to new ExtUtils::CBuilder API 0.03 August 12, 2005 - Added 'check_file' and 'check_files' methods (kind of stupid methods) 0.02 February 14, 2005 - Moved from ExtUtils:: to Config:: Previous releases - Added 'check_prog' method to check for executable program - Added 'check_progs' method to check for a list of programs - Added 'check_prog_awk' method to check for an awk implementation - Added 'check_prog_egrep' method to check for an egrep implementation - first indexable version -- I need to use this module somewhere else; - using ExtUtils::CBuilder to compile test; - version correcting test for Mac OS-X (thanks, Michael Schwern); - using Config module to get CC value and EXE extension; - using ExtUtils::CBuilder (well take advantage of it later); Config-AutoConf-0.21/lib/000755 000765 000024 00000000000 12061106415 015204 5ustar00ambsstaff000000 000000 Config-AutoConf-0.21/Makefile.PL000644 000765 000024 00000001217 11715761374 016431 0ustar00ambsstaff000000 000000 use strict; use warnings; use ExtUtils::MakeMaker; use 5.008002; WriteMakefile( NAME => 'Config::AutoConf', AUTHOR => 'Alberto Simoes ', LICENSE => 'perl', VERSION_FROM => 'lib/Config/AutoConf.pm', ABSTRACT_FROM => 'lib/Config/AutoConf.pm', PL_FILES => {}, PREREQ_PM => { 'Capture::Tiny' => 0, 'ExtUtils::CBuilder' => 0.23, 'Test::More' => 0, }, dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz' }, clean => { FILES => 'Config-AutoConf-*' }, ); Config-AutoConf-0.21/MANIFEST000644 000765 000024 00000000412 12061106415 015564 0ustar00ambsstaff000000 000000 Changes MANIFEST META.yml # Will be created by "make dist" Makefile.PL README lib/Config/AutoConf.pm t/00.load.t t/pod-coverage.t t/pod.t t/01.checkprog.t t/02.compile.t t/03.link.t META.json Module JSON meta-data (added by MakeMaker) Config-AutoConf-0.21/META.json000644 000765 000024 00000001734 12061106415 016064 0ustar00ambsstaff000000 000000 { "abstract" : "A module to implement some of AutoConf macros in pure perl.", "author" : [ "Alberto Simoes " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120921", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Config-AutoConf", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Capture::Tiny" : "0", "ExtUtils::CBuilder" : "0.23", "Test::More" : "0" } } }, "release_status" : "stable", "version" : "0.21" } Config-AutoConf-0.21/META.yml000644 000765 000024 00000001070 12061106415 015705 0ustar00ambsstaff000000 000000 --- abstract: 'A module to implement some of AutoConf macros in pure perl.' author: - 'Alberto Simoes ' build_requires: ExtUtils::MakeMaker: 0 configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120921' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Config-AutoConf no_index: directory: - t - inc requires: Capture::Tiny: 0 ExtUtils::CBuilder: 0.23 Test::More: 0 version: 0.21 Config-AutoConf-0.21/README000644 000765 000024 00000001057 11204560317 015324 0ustar00ambsstaff000000 000000 Config::AutoConf =================== A module to implement some of AutoConf macros in pure perl. ABSTRACT With this module I pretend to simulate some of the tasks AutoConf macros do. To detect a command, to detect a library, etc. INSTALLATION To install this module, run the following commands: perl Makefile.PL make make test make install COPYRIGHT AND LICENSE Copyright 2004-2009 Alberto Simões, All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Config-AutoConf-0.21/t/000755 000765 000024 00000000000 12061106415 014701 5ustar00ambsstaff000000 000000 Config-AutoConf-0.21/t/00.load.t000644 000765 000024 00000000133 10730327566 016235 0ustar00ambsstaff000000 000000 # -*- cperl -*- use Test::More tests => 1; BEGIN { use_ok( 'Config::AutoConf' ); } Config-AutoConf-0.21/t/01.checkprog.t000644 000765 000024 00000001414 12056667252 017271 0ustar00ambsstaff000000 000000 # -*- cperl -*- use Test::More tests => 6; use Config; use Config::AutoConf; END { -e "config.log" and unlink "config.log"; } ok(Config::AutoConf->check_prog("perl")); ok(!Config::AutoConf->check_prog("hopingnobodyhasthiscommand")); like(Config::AutoConf->check_progs("___perl___", "__perl__", "_perl_", "perl"), qr/perl(.exe)?$/i); is(Config::AutoConf->check_progs("___perl___", "__perl__", "_perl_"), undef); SKIP: { my $awk; skip "Not sure about your awk", 1 if $^O =~ m!MSWin32! || !$Config{awk}; ok(($awk = Config::AutoConf->check_prog_awk)); diag("Found AWK as $awk"); }; SKIP: { my $grep; skip "Not sure about your grep", 1 if $^O =~ m!MSWin32! || !$Config{egrep}; ok(($grep = Config::AutoConf->check_prog_egrep)); diag("Found EGREP as $grep"); }; Config-AutoConf-0.21/t/02.compile.t000644 000765 000024 00000007155 11710613206 016747 0ustar00ambsstaff000000 000000 # -*- cperl -*- use Test::More tests => 24; use Config::AutoConf; END { -e "config.log" and unlink "config.log"; -e "config2.log" and unlink "config2.log"; -e "config.h" and unlink "config.h"; } diag("\n\nIgnore junk bellow.\n\n"); ## OK, we really hope people have sdtio.h around ok(Config::AutoConf->check_header("stdio.h")); ok(!Config::AutoConf->check_header("astupidheaderfile.h")); is(Config::AutoConf->check_headers("astupidheaderfile.h", "stdio.h"), "stdio.h"); # check several headers at once my $ac = Config::AutoConf->new( logfile => "config2.log" ); eval { $ac->check_default_headers(); }; ok( !$@, "check_default_headers" ) or diag( $@ ); ## we should find at least a stdio.h ... note( "Checking for cache value " . $ac->_cache_name( "stdio.h" ) ); ok( $ac->cache_val( $ac->_cache_name( "stdio.h" ) ), "found stdio.h" ); # some complex header tests for wide OS support eval { $ac->check_dirent_header(); }; ok( !$@, "check_dirent_header" ) or diag( $@ ); # check predeclared symbol # as we test a perl module, we expect perl.h available and suitable my $include_perl = "#include \n#include "; SKIP: { skip "Constants not defined on this Perl version", 2 if $] <= 5.01000; ok $ac->check_decl( "PERL_VERSION_STRING", undef, undef, $include_perl ), "PERL_VERSION_STRING declared"; ok $ac->check_decls( [qw(PERL_API_REVISION PERL_API_VERSION PERL_API_SUBVERSION)], undef, undef, $include_perl ), "PERL_API_* declared"; } ok $ac->check_decl( "perl_parse(PerlInterpreter *, XSINIT_t , int , char** , char** )", undef, undef, $include_perl ), "perl_parse() declared"; # check declared types ok $ac->check_type( "I32", undef, undef, $include_perl ), "I32 is valid type"; ok $ac->check_types( ["SV *", "AV *", "HV *" ], undef, undef, $include_perl ), "[SAH]V * are valid types" ; # check size of perl types my $typesize = $ac->check_sizeof_type( "I32", undef, undef, $include_perl ); ok $typesize, "I32 has size of " . ($typesize ? $typesize : "n/a") . " bytes"; ok $ac->check_sizeof_types( ["I32", "SV *", "AV", "HV *", "SV.sv_refcnt" ], undef, undef, $include_perl ), "Could determined sizes for I32, SV *, AV, HV *, SV.sv_refcnt" ; my $compute = $ac->compute_int( "-sizeof(I32)", undef, $include_perl ); ok $typesize + $compute == 0, "Compute (-sizeof(I32)"; # check perl data structure members ok $ac->check_member( "struct av.sv_any", undef, undef, $include_perl ), "have struct av.sv_any member"; ok $ac->check_members( ["struct hv.sv_any", "struct STRUCT_SV.sv_any"], undef, undef, $include_perl ), "have struct hv.sv_any and struct STRUCT_SV.sv_any members"; # check aligning ok $ac->check_alignof_type( "I32", undef, undef, $include_perl ), "Align of I32"; ok $ac->check_alignof_type( "SV.sv_refcnt", undef, undef, $include_perl ), "Align of SV.sv_refcnt"; ok $ac->check_alignof_types( ["I32", "U32", "AV", "HV *", "SV.sv_refcnt" ], undef, undef, $include_perl ), "Could determined sizes for I32, U32, AV, HV *, SV.sv_refcnt" ; Config::AutoConf->write_config_h(); ok( -f "config.h", "default config.h created" ); my $fsize; ok( $fsize = (stat("config.h"))[7], "config.h contains content" ); $ac->write_config_h(); ok( -f "config.h", "default config.h created" ); cmp_ok( (stat("config.h"))[7], ">", $fsize, "2nd config.h is bigger than first (more checks made)" ); my ($fh, $fbuf, $dbuf); open( $fh, "<", "config.h" ); { local $/; $fbuf = <$fh>; } close( $fh ); open( $fh, "+>", \$dbuf ); $ac->write_config_h( $fh ); close( $fh ); cmp_ok( $dbuf, "eq", $fbuf, "file and direct write computes equal" ); Config-AutoConf-0.21/t/03.link.t000644 000765 000024 00000001431 12060204644 016245 0ustar00ambsstaff000000 000000 # -*- cperl -*- use Test::More tests => 6; use Config::AutoConf; END { -e "config.log" and unlink "config.log"; } diag("\n\nIgnore junk bellow.\n\n"); my ($ac_1, $ac_2); ok( $ac_1 = Config::AutoConf->new(), "Instantiating Config::AutoConf for check_lib() tests" ); ok( $ac_2 = Config::AutoConf->new(), "Instantiating Config::AutoConf for search_libs() tests" ); TODO: { local $TODO = "It seems some Windows machine doesn't have -lm"; ## OK, we really hope people have -lm around ok($ac_1->check_lib("m", "atan"), "atan() in -lm"); ok(!$ac_1->check_lib("m", "foobar"), "foobar() not in -lm"); }; my $where_atan; ok( $where_atan = $ac_2->search_libs( "atan", [qw(m)] ), "searching lib for atan()" ); isnt( $where_atan, 0, "library for atan() found (or none required)" ); Config-AutoConf-0.21/t/pod-coverage.t000644 000765 000024 00000000375 11764463540 017464 0ustar00ambsstaff000000 000000 #!perl -T use Test::More; eval "use Test::Pod::Coverage 1.04"; plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@; plan skip_all => "Set AUTHOR_TESTS for author tests." unless $ENV{AUTHOR_TESTS}; all_pod_coverage_ok(); Config-AutoConf-0.21/t/pod.t000644 000765 000024 00000000335 11764463532 015670 0ustar00ambsstaff000000 000000 #!perl -T use Test::More; eval "use Test::Pod 1.14"; plan skip_all => "Test::Pod 1.14 required for testing POD" if $@; plan skip_all => "Set AUTHOR_TESTS for author tests." unless $ENV{AUTHOR_TESTS}; all_pod_files_ok(); Config-AutoConf-0.21/lib/Config/000755 000765 000024 00000000000 12061106415 016411 5ustar00ambsstaff000000 000000 Config-AutoConf-0.21/lib/Config/AutoConf.pm000644 000765 000024 00000150304 12056667412 020505 0ustar00ambsstaff000000 000000 package Config::AutoConf; use ExtUtils::CBuilder; use 5.008002; use Config; use Carp qw/croak/; use File::Temp qw/tempfile/; use File::Basename; use File::Spec; use Capture::Tiny qw/capture/; use Scalar::Util qw/looks_like_number/; # in core since 5.7.3 use base 'Exporter'; our @EXPORT = ('$LIBEXT', '$EXEEXT'); use warnings; use strict; # XXX detect HP-UX / HPPA our $LIBEXT = (defined $Config{dlext}) ? ("." . $Config{dlext}) : ($^O =~ /darwin/i) ? ".dylib" : ( ($^O =~ /mswin32/i) ? ".dll" : ".so" ); our $EXEEXT = ($^O =~ /mswin32/i) ? ".exe" : ""; =encoding UTF-8 =head1 NAME Config::AutoConf - A module to implement some of AutoConf macros in pure perl. =cut our $VERSION = '0.21'; =head1 ABSTRACT With this module I pretend to simulate some of the tasks AutoConf macros do. To detect a command, to detect a library, etc. =head1 SYNOPSIS use Config::AutoConf; Config::AutoConf->check_prog("agrep"); my $grep = Config::AutoConf->check_progs("agrep", "egrep", "grep"); Config::AutoConf->check_header("ncurses.h"); my $curses = Config::AutoConf->check_headers("ncurses.h","curses.h"); Config::AutoConf->check_prog_awk; Config::AutoConf->check_prog_egrep; Config::AutoConf->check_cc(); Config::AutoConf->check_lib("ncurses", "tgoto"); Config::AutoConf->check_file("/etc/passwd"); # -f && -r =head1 FUNCTIONS =cut my $glob_instance; =head2 new This function instantiates a new instance of Config::AutoConf, eg. to configure child components. =cut sub new { my $class = shift; ref $class and $class = ref $class; my %args = @_; my %instance = ( msg_prefix => 'configure: ', lang => "C", lang_stack => [], lang_supported => { "C" => "ExtUtils::CBuilder", }, cache => {}, defines => {}, extra_libs => [], extra_lib_dirs => [], extra_include_dirs => [], extra_preprocess_flags => [], extra_compile_flags => { "C" => [], }, extra_link_flags => [], logfile => "config.log", %args ); my $self = bless( \%instance, $class ); return $self; } =head2 check_file This function checks if a file exists in the system and is readable by the user. Returns a boolean. You can use '-f $file && -r $file' so you don't need to use a function call. =cut sub check_file { my $self = shift; my $file = shift; return (-f $file && -r $file); } =head2 check_files This function checks if a set of files exist in the system and are readable by the user. Returns a boolean. =cut sub check_files { my $self = shift; for (@_) { return 0 unless check_file($self, $_) } return 1; } =head2 check_prog This function checks for a program with the supplied name. In success returns the full path for the executable; =cut sub check_prog { my $self = shift; # sanitize ac_prog my $ac_prog = _sanitize(shift()); my $PATH = $ENV{PATH}; my $p; my $ext = ""; $ext = ".exe" if $^O =~ /mswin/i; for $p (split /$Config{path_sep}/,$PATH) { my $cmd = File::Spec->catfile($p,$ac_prog.$ext); return $cmd if -x $cmd; } return undef; } =head2 check_progs This function takes a list of program names. Returns the full path for the first found on the system. Returns undef if none was found. =cut sub check_progs { my $self = shift; my @progs = @_; for (@progs) { my $ans = check_prog($self, $_); return $ans if $ans; } return undef; } =head2 check_prog_yacc From the autoconf documentation, If `bison' is found, set [...] `bison -y'. Otherwise, if `byacc' is found, set [...] `byacc'. Otherwise set [...] `yacc'. Returns the full path, if found. =cut sub check_prog_yacc { my $self = shift; my $binary = check_progs(qw/$self bison byacc yacc/); $binary .= " -y" if ($binary =~ /bison$/); return $binary; } =head2 check_prog_awk From the autoconf documentation, Check for `gawk', `mawk', `nawk', and `awk', in that order, and set output [...] to the first one that is found. It tries `gawk' first because that is reported to be the best implementation. Note that it returns the full path, if found. =cut sub check_prog_awk { my $self = shift; return check_progs(qw/$self gawk mawk nawk awk/); } =head2 check_prog_egrep From the autoconf documentation, Check for `grep -E' and `egrep', in that order, and [...] output [...] the first one that is found. Note that it returns the full path, if found. =cut sub check_prog_egrep { my $self = shift; my $grep; if ($grep = check_prog($self,"grep")) { my $ans = `echo a | ($grep -E '(a|b)') 2>/dev/null`; return "$grep -E" if $ans eq "a\n"; } if ($grep = check_prog($self, "egrep")) { return $grep; } return undef; } =head2 check_cc This function checks if you have a running C compiler. =cut sub check_cc { ExtUtils::CBuilder->new(quiet => 1)->have_compiler; } =head2 msg_checking Prints "Checking @_ ..." =cut sub msg_checking { my $self = shift->_get_instance(); $self->{quiet} or print "Checking " . join(" ", @_) . "... "; $self->_add2log( "Checking " . join( " ", @_, "..." ) ); return; } =head2 msg_result Prints result \n =cut sub msg_result { my $self = shift->_get_instance(); $self->{quiet} or print join( " ", map { looks_like_number( $_ ) ? ( $_ == 0 ? "no" : ( $_ == 1 ? "yes" : $_ ) ) : $_ } @_ ), "\n"; return; } =head2 msg_notice Prints "configure: " @_ to stdout =cut sub msg_notice { my $self = shift->_get_instance(); $self->{quiet} or print $self->{msg_prefix} . join( " ", @_ ) . "\n"; return; } =head2 msg_warn Prints "configure: " @_ to stderr =cut sub msg_warn { my $self = shift->_get_instance(); $self->{quiet} or print STDERR $self->{msg_prefix} . join( " ", @_ ) . "\n"; return; } =head2 msg_error Prints "configure: " @_ to stderr and exits with exit code 0 (tells toolchain to stop here and report unsupported environment) =cut sub msg_error { my $self = shift->_get_instance(); $self->{quiet} or print STDERR $self->{msg_prefix} . join( " ", @_ ) . "\n"; exit(0); # #toolchain agreement: prevents configure stage to finish } =head2 msg_failure Prints "configure: " @_ to stderr and exits with exit code 0 (tells toolchain to stop here and report unsupported environment). Additional details are provides in config.log (probably more information in a later stage). =cut sub msg_failure { my $self = shift->_get_instance(); $self->{quiet} or print STDERR $self->{msg_prefix} . join( " ", @_ ) . "\n"; exit(0); # #toolchain agreement: prevents configure stage to finish } =head2 define_var( $name, $value [, $comment ] ) Defines a check variable for later use in further checks or code to compile. =cut sub define_var { my $self = shift->_get_instance(); my ($name, $value, $comment) = @_; defined( $name ) or croak( "Need a name to add a define" ); $self->{defines}->{$name} = [ $value, $comment ]; return; } =head2 write_config_h( [$target] ) Writes the defined constants into given target: Config::AutoConf->write_config_h( "config.h" ); =cut sub write_config_h { my $self = shift->_get_instance(); my $tgt; defined( $_[0] ) ? ( ref( $_[0] ) ? $tgt = $_[0] : open( $tgt, ">", $_[0] ) ) : open( $tgt, ">", "config.h" ); my $conf_h = <<'EOC'; /** * Generated from Config::AutoConf * * Do not edit this file, all modifications will be lost, * modify Makefile.PL or Build.PL instead. * * Inspired by GNU AutoConf. * * (c) 2011 Alberto Simoes & Jens Rehsack */ #ifndef __CONFIG_H__ EOC while( my ($defname, $defcnt) = each( %{ $self->{defines} } ) ) { if( $defcnt->[0] ) { defined $defcnt->[1] and $conf_h .= "/* " . $defcnt->[1] . " */\n"; $conf_h .= join( " ", "#define", $defname, $defcnt->[0] ) . "\n"; } else { defined $defcnt->[1] and $conf_h .= "/* " . $defcnt->[1] . " */\n"; $conf_h .= "/* " . join( " ", "#undef", $defname ) . " */\n\n"; } } $conf_h .= "#endif /* ?__CONFIG_H__ */\n"; print {$tgt} $conf_h; return; } =head2 push_lang(lang [, implementor ]) Puts the current used language on the stack and uses specified language for subsequent operations until ending pop_lang call. =cut sub push_lang { my $self = shift->_get_instance(); push @{$self->{lang_stack}}, [ $self->{lang} ]; return $self->_set_language( @_ ); } =head2 pop_lang([ lang ]) Pops the currently used language from the stack and restores previously used language. If I specified, it's asserted that the current used language equals to specified language (helps finding control flow bugs). =cut sub pop_lang { my $self = shift->_get_instance(); scalar( @{$self->{lang_stack}} ) > 0 or croak( "Language stack empty" ); defined( $_[0] ) and $self->{lang} ne $_[0] and croak( "pop_lang( $_[0] ) doesn't match language in use (" . $self->{lang} . ")" ); return $self->_set_language( @{ pop @{ $self->{lang} } } ); } =head2 lang_call( [prologue], function ) Builds program which simply calls given function. When given, prologue is prepended otherwise, the default includes are used. =cut sub lang_call { my $self = shift->_get_instance(); my ($prologue, $function) = @_; defined( $prologue ) or $prologue = $self->_default_includes(); $prologue .= <<"_ACEOF"; /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" { #endif char $function (); #ifdef __cplusplus } #endif _ACEOF my $body = "return $function ();"; $body = $self->_build_main( $body ); my $conftest = $self->_fill_defines(); $conftest .= "\n$prologue\n"; $conftest .= "\n$body\n"; return $conftest; } =head2 lang_build_program( prologue, body ) Builds program for current chosen language. If no prologue is given (I), the default headers are used. If body is missing, default body is used. Typical call of Config::AutoConf->lang_build_program( "const char hw[] = \"Hello, World\\n\";", "fputs (hw, stdout);" ) will create const char hw[] = "Hello, World\n"; /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif int main (int argc, char **argv) { (void)argc; (void)argv; fputs (hw, stdout);; return 0; } #ifdef __cplusplus } #endif =cut sub lang_build_program { my $self = shift->_get_instance(); my ($prologue, $body) = @_; defined( $prologue ) or $prologue = $self->_default_includes(); defined( $body ) or $body = ""; $body = $self->_build_main( $body ); my $conftest = $self->_fill_defines(); $conftest .= "\n$prologue\n"; $conftest .= "\n$body\n"; return $conftest; } =head2 lang_build_bool_test (prologue, test, [@decls]) Builds a static test which will fail to compile when test evaluates to false. If C<@decls> is given, it's prepended before the test code at the variable definition place. =cut sub lang_build_bool_test { my $self = shift->_get_instance(); my ($prologue, $test, @decls) = @_; defined( $test ) or $test = "1"; my $test_code = <lang_build_program( $prologue, $test_code ); } =head2 push_includes Adds given list of directories to preprocessor/compiler invocation. This is not proved to allow adding directories which might be created during the build. =cut sub push_includes { my $self = shift->_get_instance(); my @includes = @_; push( @{$self->{extra_include_dirs}}, @includes ); return; } =head2 push_preprocess_flags Adds given flags to the parameter list for preprocessor invocation. =cut sub push_preprocess_flags { my $self = shift->_get_instance(); my @cpp_flags = @_; push( @{$self->{extra_preprocess_flags}}, @cpp_flags ); return; } =head2 push_compiler_flags Adds given flags to the parameter list for compiler invocation. =cut sub push_compiler_flags { my $self = shift->_get_instance(); my @compiler_flags = @_; my $lang = $self->{lang}; if( scalar( @compiler_flags ) && ( ref($compiler_flags[-1]) eq "HASH" ) ) { my $lang_opt = pop( @compiler_flags ); defined( $lang_opt->{lang} ) or croak( "Missing lang attribute in language options" ); $lang = $lang_opt->{lang}; defined( $self->{lang_supported}->{$lang} ) or croak( "Unsupported language '$lang'" ); } push( @{$self->{extra_compile_flags}->{$lang}}, @compiler_flags ); return; } =head2 push_libraries Adds given list of libraries to the parameter list for linker invocation. =cut sub push_libraries { my $self = shift->_get_instance(); my @libs = @_; push( @{$self->{extra_libs}}, @libs ); return; } =head2 push_library_paths Adds given list of library paths to the parameter list for linker invocation. =cut sub push_library_paths { my $self = shift->_get_instance(); my @libdirs = @_; push( @{$self->{extra_lib_dirs}}, @libdirs ); return; } =head2 push_link_flags Adds given flags to the parameter list for linker invocation. =cut sub push_link_flags { my $self = shift->_get_instance(); my @link_flags = @_; push( @{$self->{extra_link_flags}}, @link_flags ); return; } =head2 compile_if_else( $src [, action-if-true [, action-if-false ] ] ) This function trys to compile specified code and runs action-if-true on success or action-if-false otherwise. Returns a boolean value containing check success state. =cut sub compile_if_else { my ($self, $src, $action_if_true, $action_if_false) = @_; ref $self or $self = $self->_get_instance(); my $builder = $self->_get_builder(); my ($fh, $filename) = tempfile( "testXXXXXX", SUFFIX => '.c'); print {$fh} $src; close $fh; my ($obj_file, $errbuf, $exception); (undef, $errbuf) = capture { eval { $obj_file = $builder->compile( source => $filename, include_dirs => $self->{extra_include_dirs}, extra_compiler_flags => $self->_get_extra_compiler_flags() ); }; $exception = $@; }; unlink $filename; unlink $obj_file if $obj_file; if ($exception || !$obj_file) { $self->_add2log( "compile stage failed" . ( $exception ? " - " . $exception : "" ) ); $errbuf and $self->_add2log( $errbuf ); $self->_add2log( "failing program is:\n" . $src ); defined( $action_if_false ) and "CODE" eq ref( $action_if_false ) and &{$action_if_false}(); return 0; } defined( $action_if_true ) and "CODE" eq ref( $action_if_true ) and &{$action_if_true}(); return 1; } =head2 link_if_else( $src [, action-if-true [, action-if-false ] ] ) This function trys to compile and link specified code and runs action-if-true on success or action-if-false otherwise. Returns a boolean value containing check success state. =cut sub link_if_else { my ($self, $src, $action_if_true, $action_if_false) = @_; ref $self or $self = $self->_get_instance(); my $builder = $self->_get_builder(); my ($fh, $filename) = tempfile( "testXXXXXX", SUFFIX => '.c'); print {$fh} $src; close $fh; my ($obj_file, $errbuf, $exception); (undef, $errbuf) = capture { eval { $obj_file = $builder->compile( source => $filename, include_dirs => $self->{extra_include_dirs}, extra_compiler_flags => $self->_get_extra_compiler_flags() ); }; $exception = $@; }; if ($exception || !$obj_file) { $self->_add2log( "compile stage failed" . ( $exception ? " - " . $exception : "" ) ); $errbuf and $self->_add2log( $errbuf ); $self->_add2log( "failing program is:\n" . $src ); unlink $filename; unlink $obj_file if $obj_file; defined( $action_if_false ) and "CODE" eq ref( $action_if_false ) and &{$action_if_false}(); return 0; } my $exe_file; (undef, $errbuf) = capture { eval { $exe_file = $builder->link_executable( objects => $obj_file, extra_linker_flags => $self->_get_extra_linker_flags() ); }; $exception = $@; }; unlink $filename; unlink $obj_file if $obj_file; unlink $exe_file if $exe_file; if ($exception || !$exe_file) { $self->_add2log( "link stage failed" . ( $exception ? " - " . $exception : "" ) ); $errbuf and $self->_add2log( $errbuf ); $self->_add2log( "failing program is:\n" . $src ); defined( $action_if_false ) and "CODE" eq ref( $action_if_false ) and &{$action_if_false}(); return 0; } defined( $action_if_true ) and "CODE" eq ref( $action_if_true ) and &{$action_if_true}(); return 1; } =head2 check_cached( cache-var, message, sub-to-check ) This function checks whether a specified cache variable is set or not, and if not it's going to set it using specified sub-to-check. =cut sub check_cached { my ($self, $cache_name, $message, $check_sub) = @_; ref $self or $self = $self->_get_instance(); $self->msg_checking( $message ); if( defined($self->{cache}->{$cache_name}) ) { $self->msg_result( "(cached)", $self->{cache}->{$cache_name} ); } else { $self->{cache}->{$cache_name} = &{$check_sub}(); $self->msg_result( $self->{cache}->{$cache_name} ); } return $self->{cache}->{$cache_name}; } =head2 cache_val This functions returns the value of a previously check_cached call. =cut sub cache_val { my $self = shift->_get_instance(); my $cache_name = shift; defined $self->{cache}->{$cache_name} or return; return $self->{cache}->{$cache_name}; } =head2 check_decl( symbol, [action-if-found], [action-if-not-found], [prologue = default includes] ) If symbol (a function, variable or constant) is not declared in includes and a declaration is needed, run the code ref given in I, otherwise I. includes is a series of include directives, defaulting to I, which are used prior to the declaration under test. This method actually tests whether symbol is defined as a macro or can be used as an r-value, not whether it is really declared, because it is much safer to avoid introducing extra declarations when they are not needed. In order to facilitate use of C++ and overloaded function declarations, it is possible to specify function argument types in parentheses for types which can be zero-initialized: Config::AutoConf->check_decl("basename(char *)") This method caches its result in the Cset langE>_symbol variable. =cut sub check_decl { my ($self, $symbol, $action_if_found, $action_if_not_found, $prologue) = @_; $self = $self->_get_instance(); defined( $symbol ) or return; # XXX prefer croak ref( $symbol ) eq "" or return; ( my $sym_plain = $symbol ) =~ s/ *\(.*//; my $sym_call = $symbol; $sym_call =~ s/\(/((/; $sym_call =~ s/\)/) 0)/; $sym_call =~ s/,/) 0, (/g; my $cache_name = $self->_cache_name( "decl", $self->{lang}, $symbol ); my $check_sub = sub { my $body = <lang_build_program( $prologue, $body ); my $have_decl = $self->compile_if_else( $conftest ); if( $have_decl ) { if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } } return $have_decl; }; return $self->check_cached( $cache_name, "whether $symbol is declared", $check_sub ); } =head2 check_decls( symbols, [action-if-found], [action-if-not-found], [prologue = default includes] ) For each of the symbols (with optional function argument types for C++ overloads), run L. If I is given, it is additional code to execute when one of the symbol declarations is needed, otherwise I is executed. Contrary to GNU autoconf, this method does not declare HAVE_DECL_symbol macros for the resulting C, because it differs as C between compiling languages. =cut sub check_decls { my ($self, $symbols, $action_if_found, $action_if_not_found, $prologue) = @_; $self = $self->_get_instance(); my $have_syms = 1; foreach my $symbol (@$symbols) { $have_syms &= $self->check_decl( $symbol, undef, undef, $prologue ); } if( $have_syms ) { if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } } return $have_syms; } sub _have_type_define_name { my $type = $_[0]; my $have_name = "HAVE_" . uc($type); $have_name =~ tr/*/P/; $have_name =~ tr/_A-Za-z0-9/_/c; return $have_name; } =head2 check_type (type, [action-if-found], [action-if-not-found], [prologue = default includes]) Check whether type is defined. It may be a compiler builtin type or defined by the includes. I should be a series of include directives, defaulting to I, which are used prior to the type under test. In C, type must be a type-name, so that the expression C is valid (but C is not) If I type is defined, preprocessor macro HAVE_I (in all capitals, with "*" replaced by "P" and spaces and dots replaced by underscores) is defined. This method caches its result in the Ctype variable. =cut sub check_type { my ($self, $type, $action_if_found, $action_if_not_found, $prologue) = @_; $self = $self->_get_instance(); defined( $type ) or return; # XXX prefer croak ref( $type ) eq "" or return; my $cache_name = $self->_cache_type_name( "type", $type ); my $check_sub = sub { my $body = <lang_build_program( $prologue, $body ); my $have_type = $self->compile_if_else( $conftest ); $self->define_var( _have_type_define_name( $type ), $have_type ? $have_type : undef, "defined when $type is available" ); if( $have_type ) { if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } } return $have_type; }; return $self->check_cached( $cache_name, "for $type", $check_sub ); } =head2 check_types (types, [action-if-found], [action-if-not-found], [prologue = default includes]) For each type L is called to check for type. If I is given, it is additionally executed when all of the types are found. If I is given, it is executed when one of the types is not found. =cut sub check_types { my ($self, $types, $action_if_found, $action_if_not_found, $prologue) = @_; $self = $self->_get_instance(); my $have_types = 1; foreach my $type (@$types) { $have_types &= $self->check_type( $type, undef, undef, $prologue ); } if( $have_types ) { if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } } return $have_types; } sub _compute_int_compile { my ($self, $expr, $prologue, @decls) = @_; $self = $self->_get_instance(); my( $body, $conftest, $compile_result ); my ($low, $mid, $high) = (0, 0, 0); if( $self->compile_if_else( $self->lang_build_bool_test( $prologue, "((long int)($expr)) >= 0", @decls ) ) ) { $low = $mid = 0; while( 1 ) { if( $self->compile_if_else( $self->lang_build_bool_test( $prologue, "((long int)($expr)) <= $mid", @decls ) ) ) { $high = $mid; last; } $low = $mid + 1; # avoid overflow if( $low <= $mid ) { $low = 0; last; } $mid = $low * 2; } } elsif( $self->compile_if_else( $self->lang_build_bool_test( $prologue, "((long int)($expr)) < 0", @decls ) ) ) { $high = $mid = -1; while( 1 ) { if( $self->compile_if_else( $self->lang_build_bool_test( $prologue, "((long int)($expr)) >= $mid", @decls ) ) ) { $low = $mid; last; } $high = $mid - 1; # avoid overflow if( $mid < $high ) { $high = 0; last; } $mid = $high * 2; } } # perform binary search between $low and $high while( $low <= $high ) { $mid = int( ( $high - $low ) / 2 + $low ); if( $self->compile_if_else( $self->lang_build_bool_test( $prologue, "((long int)($expr)) < $mid", @decls ) ) ) { $high = $mid - 1; } elsif( $self->compile_if_else( $self->lang_build_bool_test( $prologue, "((long int)($expr)) > $mid", @decls ) ) ) { $low = $mid + 1; } else { return $mid; } } return; } =head2 compute_int (expression, [action-if-fails], [prologue = default includes], [@decls]) Returns the value of the integer I. The value should fit in an initializer in a C variable of type signed long. It should be possible to evaluate the expression at compile-time. If no includes are specified, the default includes are used. Execute I if the value cannot be determined correctly. =cut sub compute_int { my ($self, $expr, $action_if_fails, $prologue, @decls) = @_; $self = $self->_get_instance(); my $cache_name = $self->_cache_type_name( "compute_int", $self->{lang}, $expr ); my $check_sub = sub { my $val = $self->_compute_int_compile( $expr, $prologue, @decls); unless( defined( $val ) ) { if( defined( $action_if_fails ) and "CODE" eq ref( $action_if_fails ) ) { &{$action_if_fails}(); } } return $val; }; return $self->check_cached( $cache_name, "for compute result of ($expr)", $check_sub ); } sub _sizeof_type_define_name { my $type = $_[0]; my $have_name = "SIZEOF_" . uc($type); $have_name =~ tr/*/P/; $have_name =~ tr/_A-Za-z0-9/_/c; return $have_name; } =head2 check_sizeof_type (type, [action-if-found], [action-if-not-found], [prologue = default includes]) Checks for the size of the specified type by compiling. If no size can determined, I is invoked when given. Otherwise I is invoked and C is defined using the determined size. In opposition to GNU AutoConf, this method can determine size of structure members, eg. $ac->check_sizeof_type( "SV.sv_refcnt", undef, undef, $include_perl ); # or $ac->check_sizeof_type( "struct utmpx.ut_id", undef, undef, "#include " ); This method caches its result in the Cset langE>_type variable. =cut sub check_sizeof_type { my ($self, $type, $action_if_found, $action_if_not_found, $prologue) = @_; $self = $self->_get_instance(); defined( $type ) or return; # XXX prefer croak ref( $type ) eq "" or return; my $cache_name = $self->_cache_type_name( "sizeof", $self->{lang}, $type ); my $check_sub = sub { my @decls; if( $type =~ m/^([^.]+)\.([^.]+)$/ ) { my $struct = $1; $type = "_ac_test_aggr.$2"; my $decl = "static $struct _ac_test_aggr;"; push( @decls, $decl ); } my $typesize = $self->_compute_int_compile( "sizeof($type)", $prologue, @decls ); $self->define_var( _sizeof_type_define_name( $type ), $typesize ? $typesize : undef, "defined when sizeof($type) is available" ); if( $typesize ) { if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } } return $typesize; }; return $self->check_cached( $cache_name, "for size of $type", $check_sub ); } =head2 check_sizeof_types (type, [action-if-found], [action-if-not-found], [prologue = default includes]) For each type L is called to check for size of type. If I is given, it is additionally executed when all of the sizes of the types could determined. If I is given, it is executed when one size of the types could not determined. =cut sub check_sizeof_types { my ($self, $types, $action_if_found, $action_if_not_found, $prologue) = @_; $self = $self->_get_instance(); my $have_sizes = 1; foreach my $type (@$types) { $have_sizes &= ! ! ($self->check_sizeof_type ( $type, undef, undef, $prologue )); } if( $have_sizes ) { if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } } return $have_sizes; } sub _alignof_type_define_name { my $type = $_[0]; my $have_name = "ALIGNOF_" . uc($type); $have_name =~ tr/*/P/; $have_name =~ tr/_A-Za-z0-9/_/c; return $have_name; } =head2 check_alignof_type (type, [action-if-found], [action-if-not-found], [prologue = default includes]) Define ALIGNOF_type to be the alignment in bytes of type. I must be valid as a structure member declaration or I must be a structure member itself. This method caches its result in the Cset langE>_type variable, with I<*> mapped to C

and other characters not suitable for a variable name mapped to underscores. =cut sub check_alignof_type { my ($self, $type, $action_if_found, $action_if_not_found, $prologue) = @_; $self = $self->_get_instance(); defined( $type ) or return; # XXX prefer croak ref( $type ) eq "" or return; my $cache_name = $self->_cache_type_name( "alignof", $self->{lang}, $type ); my $check_sub = sub { my @decls = ( "#ifndef offsetof", "# ifdef __ICC", "# define offsetof(type,memb) ((size_t)(((char *)(&((type*)0)->memb)) - ((char *)0)))", "# else", "# define offsetof(type,memb) ((size_t)&((type*)0)->memb)", "# endif", "#endif" ); my ($struct, $memb); if( $type =~ m/^([^.]+)\.([^.]+)$/ ) { $struct = $1; $memb = $2; } else { push( @decls, "typedef struct { char x; $type y; } ac__type_alignof_;" ); $struct = "ac__type_alignof_"; $memb = "y"; } my $typealign = $self->_compute_int_compile( "offsetof($struct, $memb)", $prologue, @decls ); $self->define_var( _alignof_type_define_name( $type ), $typealign ? $typealign : undef, "defined when alignof($type) is available" ); if( $typealign ) { if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } } return $typealign; }; return $self->check_cached( $cache_name, "for align of $type", $check_sub ); } =head2 check_alignof_types (type, [action-if-found], [action-if-not-found], [prologue = default includes]) For each type L is called to check for align of type. If I is given, it is additionally executed when all of the aligns of the types could determined. If I is given, it is executed when one align of the types could not determined. =cut sub check_alignof_types { my ($self, $types, $action_if_found, $action_if_not_found, $prologue) = @_; $self = $self->_get_instance(); my $have_aligns = 1; foreach my $type (@$types) { $have_aligns &= ! ! ($self->check_alignof_type ( $type, undef, undef, $prologue )); } if( $have_aligns ) { if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } } return $have_aligns; } sub _have_member_define_name { my $member = $_[0]; my $have_name = "HAVE_" . uc($member); $have_name =~ tr/_A-Za-z0-9/_/c; return $have_name; } =head2 check_member (member, [action-if-found], [action-if-not-found], [prologue = default includes]) Check whether I is in form of I.I and I is a member of the I aggregate. I should be a series of include directives, defaulting to I, which are used prior to the aggregate under test. Config::AutoConf->check_member( "struct STRUCT_SV.sv_refcnt", undef, sub { Config::AutoConf->msg_failure( "sv_refcnt member required for struct STRUCT_SV" ); } "#include \n#include " ); If I aggregate has I member, preprocessor macro HAVE_I_I (in all capitals, with spaces and dots replaced by underscores) is defined. This macro caches its result in the Caggr_member variable. =cut sub check_member { my ($self, $member, $action_if_found, $action_if_not_found, $prologue) = @_; $self = $self->_get_instance(); defined( $member ) or return; # XXX prefer croak ref( $member ) eq "" or return; $member =~ m/^([^.]+)\.([^.]+)$/ or return; my $type = $1; $member = $2; my $cache_name = $self->_cache_type_name( "member", $type ); my $check_sub = sub { my $body = <lang_build_program( $prologue, $body ); my $have_member = $self->compile_if_else( $conftest ); $self->define_var( _have_member_define_name( $member ), $have_member ? $have_member : undef, "defined when $member is available" ); if( $have_member ) { if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } } return $have_member; }; return $self->check_cached( $cache_name, "for $type.$member", $check_sub ); } =head2 check_members (members, [action-if-found], [action-if-not-found], [prologue = default includes]) For each member L is called to check for member of aggregate. If I is given, it is additionally executed when all of the aggregate members are found. If I is given, it is executed when one of the aggregate members is not found. =cut sub check_members { my ($self, $members, $action_if_found, $action_if_not_found, $prologue) = @_; $self = $self->_get_instance(); my $have_members = 1; foreach my $member (@$members) { $have_members &= $self->check_member( $member, undef, undef, $prologue ); } if( $have_members ) { if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } } return $have_members; } =head2 check_headers This function uses check_header to check if a set of include files exist in the system and can be included and compiled by the available compiler. Returns the name of the first header file found. =cut sub check_headers { my $self = shift; for (@_) { return $_ if check_header($self, $_) } return undef; } sub _have_header_define_name { my $header = $_[0]; my $have_name = "HAVE_" . uc($header); $have_name =~ tr/_A-Za-z0-9/_/c; return $have_name; } sub _check_header { my ($self, $header, $prologue, $body) = @_; $prologue .= <<"_ACEOF"; #include <$header> _ACEOF my $conftest = $self->lang_build_program( $prologue, $body ); my $have_header = $self->compile_if_else( $conftest ); return $have_header; } =head2 check_header This function is used to check if a specific header file is present in the system: if we detect it and if we can compile anything with that header included. Note that normally you want to check for a header first, and then check for the corresponding library (not all at once). The standard usage for this module is: Config::AutoConf->check_header("ncurses.h"); This function will return a true value (1) on success, and a false value if the header is not present or not available for common usage. =cut sub check_header { my $self = shift; my $header = shift; my $pre_inc = shift; return 0 unless $header; my $prologue = ""; defined $pre_inc and $prologue .= "$pre_inc\n"; my $cache_name = $self->_cache_name( $header ); my $check_sub = sub { my $have_header = $self->_check_header( $header, $prologue, "" ); $self->define_var( _have_header_define_name( $header ), $have_header ? $have_header : undef, "defined when $header is available" ); return $have_header; }; return $self->check_cached( $cache_name, "for $header", $check_sub ); } =head2 check_all_headers This function checks each given header for usability. =cut sub check_all_headers { my $self = shift->_get_instance(); @_ or return; my $rc = 1; foreach my $header (@_) { $rc &= $self->check_header( $header ); } return $rc; } =head2 check_stdc_headers Checks for standard C89 headers, namely stdlib.h, stdarg.h, string.h and float.h. If those are found, additional all remaining C89 headers are checked: assert.h, ctype.h, errno.h, limits.h, locale.h, math.h, setjmp.h, signal.h, stddef.h, stdio.h and time.h. Returns a false value if it fails. =cut sub check_stdc_headers { my $self = shift->_get_instance(); my $rc = 0; if( $rc = $self->check_all_headers( qw(stdlib.h stdarg.h string.h float.h) ) ) { $rc &= $self->check_all_headers( qw/assert.h ctype.h errno.h limits.h/ ); $rc &= $self->check_all_headers( qw/locale.h math.h setjmp.h signal.h/ ); $rc &= $self->check_all_headers( qw/stddef.h stdio.h time.h/ ); } if( $rc ) { $self->define_var( "STDC_HEADERS", 1, "Define to 1 if you have the ANSI C header files." ); } return $rc; } =head2 check_default_headers This function checks for some default headers, the std c89 haeders and sys/types.h, sys/stat.h, memory.h, strings.h, inttypes.h, stdint.h and unistd.h =cut sub check_default_headers { my $self = shift->_get_instance(); my $rc = $self->check_stdc_headers() and $self->check_all_headers( qw(sys/types.h sys/stat.h memory.h strings.h inttypes.h stdint.h unistd.h) ); return $rc; } =head2 check_dirent_header Check for the following header files. For the first one that is found and defines 'DIR', define the listed C preprocessor macro: dirent.h HAVE_DIRENT_H sys/ndir.h HAVE_SYS_NDIR_H sys/dir.h HAVE_SYS_DIR_H ndir.h HAVE_NDIR_H The directory-library declarations in your source code should look something like the following: #include #ifdef HAVE_DIRENT_H # include # define NAMLEN(dirent) strlen ((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) ((dirent)->d_namlen) # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif #endif Using the above declarations, the program would declare variables to be of type C, not C, and would access the length of a directory entry name by passing a pointer to a C to the C macro. This macro might be obsolescent, as all current systems with directory libraries have C<dirent.hE>>. Programs supporting only newer OS might not need touse this macro. =cut sub check_dirent_header { my $self = shift->_get_instance(); my $cache_name = $self->_cache_name( "header_dirent" ); my $check_sub = sub { my $have_dirent; foreach my $header (qw(dirent.h sys/ndir.h sys/dir.h ndir.h)) { $have_dirent = $self->_check_header( $header, "#include \n", "if ((DIR *) 0) { return 0; }" ); $self->define_var( _have_header_define_name( $header ), $have_dirent ? $have_dirent : undef, "defined when $header is available" ); $have_dirent and $have_dirent = $header and last; } return $have_dirent; }; return $self->check_cached( $cache_name, "for header defining DIR *", $check_sub ); } sub _have_lib_define_name { my $lib = $_[0]; my $have_name = "HAVE_LIB" . uc($lib); $have_name =~ tr/_A-Za-z0-9/_/c; return $have_name; } =head2 check_lm( [ action-if-found ], [ action-if-not-found ] ) This method is used to check if some common C functions are available, and if C<-lm> is needed. Returns the empty string if no library is needed, or the "-lm" string if libm is needed. Actions are only called at the end of the list of tests. If one fails, I is run. Otherwise, I is run. =cut sub check_lm { my ($self, $aif, $ainf) = @_; ref($self) or $self = $self->_get_instance(); my $fail = 0; my $required = ""; for my $func (qw(log2 pow log10 log exp sqrt)) { my $ans = $self->search_libs( $func, ['m'] ); $ans or $fail = 1; ($ans ne "none required") and $required = $ans; } if ($fail) { $ainf && $ainf->() } else { $aif && $aif->() } return $required; } =head2 check_lib( lib, func, [ action-if-found ], [ action-if-not-found ], [ @other-libs ] ) This function is used to check if a specific library includes some function. Call it with the library name (without the lib portion), and the name of the function you want to test: Config::AutoConf->check_lib("z", "gzopen"); It returns 1 if the function exist, 0 otherwise. I and I can be CODE references whereby the default action in case of function found is to define the HAVE_LIBlibrary (all in capitals) preprocessor macro with 1 and add $lib to the list of libraries to link. If linking with library results in unresolved symbols that would be resolved by linking with additional libraries, give those libraries as the I argument: e.g., C<[qw(Xt X11)]>. Otherwise, this routine may fail to detect that library is present, because linking the test program can fail with unresolved symbols. The other-libraries argument should be limited to cases where it is desirable to test for one library in the presence of another that is not already in LIBS. It's recommended to use L instead of check_lib these days. =cut sub check_lib { my ( $self, $lib, $func, $action_if_found, $action_if_not_found, @other_libs ) = @_; ref($self) or $self = $self->_get_instance(); return 0 unless $lib; return 0 unless $func; scalar( @other_libs ) == 1 and ref( $other_libs[0] ) eq "ARRAY" and @other_libs = @{ $other_libs[0] }; my $cache_name = $self->_cache_name( "lib", $lib, $func ); my $check_sub = sub { my $conftest = $self->lang_call( "", $func ); my @save_libs = @{$self->{extra_libs}}; push( @{$self->{extra_libs}}, $lib, @other_libs ); my $have_lib = $self->link_if_else( $conftest ); $self->{extra_libs} = [ @save_libs ]; if( $have_lib ) { if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } else { $self->define_var( _have_lib_define_name( $lib ), $have_lib, "defined when library $lib is available" ); push( @{$self->{extra_libs}}, $lib ); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } else { $self->define_var( _have_lib_define_name( $lib ), undef, "defined when library $lib is available" ); } } return $have_lib; }; return $self->check_cached( $cache_name, "for $func in -l$lib", $check_sub ); } =head2 search_libs( function, search-libs, [action-if-found], [action-if-not-found], [other-libs] ) Search for a library defining function if it's not already available. This equates to calling Config::AutoConf->link_if_else( Config::AutoConf->lang_call( "", "$function" ) ); first with no libraries, then for each library listed in search-libs. I must be specified as an array reference to avoid confusion in argument order. Prepend -llibrary to LIBS for the first library found to contain function, and run I. If the function is not found, run I. If linking with library results in unresolved symbols that would be resolved by linking with additional libraries, give those libraries as the I argument: e.g., C<[qw(Xt X11)]>. Otherwise, this method fails to detect that function is present, because linking the test program always fails with unresolved symbols. The result of this test is cached in the ac_cv_search_function variable as "none required" if function is already available, as C<0> if no library containing function was found, otherwise as the -llibrary option that needs to be prepended to LIBS. =cut sub search_libs { my ( $self, $func, $libs, $action_if_found, $action_if_not_found, @other_libs ) = @_; ref($self) or $self = $self->_get_instance(); ( defined( $libs ) and "ARRAY" eq ref( $libs ) and scalar( @{$libs} ) > 0 ) or return 0; # XXX would prefer croak return 0 unless $func; scalar( @other_libs ) == 1 and ref( $other_libs[0] ) eq "ARRAY" and @other_libs = @{ $other_libs[0] }; my $cache_name = $self->_cache_name( "search", $func ); my $check_sub = sub { my $conftest = $self->lang_call( "", $func ); my @save_libs = @{$self->{extra_libs}}; my $have_lib = 0; foreach my $libstest ( undef, @$libs ) { # XXX would local work on array refs? can we omit @save_libs? $self->{extra_libs} = [ @save_libs ]; defined( $libstest ) and unshift( @{$self->{extra_libs}}, $libstest, @other_libs ); $self->link_if_else( $conftest ) and ( $have_lib = defined( $libstest ) ? $libstest : "none required" ) and last; } $self->{extra_libs} = [ @save_libs ]; if( $have_lib ) { $have_lib eq "none required" or unshift( @{$self->{extra_libs}}, $have_lib ); if( defined( $action_if_found ) and "CODE" eq ref( $action_if_found ) ) { &{$action_if_found}(); } } else { if( defined( $action_if_not_found ) and "CODE" eq ref( $action_if_not_found ) ) { &{$action_if_not_found}(); } } return $have_lib; }; return $self->check_cached( $cache_name, "for library containing $func", $check_sub ); } # # # Auxiliary funcs # sub _sanitize { # This is hard coded, and maybe a little stupid... my $x = shift; $x =~ s/ //g; $x =~ s/\///g; $x =~ s/\\//g; return $x; } sub _get_instance { my $class = shift; ref $class and return $class; defined( $glob_instance ) and ref( $glob_instance ) and return $glob_instance; $glob_instance = $class->new(); return $glob_instance; } sub _get_builder { my $self = $_[0]->_get_instance(); defined( $self->{lang_supported}->{ $self->{lang} } ) or croak( "Unsupported compile language \"" . $self->{lang} . "\"" ); my $builder = $self->{lang_supported}->{ $self->{lang} }->new( quiet => 1 ); ## XXX - Temporarily. Will try to send upstream if ($self->{lang} eq "C") { $builder->{config}{ccflags} =~ s/-arch \S+//g; $builder->{config}{lddlflags} =~ s/-arch \S+//g; $builder->{config}{ldflags} =~ s/-arch \S+//g; } return $builder; } sub _set_language { my $self = shift->_get_instance(); my ($lang, $impl) = @_; defined( $lang ) or croak( "Missing language" ); defined( $impl ) and defined( $self->{lang_supported}->{$lang} ) and $impl ne $self->{lang_supported}->{$lang} and croak( "Language implementor ($impl) doesn't match exisiting one (" . $self->{lang_supported}->{$lang} . ")" ); defined( $impl ) and !defined( $self->{lang_supported}->{$lang} ) and $self->{lang_supported}->{$lang} = $impl; defined( $self->{lang_supported}->{$lang} ) or croak( "Unsupported language \"$lang\"" ); defined( $self->{extra_compile_flags}->{$lang} ) or $self->{extra_compile_flags}->{$lang} = []; $self->{lang} = $lang; return; } sub _fill_defines { my ($self, $src, $action_if_true, $action_if_false) = @_; ref $self or $self = $self->_get_instance(); my $conftest = ""; while( my ($defname, $defcnt) = each( %{ $self->{defines} } ) ) { $defcnt->[0] or next; defined $defcnt->[1] and $conftest .= "/* " . $defcnt->[1] . " */\n"; $conftest .= join( " ", "#define", $defname, $defcnt->[0] ) . "\n"; } $conftest .= "/* end of conftest.h */\n"; return $conftest; } # # default includes taken from autoconf/headers.m4 # =head2 _default_includes returns a string containing default includes for program prologue taken from autoconf/headers.m4: #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif =cut sub _default_includes { my $conftest .= <<"_ACEOF"; #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif _ACEOF return $conftest; } sub _default_main { return $_[0]->_build_main(""); } sub _build_main { my $self = shift->_get_instance(); my $body = shift || ""; my $conftest .= <<"_ACEOF"; int main () { $body; return 0; } _ACEOF return $conftest; } sub _cache_prefix { return "ac"; } sub _cache_name { my ($self, @names) = @_; my $cache_name = join( "_", $self->_cache_prefix(), "cv", @names ); $cache_name =~ tr/_A-Za-z0-9/_/c; if( $cache_name eq "ac_cv_0_0" ) { Test::More::diag( "break here" ); } return $cache_name; } sub _get_log_fh { my $self = $_[0]->_get_instance(); unless( defined( $self->{logfh} ) ) { open( $self->{logfh}, ">", $self->{logfile} ) or croak "Could not open file $self->{logfile}: $!"; } return $self->{logfh}; } sub _add2log { my ($self, @logentries) = @_; ref($self) or $self = $self->_get_instance(); $self->_get_log_fh(); foreach my $logentry (@logentries) { print {$self->{logfh}} "$logentry\n"; } return; } sub _cache_type_name { my ($self, @names) = @_; return $self->_cache_name( map { $_ =~ tr/*/p/; $_ } @names ); } sub _get_extra_compiler_flags { my $self = shift->_get_instance(); my @ppflags = @{$self->{extra_preprocess_flags}}; my @cflags = @{$self->{extra_compile_flags}->{ $self->{lang} }}; return join( " ", @ppflags, @cflags ); } sub _get_extra_linker_flags { my $self = shift->_get_instance(); my @libs = @{$self->{extra_libs}}; my @ldflags = @{$self->{extra_link_flags}}; return join( " ", @ldflags, map { "-l$_" } @libs ); } =head1 AUTHOR Alberto SimƵes, C<< >> Jens Rehsack, C<< >> =head1 NEXT STEPS Although a lot of work needs to be done, this is the next steps I intent to take. - detect flex/lex - detect yacc/bison/byacc - detect ranlib (not sure about its importance) These are the ones I think not too much important, and will be addressed later, or by request. - detect an 'install' command - detect a 'ln -s' command -- there should be a module doing this kind of task. =head1 BUGS A lot. Portability is a pain. B<>. Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 ACKNOWLEDGEMENTS Michael Schwern for kind MacOS X help. Ken Williams for ExtUtils::CBuilder =head1 COPYRIGHT & LICENSE Copyright 2004-2011 by the Authors This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO ExtUtils::CBuilder(3) =cut 1; # End of Config::AutoConf