diff --git a/ARTISTIC-1.0 b/ARTISTIC-1.0 new file mode 100644 index 0000000..2cfaacf --- /dev/null +++ b/ARTISTIC-1.0 @@ -0,0 +1,130 @@ + + + The "Artistic License" + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder as specified below. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) give non-standard executables non-standard names, and clearly + document the differences in manual pages (or equivalent), together + with instructions on where to get the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this +Package. You may not charge a fee for this Package itself. However, +you may distribute this Package in aggregate with other (possibly +commercial) programs as part of a larger (possibly commercial) software +distribution provided that you do not advertise this Package as a +product of your own. You may embed this Package's interpreter within +an executable of yours (by linking); this shall be construed as a mere +form of aggregation, provided that the complete Standard Version of the +interpreter is so embedded. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whoever generated +them, and may be sold commercially, and may be aggregated with this +Package. If such scripts or library files are aggregated with this +Package via the so-called "undump" or "unexec" methods of producing a +binary executable image, then distribution of such an image shall +neither be construed as a distribution of this Package nor shall it +fall under the restrictions of Paragraphs 3 and 4, provided that you do +not represent such an executable image as a Standard Version of this +Package. + +7. C subroutines (or comparably compiled subroutines in other +languages) supplied by you and linked into this Package in order to +emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. Aggregation of this Package with a commercial distribution is always +permitted provided that the use of this Package is embedded; that is, +when no overt attempt is made to make this Package's interfaces visible +to the end user of the commercial distribution. Such use shall not be +construed as a distribution of this Package. + +9. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End + diff --git a/Changes b/Changes new file mode 100644 index 0000000..3d5aaf5 --- /dev/null +++ b/Changes @@ -0,0 +1,240 @@ +Revision history for Config-AutoConf + +0.315 2017-08-02 + - add check_builtin + - perltidy code and add perltidy test (taken from MooX::Options) + - ensure for many check_* methods that externally controlled + ac_av_* environment variables are correctly passed into config.h + - fix check_dirent_header to cache proving header and proving + availability of 'DIR *' in such a header separately + +0.314 2017-03-30 + - _get_extra_linker_flags: add library dirs + +0.313 2016-04-11 + - release 0.312_001 without further changes + +0.312_001 2016-04-07 + - fix "check_member" test (RT#113271) + - update Copyright notice + - add license files + - improve compile_if_else/link_if_else by proving whether object + or binary file (compile result) exists + - fix some typos and other POD quirks + - Update README.md from updated POD + +0.311 2015-03-17 + - fix check_member(s) - patch by jddurand + +0.310 2015-02-20 + - Fix some typographical errors (by Peter Pentchev ) + - bump copyright timestamps + - add ribasushi to acknowledgements + - improve/correct meta information + - improve bundled POD + +0.309 2014-12-31 + - Remove the -arch removal for Mac OS X. + +0.308 2014-12-26 + - deal with "no C compiler available" properly (see RT#101121) + +0.307 2014-12-14 + - no Changes since 0.306_002 + +0.306_002 2014-12-08 + - fix perl_api_link test for broken environments of some windows + testers + +0.306_001 2014-12-01 + - indent source as requested via issue#4 by Dave Rolsky + - consolidate check_... function on_*_true/false parameters + (Thanks to Peter Rabbitson for being sounding board) + - introduce more Perlish tests whether XS build is sane: + check_produce_xs_build, check_produce_loadable_xs_build + (Thanks to Peter Rabbitson for being sounding board) + - extensive refactoring with some API modifcations (warned + users via mail and issue#5) + +0.305 2014-06-12 + - skip compiler based tests when compiler seems weird + - add check_sane_xs composition as discussed on cpan-workers@ + +0.304 2014-06-01 + - improve dealing with whitespaces in path's of programs + - reorder -lperl and $Config{perllibs} - let's see if that covers + all smokers + - some minor speed improvements (micro-optimization, but ...) + +0.303 2014-05-29 + - fix perl-api check for threaded perl's (by using XSUB.h) + - fix non-transient linking situations in perl link check + - cleanup temporary test dependecies + +0.302 2014-05-27 + - fix for snooping smoke targets + - deal with older ExtUtils::MakeMaker versions (can't handle multiple + authors) + - fix double "-lm" in negative test of libmath + +0.301 2014-05-26 + - Adding log-file output tee'ing as proposed by H.Merijn Brand and + rewrote tests against that API. Make perl.h compile test not TODO + for smokers. + +0.300 2014-05-20 + - add some code to tests to inspect the massive fail of 0.28 + - include compiler invocation in log on failure + - add support for appending to logfiles (see t/ for examples) + - tidy Makefile.PL a bit and try to improve smoke results + +0.29 2014-05-19 + - make perl extension tests optional - add support to analyse + is scheduled for 0.300 + +0.28 2014-05-18 + - fix perl 5.6 support + - improve existing prog checks when binaries with default ars are + returned + - honor environment variables as GNU Autoconf does + - add additional check_prog_... support fox lex and sed - most + other checks aren't suitable until a reasonable "postamble" + support is provided + - add support to prove whether perl development environment is + "sane" (as far that can be told) + - add checks to prove for pureperl build + +0.27 2014-04-25 + - fix broken Changes + - add some fixes for older Perls + +0.26 2014-04-23 + - Fix pkg-config test as it's intended (allow testing without + pkg-config binary) + - fix C::AC complains about unset results + +0.25 2014-04-14 + - Fix settings test that would complain with a duplicate plan + when no PkgConfig was present. + +0.24 2014-04-11 + - Fix lost dependencies during Makefile.PL update + - add even core dependencies to support older Perls + - adjust $LIBEXT/$EXEEXT initialization to support HP-UX/HPPA + +0.23 2014-04-10 + - bring back to 5.6 (Peter 'Ribasushi' Rabbitson) + - introduce pkg-config based checks (Jens 'Sno' Rehsack) + - fix spurious invocation issues (Jens 'Sno' Rehsack) + - Changes reformatted as per CPAN::Changes::Spec + +0.22 2012-12-11 + - Flag some more tests as TODO. + +0.21 2012-12-02 + - Flag -lm tests as 'TODO' as they might fail in some Windows + machines + +0.20 2012-11-09 + - Add stdint.h into check_default_headers + - Make POD tests author only. + +0.19 2012-02-07 + - Added new method, check_lm + +0.18 2012-02-02 + - 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 2012-01-04 + - Re-fixed tests that do not run in <= v5.010 + +0.17_02 2012-01-03 + - Fixed tests that do not run on older Perl version. + +0.17_01 2012-01-02 + - 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 2010-09-23 + - Config::AutoConf::Linker moved to ExtUtils::LibBuilder. + +0.15 2010-05-08 + - Config::AutoConf::Linker more silent. + +0.14 2010-02-14 + - Added rewind to Linker.pm module. This code is still under heavy tests. + +0.13 2009-06-02 + - First stable release with code to detect how to build a C dynamic library. + +0.12_3 2009-06-01 + - Trying other way arround to change LD_LIBRARY_PATH under + t/04, that was failing under FreeBSD. + +0.12_2 2009-05-19 + - Added t/04 that was missing from MANIFEST + +0.12_1 2009-05-18 + - Added code to detect how to build a library. + It is a big, really big hack. Still not documented. + +0.11 2009-01-09 + - check_prog with better support for Windows machines. + +0.10 2008-09-03 + - Removed the tilde on my name, from Makefile.PL. + Was generating some weird results on VMS and Solaris. + +0.09 2008-04-23 + - 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 2008-03-29 + - require a 5.8 Perl + +0.07 2008-03-19 + - re-factored some tests to make them Win-aware + +0.06 2008-03-19 + - added -quiet option to ExtUtils::CBuilder for less noise when + detecting things. + +0.05 2008-03-18 + - added 'check_prog_yacc' method to check for a yacc implementation + (see POD) + +0.04 2008-03-18 + - adapt to new ExtUtils::CBuilder API + +0.03 2005-08-12 + - Added 'check_file' and 'check_files' methods (kind of stupid methods) + +0.02 2005-02-14 + - 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); diff --git a/GPL-1 b/GPL-1 new file mode 100644 index 0000000..f5c0717 --- /dev/null +++ b/GPL-1 @@ -0,0 +1,252 @@ + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..414e541 --- /dev/null +++ b/LICENSE @@ -0,0 +1,16 @@ +This software is licensed under the same terms as Perl5 itself. +At the time of writing this means, you can redistribute it and/or +modify it under the terms of either: + + a) the GNU General Public License as published by the Free + Software Foundation; either version 1, or (at your option) any + later version, or + + b) the "Artistic License" + +which both comes with this Kit. + +This software is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either +the GNU General Public License or the Artistic License for more details. diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..ff227e5 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,16 @@ +ARTISTIC-1.0 +Changes +GPL-1 +lib/Config/AutoConf.pm +LICENSE +Makefile.PL +MANIFEST This list of files +MANIFEST.SKIP +README.md +t/00.load.t +t/01.checkprog.t +t/02.compile.t +t/03.link.t +t/testdata/foo.pc +META.yml Module YAML meta-data (added by MakeMaker) +META.json Module JSON meta-data (added by MakeMaker) diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP new file mode 100644 index 0000000..b153c7c --- /dev/null +++ b/MANIFEST.SKIP @@ -0,0 +1,35 @@ +\B\.svn\b +\B\.git\b +\.gitignore$ +\.[Bb][Aa][Kk]$ +\.orig$ +\.old$ +\.tdy$ +\.tmp$ +\..*sw? +^Makefile$ +^Build$ +^Build\.bat$ +\.Inline/.* +_Inline/.* +\.bak$ +\.tar$ +\.tgz$ +\.tar\.gz$ +^mess/ +^tmp/ +^testdata/ +^blib/ +^sandbox/ +^pm_to_blib$ +^_build/.* +~$ +.*\.planner +^\..* +Config-AutoConf-.* +^applied_patches/ +\bxt +^MYMETA\.json$ +^MYMETA\..*$ +cover_db +nytprof diff --git a/META.json b/META.json new file mode 100644 index 0000000..75cbbf6 --- /dev/null +++ b/META.json @@ -0,0 +1,93 @@ +{ + "abstract" : "A module to implement some of AutoConf macros in pure perl.", + "author" : [ + "Alberto Simoes ", + "Jens Rehsack ' + - 'Jens Rehsack 0, + 'strict' => 0, + 'warnings' => 0, + 'Carp' => 0, + 'Capture::Tiny' => 0, + 'Config' => 0, + 'Cwd' => 0, + 'Exporter' => 0, + 'File::Basename' => 0, + 'File::Spec' => 0, + 'File::Temp' => 0, + 'Text::ParseWords' => 0, +); +my %CONFIGURE_DEPS = ('ExtUtils::MakeMaker' => 0); +my %BUILD_DEPS = (); + +my %TEST_DEPS = ( + 'Test::More' => 0.90, + 'ExtUtils::CBuilder' => '0.23' +); +$] < 5.008 and $TEST_DEPS{'IO::String'} = 0; + +WriteMakefile1( + META_ADD => { + 'meta-spec' => {version => 2}, + resources => { + homepage => 'https://metacpan.org/release/Config-AutoConf', + repository => { + url => 'https://github.com:ambs/Config-AutoConf.git', + web => 'https://github.com/ambs/Config-AutoConf', + type => 'git', + }, + license => 'http://dev.perl.org/licenses/', + bugtracker => { + web => 'http://rt.cpan.org/Public/Dist/Display.html?Name=Config-AutoConf', + mailto => 'bug-Config-AutoConf@rt.cpan.org', + }, + x_IRC => "irc://irc.perl.org/#toolchain", + x_MailingList => "mailto:cpan-workers\@perl.org'", + }, + prereqs => { + develop => { + requires => { + 'Test::CPAN::Changes' => 0, + 'Test::CheckManifest' => 0, + 'Module::CPANTS::Analyse' => '0.96', + 'Test::Kwalitee' => 0, + 'Test::PerlTidy' => 0, + 'Test::Pod' => 0, + 'Test::Pod::Coverage' => 0, + 'Test::Pod::Spelling::CommonMistakes' => 0, + 'Test::Spelling' => 0, + }, + }, + configure => { + requires => {%CONFIGURE_DEPS}, + }, + build => { + requires => {%BUILD_DEPS}, + }, + test => { + requires => {%TEST_DEPS}, + }, + runtime => { + requires => {%RUN_DEPS}, + recommends => { + 'ExtUtils::CBuilder' => '0.280220', + 'File::Slurp::Tiny' => 0, + 'Scalar::Util' => '1.18', + }, + }, + }, + }, + NAME => 'Config::AutoConf', + AUTHOR => ['Alberto Simoes ', 'Jens Rehsack 'lib/Config/AutoConf.pm', + ABSTRACT_FROM => 'lib/Config/AutoConf.pm', + LICENSE => 'perl', + PREREQ_PM => \%RUN_DEPS, + BUILD_REQUIRES => \%BUILD_DEPS, + TEST_REQUIRES => \%TEST_DEPS, + test => {TESTS => 't/*.t xt/*.t'}, +); + +sub WriteMakefile1 +{ # originally written by Alexandr Ciornii, version 0.21. Added by eumm-upgrade. + my %params = @_; + my $eumm_version = $ExtUtils::MakeMaker::VERSION; + $eumm_version = eval $eumm_version; + die "EXTRA_META is deprecated" if (exists($params{EXTRA_META})); + die "License not specified" if (!exists($params{LICENSE})); + $params{TEST_REQUIRES} + and $eumm_version < 6.6303 + and $params{BUILD_REQUIRES} = {%{$params{BUILD_REQUIRES} || {}}, %{delete $params{TEST_REQUIRES}}}; + #EUMM 6.5502 has problems with BUILD_REQUIRES + $params{BUILD_REQUIRES} + and $eumm_version < 6.5503 + and $params{PREREQ_PM} = {%{$params{PREREQ_PM} || {}}, %{delete $params{BUILD_REQUIRES}}}; + ref $params{AUTHOR} + and "ARRAY" eq ref $params{AUTHOR} + and $eumm_version < 6.5702 + and $params{AUTHOR} = join(", ", @{$params{AUTHOR}}); + delete $params{CONFIGURE_REQUIRES} if ($eumm_version < 6.52); + delete $params{MIN_PERL_VERSION} if ($eumm_version < 6.48); + delete $params{META_MERGE} if ($eumm_version < 6.46); + delete $params{META_ADD}{prereqs} if ($eumm_version < 6.58); + delete $params{META_ADD}{'meta-spec'} if ($eumm_version < 6.58); + delete $params{META_ADD} if ($eumm_version < 6.46); + delete $params{LICENSE} if ($eumm_version < 6.31); + delete $params{AUTHOR} if ($] < 5.005); + delete $params{ABSTRACT_FROM} if ($] < 5.005); + delete $params{BINARY_LOCATION} if ($] < 5.005); + + # more or less taken from Moose' Makefile.PL + if ($params{CONFLICTS}) + { + my $ok = CheckConflicts(%params); + exit(0) if ($params{PREREQ_FATAL} and not $ok); + my $cpan_smoker = grep { $_ =~ m/(?:CR_SMOKER|CPAN_REPORTER|AUTOMATED_TESTING)/ } keys %ENV; + unless ($cpan_smoker || $ENV{PERL_MM_USE_DEFAULT}) + { + sleep 4 unless ($ok); + } + delete $params{CONFLICTS}; + } + + WriteMakefile(%params); +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..5af0c65 --- /dev/null +++ b/README.md @@ -0,0 +1,1044 @@ +# NAME + +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. + +# 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 + +# DESCRIPTION + +Config::AutoConf is intended to provide the same opportunities to Perl +developers as [GNU Autoconf](http://www.gnu.org/software/autoconf/) +does for Shell developers. + +As Perl is the second most deployed language (mind: every Unix comes +with Perl, several mini-computers have Perl and even lot's of Windows +machines run Perl software - which requires deployed Perl there, too), +this gives wider support than Shell based probes. + +The API is leaned against GNU Autoconf, but we try to make the API +(especially optional arguments) more Perl'ish than m4 abilities allow +to the original. + +# CONSTRUCTOR + +## new + +This function instantiates a new instance of Config::AutoConf, eg. to +configure child components. The constructor adds also values set via +environment variable `PERL5_AUTOCONF_OPTS`. + +# METHODS + +## 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. + +## check\_files + +This function checks if a set of files exist in the system and are +readable by the user. Returns a boolean. + +## check\_prog( $prog, \\@dirlist?, \\%options? ) + +This function checks for a program with the supplied name. In success +returns the full path for the executable; + +An optional array reference containing a list of directories to be searched +instead of $PATH is gracefully honored. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. + +## check\_progs(progs, \[dirlist\]) + +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. + +An optional array reference containing a list of directories to be searched +instead of $PATH is gracefully honored. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. The +name of the _$prog_ to check and the found full path are passed as first +and second argument to the _action\_on\_true_ callback. + +## check\_prog\_yacc + +From the autoconf documentation, + + If `bison' is found, set [...] `bison -y'. + Otherwise, if `byacc' is found, set [...] `byacc'. + Otherwise set [...] `yacc'. The result of this test can be influenced + by setting the variable YACC or the cache variable ac_cv_prog_YACC. + +Returns the full path, if found. + +## 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. + The result can be overridden by setting the variable AWK or the + cache variable ac_cv_prog_AWK. + +Note that it returns the full path, if found. + +## check\_prog\_egrep + +From the autoconf documentation, + + Check for `grep -E' and `egrep', in that order, and [...] output + [...] the first one that is found. The result can be overridden by + setting the EGREP variable and is cached in the ac_cv_path_EGREP + variable. + +Note that it returns the full path, if found. + +## check\_prog\_lex + +From the autoconf documentation, + + If flex is found, set output [...] to ‘flex’ and [...] to -lfl, if that + library is in a standard place. Otherwise set output [...] to ‘lex’ and + [...] to -ll, if found. If [...] packages [...] ship the generated + file.yy.c alongside the source file.l, this [...] allows users without a + lexer generator to still build the package even if the timestamp for + file.l is inadvertently changed. + +Note that it returns the full path, if found. + +The structure $self->{lex} is set with attributes + + prog => $LEX + lib => $LEXLIB + root => $lex_root + +## check\_prog\_sed + +From the autoconf documentation, + + Set output variable [...] to a Sed implementation that conforms to Posix + and does not have arbitrary length limits. Report an error if no + acceptable Sed is found. See Limitations of Usual Tools, for more + information about portability problems with Sed. + + The result of this test can be overridden by setting the SED variable and + is cached in the ac_cv_path_SED variable. + +Note that it returns the full path, if found. + +## check\_prog\_pkg\_config + +Checks for `pkg-config` program. No additional tests are made for it ... + +## check\_prog\_cc + +Determine a C compiler to use. Currently the probe is delegated to [ExtUtils::CBuilder](https://metacpan.org/pod/ExtUtils::CBuilder). + +## check\_cc + +(Deprecated) Old name of ["check\_prog\_cc"](#check_prog_cc). + +## check\_valid\_compiler + +This function checks for a valid compiler for the currently active language. +At the very moment only `C` is understood (corresponding to your compiler +default options, e.g. -std=gnu89). + +## check\_valid\_compilers(;\\@) + +Checks for valid compilers for each given language. When unspecified +defaults to `[ "C" ]`. + +## msg\_checking + +Prints "Checking @\_ ..." + +## msg\_result + +Prints result \\n + +## msg\_notice + +Prints "configure: " @\_ to stdout + +## msg\_warn + +Prints "configure: " @\_ to stderr + +## msg\_error + +Prints "configure: " @\_ to stderr and exits with exit code 0 (tells +toolchain to stop here and report unsupported environment) + +## 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). + +## define\_var( $name, $value \[, $comment \] ) + +Defines a check variable for later use in further checks or code to compile. +Returns the value assigned value + +## write\_config\_h( \[$target\] ) + +Writes the defined constants into given target: + + Config::AutoConf->write_config_h( "config.h" ); + +## push\_lang(lang \[, implementor \]) + +Puts the current used language on the stack and uses specified language +for subsequent operations until ending pop\_lang call. + +## pop\_lang(\[ lang \]) + +Pops the currently used language from the stack and restores previously used +language. If _lang_ specified, it's asserted that the current used language +equals to specified language (helps finding control flow bugs). + +## lang\_call( \[prologue\], function ) + +Builds program which simply calls given function. +When given, prologue is prepended otherwise, the default +includes are used. + +## lang\_build\_program( prologue, body ) + +Builds program for current chosen language. If no prologue is given +(_undef_), 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 + +## lang\_build\_bool\_test (prologue, test, \[@decls\]) + +Builds a static test which will fail to compile when test +evaluates to false. If `@decls` is given, it's prepended +before the test code at the variable definition place. + +## 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. + +## push\_preprocess\_flags + +Adds given flags to the parameter list for preprocessor invocation. + +## push\_compiler\_flags + +Adds given flags to the parameter list for compiler invocation. + +## push\_libraries + +Adds given list of libraries to the parameter list for linker invocation. + +## push\_library\_paths + +Adds given list of library paths to the parameter list for linker invocation. + +## push\_link\_flags + +Adds given flags to the parameter list for linker invocation. + +## compile\_if\_else( $src, \\%options? ) + +This function tries to compile specified code and returns a boolean value +containing check success state. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. + +## link\_if\_else( $src, \\%options? ) + +This function tries to compile and link specified code and returns a boolean +value containing check success state. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. + +## check\_cached( $cache-key, $check-title, \\&check-call, \\%options? ) + +Retrieves the result of a previous ["check\_cached"](#check_cached) invocation from +`cache-key`, or (when called for the first time) populates the cache +by invoking `\&check_call`. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed on **every** call +to check\_cached (not just the first cache-populating invocation), respectively. + +## cache\_val + +This function returns the value of a previously check\_cached call. + +## check\_decl( $symbol, \\%options? ) + +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 `ac_cv_decl_`\_symbol +variable. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be favoured +over `default includes` (represented by ["\_default\_includes"](#_default_includes)). If any of +_action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, both callbacks +are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. + +## check\_decls( symbols, \\%options? ) + +For each of the symbols (with optional function argument types for C++ +overloads), run [check\_decl](https://metacpan.org/pod/check_decl). + +Contrary to GNU autoconf, this method does not declare HAVE\_DECL\_symbol +macros for the resulting `confdefs.h`, because it differs as `check_decl` +between compiling languages. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be favoured +over `default includes` (represented by ["\_default\_includes"](#_default_includes)). If any of +_action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, both callbacks +are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. +Given callbacks for _action\_on\_symbol\_true_ or _action\_on\_symbol\_false_ are +called for each symbol checked using ["check\_decl"](#check_decl) receiving the symbol as +first argument. + +## check\_func( $function, \\%options? ) + +This method actually tests whether _$funcion_ can be linked into a program +trying to call _$function_. This method caches its result in the +ac\_cv\_func\_FUNCTION variable. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +If any of _action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, +both callbacks are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or +_action\_on\_false_ to `check_cached`, respectively. + +Returns: True if the function was found, false otherwise + +## check\_funcs( \\@functions-list, $action-if-true?, $action-if-false? ) + +The same as check\_func, but takes a list of functions in _\\@functions-list_ +to look for and checks for each in turn. Define HAVE\_FUNCTION for each +function that was found. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +If any of _action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, +both callbacks are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or +_action\_on\_false_ to `check_cached`, respectively. Given callbacks +for _action\_on\_function\_true_ or _action\_on\_function\_false_ are called for +each symbol checked using ["check\_func"](#check_func) receiving the symbol as first +argument. + +## check\_type( $symbol, \\%options? ) + +Check whether type is defined. It may be a compiler builtin type or defined +by the includes. In C, type must be a type-name, so that the expression +`sizeof (type)` is valid (but `sizeof ((type))` is not). + +If _type_ type is defined, preprocessor macro HAVE\__type_ (in all +capitals, with "\*" replaced by "P" and spaces and dots replaced by +underscores) is defined. + +This method caches its result in the `ac_cv_type_`type variable. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be favoured +over `default includes` (represented by ["\_default\_includes"](#_default_includes)). If any of +_action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, both callbacks +are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. + +## check\_types( \\@type-list, \\%options? ) + +For each type in _@type-list_, call [check\_type](https://metacpan.org/pod/check_type) is called to check +for type and return the accumulated result (accumulation op is binary and). + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be favoured +over `default includes` (represented by ["\_default\_includes"](#_default_includes)). If any of +_action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, both callbacks +are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. +Given callbacks for _action\_on\_type\_true_ or _action\_on\_type\_false_ are +called for each symbol checked using ["check\_type"](#check_type) receiving the symbol as +first argument. + +## compute\_int( $expression, @decls?, \\%options ) + +Returns the value of the integer _expression_. 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. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be favoured +over `default includes` (represented by ["\_default\_includes"](#_default_includes)). If any of +_action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, both callbacks +are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. + +## check\_sizeof\_type( $type, \\%options? ) + +Checks for the size of the specified type by compiling and define +`SIZEOF_type` 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", { prologue => $include_perl } ); + # or + $ac->check_sizeof_type( "struct utmpx.ut_id", { prologue => "#include " } ); + +This method caches its result in the `ac_cv_sizeof_`\_type variable. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be favoured +over `default includes` (represented by ["\_default\_includes"](#_default_includes)). If any of +_action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, both callbacks +are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. + +## check\_sizeof\_types( type, \\%options? ) + +For each type [check\_sizeof\_type](https://metacpan.org/pod/check_sizeof_type) is called to check for size of type. + +If _action-if-found_ is given, it is additionally executed when all of the +sizes of the types could determined. If _action-if-not-found_ is given, it +is executed when one size of the types could not determined. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be favoured +over `default includes` (represented by ["\_default\_includes"](#_default_includes)). If any of +_action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, both callbacks +are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. +Given callbacks for _action\_on\_size\_true_ or _action\_on\_size\_false_ are +called for each symbol checked using ["check\_sizeof\_type"](#check_sizeof_type) receiving the +symbol as first argument. + +## check\_alignof\_type( type, \\%options? ) + +Define ALIGNOF\_type to be the alignment in bytes of type. _type_ must +be valid as a structure member declaration or _type_ must be a structure +member itself. + +This method caches its result in the `ac_cv_alignof_`\_type +variable, with _\*_ mapped to `p` and other characters not suitable for a +variable name mapped to underscores. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be favoured +over `default includes` (represented by ["\_default\_includes"](#_default_includes)). If any of +_action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, both callbacks +are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. + +## check\_alignof\_types (type, \[action-if-found\], \[action-if-not-found\], \[prologue = default includes\]) + +For each type [check\_alignof\_type](https://metacpan.org/pod/check_alignof_type) is called to check for align of type. + +If _action-if-found_ is given, it is additionally executed when all of the +aligns of the types could determined. If _action-if-not-found_ is given, it +is executed when one align of the types could not determined. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be favoured +over `default includes` (represented by ["\_default\_includes"](#_default_includes)). If any of +_action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, both callbacks +are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. +Given callbacks for _action\_on\_align\_true_ or _action\_on\_align\_false_ are +called for each symbol checked using ["check\_alignof\_type"](#check_alignof_type) receiving the +symbol as first argument. + +## check\_member( member, \\%options? ) + +Check whether _member_ is in form of _aggregate_._member_ and +_member_ is a member of the _aggregate_ aggregate. + +which are used prior to the aggregate under test. + + Config::AutoConf->check_member( + "struct STRUCT_SV.sv_refcnt", + { + action_on_false => sub { Config::AutoConf->msg_failure( "sv_refcnt member required for struct STRUCT_SV" ); }, + prologue => "#include \n#include " + } + ); + +This function will return a true value (1) if the member is found. + +If _aggregate_ aggregate has _member_ member, preprocessor +macro HAVE\__aggregate_\__MEMBER_ (in all capitals, with spaces +and dots replaced by underscores) is defined. + +This macro caches its result in the `ac_cv_`aggr\_member variable. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be favoured +over `default includes` (represented by ["\_default\_includes"](#_default_includes)). If any of +_action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, both callbacks +are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. + +## check\_members( members, \\%options? ) + +For each member [check\_member](https://metacpan.org/pod/check_member) is called to check for member of aggregate. + +This function will return a true value (1) if at least one member is found. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be favoured +over `default includes` (represented by ["\_default\_includes"](#_default_includes)). If any of +_action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, both callbacks +are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. +Given callbacks for _action\_on\_member\_true_ or _action\_on\_member\_false_ are +called for each symbol checked using ["check\_member"](#check_member) receiving the symbol as +first argument. + +## check\_header( $header, \\%options? ) + +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. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +When a _prologue_ exists in the optional hash at end, it will be prepended +to the tested header. If any of _action\_on\_cache\_true_, +_action\_on\_cache\_false_ is defined, both callbacks are passed to +["check\_cached"](#check_cached) as _action\_on\_true_ or _action\_on\_false_ to +`check_cached`, respectively. + +## 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. + +Passes an optional \\%options hash to each ["check\_header"](#check_header) call. + +## check\_all\_headers + +This function checks each given header for usability and returns true +when each header can be used -- otherwise false. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +Each of existing key/value pairs using _prologue_, _action\_on\_cache\_true_ +or _action\_on\_cache\_false_ as key are passed-through to each call of +["check\_header"](#check_header). +Given callbacks for _action\_on\_header\_true_ or _action\_on\_header\_false_ are +called for each symbol checked using ["check\_header"](#check_header) receiving the symbol as +first argument. + +## 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. + +Passes an optional \\%options hash to each ["check\_all\_headers"](#check_all_headers) call. + +## check\_default\_headers + +This function checks for some default headers, the std c89 headers and +sys/types.h, sys/stat.h, memory.h, strings.h, inttypes.h, stdint.h and unistd.h + +Passes an optional \\%options hash to each ["check\_all\_headers"](#check_all_headers) call. + +## 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 `struct dirent`, not `struct direct`, and would access the length +of a directory entry name by passing a pointer to a `struct dirent` to +the `NAMLEN` macro. + +This method might be obsolescent, as all current systems with directory +libraries have `<`>. Programs supporting only newer OS +might not need to use this method. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +Each of existing key/value pairs using _prologue_, _action\_on\_header\_true_ +(as _action\_on\_true_ having the name of the tested header as first argument) +or _action\_on\_header\_false_ (as _action\_on\_false_ having the name of the +tested header as first argument) as key are passed-through to each call of +["\_check\_header"](#_check_header). +Given callbacks for _action\_on\_cache\_true_ or _action\_on\_cache\_false_ are +passed to the call of ["check\_cached"](#check_cached). + +## \_check\_perlapi\_program + +This method provides the program source which is suitable to do basic +compile/link tests to prove perl development environment. + +## \_check\_compile\_perlapi + +This method can be used from other checks to prove whether we have a perl +development environment or not (perl.h, reasonable basic checks - types, etc.) + +## check\_compile\_perlapi + +This method can be used from other checks to prove whether we have a perl +development environment or not (perl.h, reasonable basic checks - types, etc.) + +## check\_compile\_perlapi\_or\_die + +Dies when not being able to compile using the Perl API + +## check\_linkable\_xs\_so + +Checks whether a dynamic loadable object containing an XS module can be +linked or not. Due the nature of the beast, this test currently always +succeed. + +## check\_linkable\_xs\_so\_or\_die + +Dies when ["check\_linkable\_xs\_so"](#check_linkable_xs_so) fails. + +## check\_loadable\_xs\_so + +Checks whether a dynamic loadable object containing an XS module can be +loaded or not. Due the nature of the beast, this test currently always +succeed. + +## check\_loadable\_xs\_so\_or\_die + +Dies when ["check\_loadable\_xs\_so"](#check_loadable_xs_so) fails. + +## \_check\_link\_perlapi + +This method can be used from other checks to prove whether we have a perl +development environment including a suitable libperl or not (perl.h, +reasonable basic checks - types, etc.) + +Caller must ensure that the linker flags are set appropriate (`-lperl` +or similar). + +## check\_link\_perlapi + +This method can be used from other checks to prove whether we have a perl +development environment or not (perl.h, libperl.la, reasonable basic +checks - types, etc.) + +## check\_lib( lib, func, @other-libs?, \\%options? ) + +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. + +In case of function found, the HAVE\_LIBlibrary (all in capitals) +preprocessor macro is defined with 1 and $lib together with @other\_libs +are added to the list of libraries to link with. + +If linking with library results in unresolved symbols that would be +resolved by linking with additional libraries, give those libraries +as the _other-libs_ argument: e.g., `[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. + +This method caches its result in the `ac_cv_lib_`lib\_func variable. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +If any of _action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, +both callbacks are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or +_action\_on\_false_ to `check_cached`, respectively. + +It's recommended to use [search\_libs](https://metacpan.org/pod/search_libs) instead of check\_lib these days. + +## search\_libs( function, search-libs, @other-libs?, \\%options? ) + +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. +_search-libs_ 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. + +If linking with library results in unresolved symbols that would be +resolved by linking with additional libraries, give those libraries as +the _other-libraries_ argument: e.g., `[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 `0` if no +library containing function was found, otherwise as the -llibrary option +that needs to be prepended to LIBS. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +If any of _action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, +both callbacks are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or +_action\_on\_false_ to `check_cached`, respectively. Given callbacks +for _action\_on\_lib\_true_ or _action\_on\_lib\_false_ are called for +each library checked using ["link\_if\_else"](#link_if_else) receiving the library as +first argument and all `@other_libs` subsequently. + +## check\_lm( \\%options? ) + +This method is used to check if some common `math.h` functions are +available, and if `-lm` is needed. Returns the empty string if no +library is needed, or the "-lm" string if libm is needed. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +Each of existing key/value pairs using _action\_on\_func\_true_ (as +_action\_on\_true_ having the name of the tested functions as first argument), +_action\_on\_func\_false_ (as _action\_on\_false_ having the name of the tested +functions as first argument), _action\_on\_func\_lib\_true_ (as +_action\_on\_lib\_true_ having the name of the tested functions as first +argument), _action\_on\_func\_lib\_false_ (as _action\_on\_lib\_false_ having +the name of the tested functions as first argument) as key are passed- +through to each call of ["search\_libs"](#search_libs). +Given callbacks for _action\_on\_lib\_true_, _action\_on\_lib\_false_, +_action\_on\_cache\_true_ or _action\_on\_cache\_false_ are passed to the +call of ["search\_libs"](#search_libs). + +**Note** that _action\_on\_lib\_true_ and _action\_on\_func\_lib\_true_ or +_action\_on\_lib\_false_ and _action\_on\_func\_lib\_false_ cannot be used +at the same time, respectively. + +## pkg\_config\_package\_flags($package, \\%options?) + +Search for pkg-config flags for package as specified. The flags which are +extracted are `--cflags` and `--libs`. The extracted flags are appended +to the global `extra_compile_flags` and `extra_link_flags`, respectively. + +Call it with the package you're looking for and optional callback whether +found or not. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. +If any of _action\_on\_cache\_true_, _action\_on\_cache\_false_ is defined, +both callbacks are passed to ["check\_cached"](#check_cached) as _action\_on\_true_ or +_action\_on\_false_ to ["check\_cached"](#check_cached), respectively. + +## \_check\_mm\_pureperl\_build\_wanted + +This method proves the `_argv` attribute and (when set) the `PERL_MM_OPT` +whether they contain _PUREPERL\_ONLY=(0|1)_ or not. The attribute `_force_xs` +is set as appropriate, which allows a compile test to bail out when `Makefile.PL` +is called with _PUREPERL\_ONLY=0_. + +## \_check\_mb\_pureperl\_build\_wanted + +This method proves the `_argv` attribute and (when set) the `PERL_MB_OPT` +whether they contain _--pureperl-only_ or not. + +## \_check\_pureperl\_required + +This method calls `_check_mm_pureperl_build_wanted` when running under +[ExtUtils::MakeMaker](https://metacpan.org/pod/ExtUtils::MakeMaker) (`Makefile.PL`) or `_check_mb_pureperl_build_wanted` +when running under a `Build.PL` ([Module::Build](https://metacpan.org/pod/Module::Build) compatible) environment. + +When neither is found (`$0` contains neither `Makefile.PL` nor `Build.PL`), +simply 0 is returned. + +## check\_pureperl\_required + +This check method proves whether a pureperl build is wanted or not by +cached-checking `$self->_check_pureperl_required`. + +## check\_produce\_xs\_build + +This routine checks whether XS can be produced. Therefore it does +following checks in given order: + +- check pureperl environment variables (["check\_pureperl\_required"](#check_pureperl_required)) or +command line arguments and return false when pure perl is requested +- check whether a compiler is available (["check\_valid\_compilers"](#check_valid_compilers)) and +return false if none found +- check whether a test program accessing Perl API can be compiled and +die with error if not + +When all checks passed successfully, return a true value. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. + +## check\_produce\_loadable\_xs\_build + +This routine proves whether XS should be built and it's possible to create +a dynamic linked object which can be loaded using Perl's Dynaloader. + +The extension over ["check\_produce\_xs\_build"](#check_produce_xs_build) can be avoided by adding the +`notest_loadable_xs` to `$ENV{PERL5_AC_OPTS}`. + +If the very last parameter contains a hash reference, `CODE` references +to _action\_on\_true_ or _action\_on\_false_ are executed, respectively. + +## \_set\_argv + +Intended to act as a helper for evaluating given command line arguments. +Stores given arguments in instances `_argv` attribute. + +Call once at very begin of `Makefile.PL` or `Build.PL`: + + Your::Pkg::Config::AutoConf->_set_args(@ARGV); + +## \_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 + +## \_default\_includes\_with\_perl + +returns a string containing default includes for program prologue containing +_\_default\_includes_ plus + + #include + #include + +## add\_log\_fh + +Push new file handles at end of log-handles to allow tee-ing log-output + +## delete\_log\_fh + +Removes specified log file handles. This method allows you to shoot +yourself in the foot - it doesn't prove whether the primary nor the last handle +is removed. Use with caution. + +# AUTHOR + +Alberto Simões, `` + +Jens Rehsack, `` + +# NEXT STEPS + +Although a lot of work needs to be done, these are the next steps I +intend 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. + +# BUGS + +A lot. Portability is a pain. **. + +Please report any bugs or feature requests to +`bug-Config-AutoConf@rt.cpan.org`, or through the web interface at +[http://rt.cpan.org/NoAuth/Bugs.html?Dist=Config-AutoConf](http://rt.cpan.org/NoAuth/Bugs.html?Dist=Config-AutoConf). We will +be notified, and then you'll automatically be notified of progress +on your bug as we make changes. + +# SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc Config::AutoConf + +You can also look for information at: + +- AnnoCPAN: Annotated CPAN documentation + + [http://annocpan.org/dist/Config-AutoConf](http://annocpan.org/dist/Config-AutoConf) + +- CPAN Ratings + + [http://cpanratings.perl.org/dist/Config-AutoConf](http://cpanratings.perl.org/dist/Config-AutoConf) + +- MetaCPAN + + [https://metacpan.org/release/Config-AutoConf](https://metacpan.org/release/Config-AutoConf) + +- Git Repository + + [https://github.com/ambs/Config-AutoConf](https://github.com/ambs/Config-AutoConf) + +# ACKNOWLEDGEMENTS + +Michael Schwern for kind MacOS X help. + +Ken Williams for ExtUtils::CBuilder + +Peter Rabbitson for help on refactoring and making the API more Perl'ish + +# COPYRIGHT & LICENSE + +Copyright 2004-2016 by the Authors + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +# SEE ALSO + +ExtUtils::CBuilder(3) diff --git a/lib/Config/AutoConf.pm b/lib/Config/AutoConf.pm new file mode 100644 index 0000000..885ab5e --- /dev/null +++ b/lib/Config/AutoConf.pm @@ -0,0 +1,4026 @@ +package Config::AutoConf; + +use warnings; +use strict; + +use base 'Exporter'; + +our @EXPORT = ('$LIBEXT', '$EXEEXT'); + +use constant QUOTE => do { $^O eq "MSWin32" ? q["] : q['] }; + +use Config; +use Carp qw/croak/; + +use File::Temp qw/tempfile/; +use File::Basename; +use File::Spec; +use Text::ParseWords qw//; + +use Capture::Tiny qw/capture/; + +# in core since 5.7.3 +eval "use Scalar::Util qw/looks_like_number/;"; +__PACKAGE__->can("looks_like_number") or eval <<'EOP'; +=begin private + +=head2 looks_like_number + +=end private + +=cut + +# from PP part of Params::Util +sub looks_like_number { + local $_ = shift; + + # checks from perlfaq4 + return 0 if !defined($_); + if (ref($_)) { + return overload::Overloaded($_) ? defined(0 + $_) : 0; + } + return 1 if (/^[+-]?[0-9]+$/); # is a +/- integer + return 1 if (/^([+-]?)(?=[0-9]|\.[0-9])[0-9]*(\.[0-9]*)?([Ee]([+-]?[0-9]+))?$/); # a C float + return 1 if ($] >= 5.008 and /^(Inf(inity)?|NaN)$/i) or ($] >= 5.006001 and /^Inf$/i); + + 0; +} +EOP + +eval "use File::Slurp::Tiny qw/read_file/;"; +__PACKAGE__->can("read_file") or eval <<'EOP'; +=begin private + +=head2 read_file + +=end private + +=cut + +sub read_file { + my $fn = shift; + local $@ = ""; + open( my $fh, "<", $fn ) or croak "Error opening $fn: $!"; + my $fc = <$fh>; + close($fh) or croak "I/O error closing $fn: $!"; + return $fc; +} +EOP + +# PA-RISC1.1-thread-multi +my %special_dlext = ( + darwin => ".dylib", + MSWin32 => ".dll", + ($Config{archname} =~ m/PA-RISC/i ? ("hpux" => ".sl") : ()), +); + +our ($LIBEXT, $EXEEXT); + +defined $LIBEXT + or $LIBEXT = + defined $Config{so} ? "." . $Config{so} + : defined $special_dlext{$^O} ? $special_dlext{$^O} + : ".so"; +defined $EXEEXT + or $EXEEXT = ($^O eq "MSWin32") ? ".exe" : ""; + +=encoding UTF-8 + +=head1 NAME + +Config::AutoConf - A module to implement some of AutoConf macros in pure perl. + +=cut + +our $VERSION = '0.315'; +$VERSION = eval $VERSION; + +=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 DESCRIPTION + +Config::AutoConf is intended to provide the same opportunities to Perl +developers as L +does for Shell developers. + +As Perl is the second most deployed language (mind: every Unix comes +with Perl, several mini-computers have Perl and even lot's of Windows +machines run Perl software - which requires deployed Perl there, too), +this gives wider support than Shell based probes. + +The API is leaned against GNU Autoconf, but we try to make the API +(especially optional arguments) more Perl'ish than m4 abilities allow +to the original. + +=head1 CONSTRUCTOR + +=cut + +my $glob_instance; + +=head2 new + +This function instantiates a new instance of Config::AutoConf, eg. to +configure child components. The constructor adds also values set via +environment variable C. + +=cut + +sub new +{ + my $class = shift; + ref $class and $class = ref $class; + my %args = @_; + + my %flags = map { + my ($k, $v) = split("=", $_, 2); + defined $v or $v = 1; + ($k, $v) + } split(":", $ENV{PERL5_AC_OPTS}) if ($ENV{PERL5_AC_OPTS}); + + my %instance = ( + msg_prefix => 'configure: ', + lang => "C", + lang_stack => [], + lang_supported => { + "C" => $class->can("check_prog_cc"), + }, + cache => {}, + defines => {}, + extra_libs => [], + extra_lib_dirs => [], + extra_include_dirs => [], + extra_preprocess_flags => [], + extra_compile_flags => { + "C" => [], + }, + extra_link_flags => [], + logfile => "config.log", + c_ac_flags => {%flags}, + %args + ); + bless(\%instance, $class); +} + +=head1 METHODS + +=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->_get_instance(); + my $file = shift; + + my $cache_name = $self->_cache_name("file", $file); + $self->check_cached( + $cache_name, + "for $file", + sub { + -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->_get_instance(); + + for (@_) + { + return 0 unless $self->check_file($_); + } + + 1; +} + +sub _sanitize_prog +{ + my ($self, $prog) = @_; + (scalar Text::ParseWords::shellwords $prog) > 1 and $prog = QUOTE . $prog . QUOTE; + $prog; +} + +my @exe_exts = ($^O eq "MSWin32" ? qw(.exe .com .bat .cmd) : ("")); + +=head2 check_prog( $prog, \@dirlist?, \%options? ) + +This function checks for a program with the supplied name. In success +returns the full path for the executable; + +An optional array reference containing a list of directories to be searched +instead of $PATH is gracefully honored. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. + +=cut + +sub check_prog +{ + my $self = shift->_get_instance(); + # sanitize ac_prog + my $ac_prog = _sanitize(shift @_); + + my $options = {}; + scalar @_ > 1 and ref $_[-1] eq "HASH" and $options = pop @_; + + my @dirlist; + @_ and scalar @_ > 1 and @dirlist = @_; + @_ and scalar @_ == 1 and ref $_[0] eq "ARRAY" and @dirlist = @{$_[0]}; + @dirlist or @dirlist = split(/$Config{path_sep}/, $ENV{PATH}); + + for my $p (@dirlist) + { + for my $e (@exe_exts) + { + my $cmd = $self->_sanitize_prog(File::Spec->catfile($p, $ac_prog . $e)); + -x $cmd + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + -x $cmd and return $cmd; + } + } + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and $options->{action_on_false}->(); + + return; +} + +=head2 check_progs(progs, [dirlist]) + +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. + +An optional array reference containing a list of directories to be searched +instead of $PATH is gracefully honored. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. The +name of the I<$prog> to check and the found full path are passed as first +and second argument to the I callback. + +=cut + +sub check_progs +{ + my $self = shift->_get_instance(); + + my $options = {}; + scalar @_ > 1 and ref $_[-1] eq "HASH" and $options = pop @_; + + my @dirlist; + scalar @_ > 1 and ref $_[-1] eq "ARRAY" and @dirlist = @{pop @_}; + @dirlist or @dirlist = split(/$Config{path_sep}/, $ENV{PATH}); + + my @progs = @_; + foreach my $prog (@progs) + { + defined $prog or next; + + my $ans = $self->check_prog($prog, \@dirlist); + $ans + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_if_true}->($prog, $ans); + + $ans and return $ans; + } + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and $options->{action_on_false}->(); + + return; +} + +sub _append_prog_args +{ + my $self = shift->_get_instance(); + my $prog = shift; + join(" ", $self->_sanitize_prog($prog), @_); +} + +=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'. The result of this test can be influenced + by setting the variable YACC or the cache variable ac_cv_prog_YACC. + +Returns the full path, if found. + +=cut + +sub check_prog_yacc +{ + my $self = shift->_get_instance(); + + # my ($self, $cache_name, $message, $check_sub) = @_; + + my $cache_name = $self->_cache_name("prog", "YACC"); + $self->check_cached( + $cache_name, + "for yacc", + sub { + defined $ENV{YACC} and return $ENV{YACC}; + my $binary = $self->check_progs(qw/bison byacc yacc/); + defined $binary + and $binary =~ /bison(?:\.(?:exe|com|bat|cmd))?$/ + and $binary = $self->_append_prog_args($binary, "-y"); + 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. + The result can be overridden by setting the variable AWK or the + cache variable ac_cv_prog_AWK. + +Note that it returns the full path, if found. + +=cut + +sub check_prog_awk +{ + my $self = shift->_get_instance(); + my $cache_name = $self->_cache_name("prog", "AWK"); + $self->check_cached($cache_name, "for awk", sub { $ENV{AWK} || $self->check_progs(qw/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. The result can be overridden by + setting the EGREP variable and is cached in the ac_cv_path_EGREP + variable. + +Note that it returns the full path, if found. + +=cut + +sub check_prog_egrep +{ + my $self = shift->_get_instance(); + + my $cache_name = $self->_cache_name("prog", "EGREP"); + $self->check_cached( + $cache_name, + "for egrep", + sub { + defined $ENV{EGREP} and return $ENV{EGREP}; + my $grep; + $grep = $self->check_progs("egrep") and return $grep; + + if ($grep = $self->check_prog("grep")) + { + # check_run - Capture::Tiny, Open3 ... ftw! + my $ans = `echo a | ($grep -E '(a|b)') 2>/dev/null`; + chomp $ans; + $ans eq "a" and return $self->_append_prog_args($grep, "-E"); + } + } + ); +} + +=head2 check_prog_lex + +From the autoconf documentation, + + If flex is found, set output [...] to ‘flex’ and [...] to -lfl, if that + library is in a standard place. Otherwise set output [...] to ‘lex’ and + [...] to -ll, if found. If [...] packages [...] ship the generated + file.yy.c alongside the source file.l, this [...] allows users without a + lexer generator to still build the package even if the timestamp for + file.l is inadvertently changed. + +Note that it returns the full path, if found. + +The structure $self->{lex} is set with attributes + + prog => $LEX + lib => $LEXLIB + root => $lex_root + +=cut + +sub check_prog_lex +{ + my $self = shift->_get_instance; + my $cache_name = $self->_cache_name("prog", "LEX"); + my $lex = $self->check_cached($cache_name, "for lex", sub { $ENV{LEX} || $self->check_progs(qw/flex lex/) }); + if ($lex) + { + defined $self->{lex}->{prog} or $self->{lex}->{prog} = $lex; + my $lex_root_var = $self->check_cached( + "ac_cv_prog_lex_root", + "for lex output file root", + sub { + my ($fh, $filename) = tempfile( + "testXXXXXX", + SUFFIX => '.l', + UNLINK => 0 + ); + my $src = <<'EOLEX'; +%% +a { ECHO; } +b { REJECT; } +c { yymore (); } +d { yyless (1); } +e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */ + yyless ((input () != 0)); } +f { unput (yytext[0]); } +. { BEGIN INITIAL; } +%% +#ifdef YYTEXT_POINTER +extern char *yytext; +#endif +int +main (void) +{ + return ! yylex () + ! yywrap (); +} +EOLEX + + print {$fh} $src; + close $fh; + + my ($stdout, $stderr, $exit) = + capture { system($lex, $filename); }; + chomp $stdout; + unlink $filename; + -f "lex.yy.c" and return "lex.yy"; + -f "lexyy.c" and return "lexyy"; + $self->msg_error("cannot find output from $lex; giving up"); + } + ); + defined $self->{lex}->{root} or $self->{lex}->{root} = $lex_root_var; + + my $conftest = read_file($lex_root_var . ".c"); + unlink $lex_root_var . ".c"; + + $cache_name = $self->_cache_name("lib", "lex"); + my $check_sub = sub { + my @save_libs = @{$self->{extra_libs}}; + my $have_lib = 0; + foreach my $libstest (undef, qw(-lfl -ll)) + { + # 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); + $self->link_if_else($conftest) + and ($have_lib = defined($libstest) ? $libstest : "none required") + and last; + } + $self->{extra_libs} = [@save_libs]; + + if ($have_lib) + { + $self->define_var(_have_lib_define_name("lex"), $have_lib, "defined when lex library is available"); + } + else + { + $self->define_var(_have_lib_define_name("lex"), undef, "defined when lex library is available"); + } + return $have_lib; + }; + + my $lex_lib = $self->check_cached($cache_name, "lex library", $check_sub); + defined $self->{lex}->{lib} or $self->{lex}->{lib} = $lex_lib; + } + + $lex; +} + +=head2 check_prog_sed + +From the autoconf documentation, + + Set output variable [...] to a Sed implementation that conforms to Posix + and does not have arbitrary length limits. Report an error if no + acceptable Sed is found. See Limitations of Usual Tools, for more + information about portability problems with Sed. + + The result of this test can be overridden by setting the SED variable and + is cached in the ac_cv_path_SED variable. + +Note that it returns the full path, if found. + +=cut + +sub check_prog_sed +{ + my $self = shift->_get_instance(); + my $cache_name = $self->_cache_name("prog", "SED"); + $self->check_cached($cache_name, "for sed", sub { $ENV{SED} || $self->check_progs(qw/gsed sed/) }); +} + +=head2 check_prog_pkg_config + +Checks for C program. No additional tests are made for it ... + +=cut + +sub check_prog_pkg_config +{ + my $self = shift->_get_instance(); + my $cache_name = $self->_cache_name("prog", "PKG_CONFIG"); + $self->check_cached($cache_name, "for pkg-config", sub { $self->check_prog("pkg-config") }); +} + +=head2 check_prog_cc + +Determine a C compiler to use. Currently the probe is delegated to L. + +=cut + +sub check_prog_cc +{ + my $self = shift->_get_instance(); + my $cache_name = $self->_cache_name("prog", "CC"); + + $self->check_cached( + $cache_name, + "for cc", + sub { + $self->{lang_supported}->{C} = undef; + eval "use ExtUtils::CBuilder;"; + $@ and return; + my $cb = ExtUtils::CBuilder->new(quiet => 1); + $cb->have_compiler or return; + $self->{lang_supported}->{C} = "ExtUtils::CBuilder"; + $cb->{config}->{cc}; + } + ); +} + +=head2 check_cc + +(Deprecated) Old name of L. + +=cut + +sub check_cc { shift->check_prog_cc(@_) } + +=head2 check_valid_compiler + +This function checks for a valid compiler for the currently active language. +At the very moment only C is understood (corresponding to your compiler +default options, e.g. -std=gnu89). + +=cut + +sub check_valid_compiler +{ + my $self = shift->_get_instance; + my $lang = $self->{lang}; + $lang eq "C" or $self->msg_error("Language $lang is not supported"); + $self->check_prog_cc; +} + +=head2 check_valid_compilers(;\@) + +Checks for valid compilers for each given language. When unspecified +defaults to C<[ "C" ]>. + +=cut + +sub check_valid_compilers +{ + my $self = shift; + for my $lang (@{$_[0]}) + { + $self->push_lang($lang); + my $supp = $self->check_valid_compiler; + $self->pop_lang($lang); + $supp or return 0; + } + + 1; +} + +=head2 msg_checking + +Prints "Checking @_ ..." + +=cut + +sub msg_checking +{ + my $self = shift->_get_instance(); + $self->{quiet} + or print "Checking " . join(" ", @_) . "... "; + $self->_add_log_entry("Checking " . join(" ", @_, "...")); + return; +} + +=head2 msg_result + +Prints result \n + +=cut + +my @_num_to_msg = qw/no yes/; + +sub _neat +{ + defined $_[0] or return ""; + looks_like_number($_[0]) and defined $_num_to_msg[$_[0]] and return $_num_to_msg[$_[0]]; + $_[0]; +} + +sub msg_result +{ + my $self = shift->_get_instance(); + $self->{quiet} + or print join(" ", map { _neat $_ } @_), "\n"; + $self->_add_log_entry(join(" ", map { _neat $_ } @_), "\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"; + $self->_add_log_entry($self->{msg_prefix} . join(" ", @_) . "\n"); + return; +} + +=head2 msg_warn + +Prints "configure: " @_ to stderr + +=cut + +sub msg_warn +{ + my $self = shift->_get_instance(); + print STDERR $self->{msg_prefix} . join(" ", @_) . "\n"; + $self->_add_log_entry("WARNING: " . $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(); + print STDERR $self->{msg_prefix} . join(" ", @_) . "\n"; + $self->_add_log_entry("ERROR: " . $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(); + print STDERR $self->{msg_prefix} . join(" ", @_) . "\n"; + $self->_add_log_entry("FAILURE: " . $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. +Returns the value assigned value + +=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]; + $value; +} + +=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}]; + + $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} . ")"); + + $self->_set_language(@{pop @{$self->{lang_stack}}}); +} + +=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, $prologue, $body) = @_; + ref $self or $self = $self->_get_instance(); + + defined($prologue) or $prologue = $self->_default_includes(); + defined($body) or $body = ""; + $body = $self->_build_main($body); + + $self->_fill_defines() . "\n$prologue\n\n$body\n"; +} + +sub _lang_prologue_func +{ + my ($self, $prologue, $function) = @_; + ref $self or $self = $self->_get_instance(); + + 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 + + return $prologue; +} + +sub _lang_body_func +{ + my ($self, $function) = @_; + ref $self or $self = $self->_get_instance(); + + my $func_call = "return $function ();"; + return $func_call; +} + +=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, $prologue, $function) = @_; + ref $self or $self = $self->_get_instance(); + + return $self->lang_build_program($self->_lang_prologue_func($prologue, $function), $self->_lang_body_func($function),); +} + +sub _lang_prologue_builtin +{ + my ($self, $prologue, $builtin) = @_; + ref $self or $self = $self->_get_instance(); + + defined($prologue) or $prologue = $self->_default_includes(); + $prologue .= <<"_ACEOF"; +#if !defined(__has_builtin) +#undef $builtin +/* Declare this builtin with the same prototype as __builtin_$builtin. + This removes a warning about conflicting types for built-in builtin $builtin */ +__typeof__(__builtin_$builtin) $builtin; +__typeof__(__builtin_$builtin) *f = $builtin; +#endif +_ACEOF +} + +sub _lang_body_builtin +{ + my ($self, $builtin) = @_; + ref $self or $self = $self->_get_instance(); + + my $body = <<"_ACEOF"; +#if !defined(__has_builtin) +return f != $builtin; +#else +return __has_builtin($builtin); +#endif +_ACEOF + return $body; +} + +=head2 lang_builtin( [prologue], builtin ) + +Builds program which simply proves whether a builtin is known to +language compiler. + +=cut + +sub lang_builtin +{ + my ($self, $prologue, $builtin) = @_; + ref $self or $self = $self->_get_instance(); + + return $self->lang_build_program($self->_lang_prologue_func($prologue, $builtin), $self->_lang_body_builtin($builtin),); +} + +=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, $prologue, $test, @decls) = @_; + ref $self or $self = $self->_get_instance(); + + 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, @includes) = @_; + ref $self or $self = $self->_get_instance(); + + 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, @cpp_flags) = @_; + ref $self or $self = $self->_get_instance(); + + 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, @compiler_flags) = @_; + ref $self or $self = $self->_get_instance(); + 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, @libs) = @_; + ref $self or $self = $self->_get_instance(); + + 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, @libdirs) = @_; + ref $self or $self = $self->_get_instance(); + + 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, @link_flags) = @_; + ref $self or $self = $self->_get_instance(); + + push(@{$self->{extra_link_flags}}, @link_flags); + + return; +} + +=head2 compile_if_else( $src, \%options? ) + +This function tries to compile specified code and returns a boolean value +containing check success state. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. + +=cut + +sub compile_if_else +{ + my ($self, $src) = @_; + ref $self or $self = $self->_get_instance(); + + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + + my $builder = $self->_get_builder(); + + my ($fh, $filename) = tempfile( + "testXXXXXX", + SUFFIX => '.c', + UNLINK => 0 + ); + + print {$fh} $src; + close $fh; + + my ($obj_file, $outbuf, $errbuf, $exception); + ($outbuf, $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; + $obj_file and !-f $obj_file and undef $obj_file; + unlink $obj_file if $obj_file; + + if ($exception || !$obj_file) + { + $self->_add_log_lines("compile stage failed" . ($exception ? " - " . $exception : "")); + $errbuf + and $self->_add_log_lines($errbuf); + $self->_add_log_lines("failing program is:\n" . $src); + $outbuf + and $self->_add_log_lines("stdout was :\n" . $outbuf); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and $options->{action_on_false}->(); + + return 0; + } + + $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + 1; +} + +=head2 link_if_else( $src, \%options? ) + +This function tries to compile and link specified code and returns a boolean +value containing check success state. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. + +=cut + +sub link_if_else +{ + my ($self, $src) = @_; + ref $self or $self = $self->_get_instance(); + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + + my $builder = $self->_get_builder(); + + my ($fh, $filename) = tempfile( + "testXXXXXX", + SUFFIX => '.c', + UNLINK => 0 + ); + + print {$fh} $src; + close $fh; + + my ($obj_file, $outbuf, $errbuf, $exception); + ($outbuf, $errbuf) = capture + { + eval { + $obj_file = $builder->compile( + source => $filename, + include_dirs => $self->{extra_include_dirs}, + extra_compiler_flags => $self->_get_extra_compiler_flags() + ); + }; + + $exception = $@; + }; + + $obj_file and !-f $obj_file and undef $obj_file; + + if ($exception || !$obj_file) + { + $self->_add_log_lines("compile stage failed" . ($exception ? " - " . $exception : "")); + $errbuf + and $self->_add_log_lines($errbuf); + $self->_add_log_lines("failing program is:\n" . $src); + $outbuf + and $self->_add_log_lines("stdout was :\n" . $outbuf); + + unlink $filename; + unlink $obj_file if $obj_file; + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and $options->{action_on_false}->(); + + return 0; + } + + my $exe_file; + ($outbuf, $errbuf) = capture + { + eval { + $exe_file = $builder->link_executable( + objects => $obj_file, + extra_linker_flags => $self->_get_extra_linker_flags() + ); + }; + + $exception = $@; + }; + + $exe_file and !-f $exe_file and undef $exe_file; + + unlink $filename; + unlink $obj_file if $obj_file; + unlink $exe_file if $exe_file; + + if ($exception || !$exe_file) + { + $self->_add_log_lines("link stage failed" . ($exception ? " - " . $exception : "")); + $errbuf + and $self->_add_log_lines($errbuf); + $self->_add_log_lines("failing program is:\n" . $src); + $outbuf + and $self->_add_log_lines("stdout was :\n" . $outbuf); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and $options->{action_on_false}->(); + + return 0; + } + + $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + 1; +} + +=head2 check_cached( $cache-key, $check-title, \&check-call, \%options? ) + +Retrieves the result of a previous L invocation from +C, or (when called for the first time) populates the cache +by invoking C<\&check_call>. + +If the very last parameter contains a hash reference, C references +to I or I are executed on B call +to check_cached (not just the first cache-populating invocation), respectively. + +=cut + +sub check_cached +{ + my ($self, $cache_name, $message, $check_sub) = @_; + ref $self or $self = $self->_get_instance(); + my $options = {}; + scalar @_ > 4 and ref $_[-1] eq "HASH" and $options = pop @_; + + $self->msg_checking($message); + + defined $ENV{$cache_name} + and not defined $self->{cache}->{$cache_name} + and $self->{cache}->{$cache_name} = $ENV{$cache_name}; + + my @cached_result; + defined($self->{cache}->{$cache_name}) and push @cached_result, "(cached)"; + defined($self->{cache}->{$cache_name}) or $self->{cache}->{$cache_name} = $check_sub->(); + + $self->msg_result(@cached_result, $self->{cache}->{$cache_name}); + + $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $self->{cache}->{$cache_name} + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$self->{cache}->{$cache_name} + and $options->{action_on_false}->(); + + $self->{cache}->{$cache_name}; +} + +=head2 cache_val + +This function returns the value of a previously check_cached call. + +=cut + +sub cache_val +{ + my ($self, $cache_name) = @_; + ref $self or $self = $self->_get_instance(); + defined $self->{cache}->{$cache_name} or return; + $self->{cache}->{$cache_name}; +} + +=head2 check_decl( $symbol, \%options? ) + +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. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be favoured +over C (represented by L). If any of +I, I is defined, both callbacks +are passed to L as I or I to +C, respectively. + +=cut + +sub check_decl +{ + my ($self, $symbol) = @_; + $self = $self->_get_instance(); + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + + defined($symbol) or return croak("No symbol to check for"); + ref($symbol) eq "" or return croak("No symbol to check for"); + (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($options->{prologue}, $body); + + my $have_decl = $self->compile_if_else( + $conftest, + { + ($options->{action_on_true} ? (action_on_true => $options->{action_on_true}) : ()), + ($options->{action_on_false} ? (action_on_false => $options->{action_on_false}) : ()) + } + ); + + $have_decl; + }; + + $self->check_cached( + $cache_name, + "whether $symbol is declared", + $check_sub, + { + ($options->{action_on_cache_true} ? (action_on_true => $options->{action_on_cache_true}) : ()), + ($options->{action_on_cache_false} ? (action_on_false => $options->{action_on_cache_false}) : ()) + } + ); +} + +=head2 check_decls( symbols, \%options? ) + +For each of the symbols (with optional function argument types for C++ +overloads), run L. + +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. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be favoured +over C (represented by L). If any of +I, I is defined, both callbacks +are passed to L as I or I to +C, respectively. +Given callbacks for I or I are +called for each symbol checked using L receiving the symbol as +first argument. + +=cut + +sub check_decls +{ + my ($self, $symbols) = @_; + $self = $self->_get_instance(); + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + + my %pass_options; + defined $options->{prologue} and $pass_options{prologue} = $options->{prologue}; + defined $options->{action_on_cache_true} and $pass_options{action_on_cache_true} = $options->{action_on_cache_true}; + defined $options->{action_on_cache_false} and $pass_options{action_on_cache_false} = $options->{action_on_cache_false}; + + my $have_syms = 1; + foreach my $symbol (@$symbols) + { + $have_syms &= $self->check_decl( + $symbol, + { + %pass_options, + ( + $options->{action_on_symbol_true} && "CODE" eq ref $options->{action_on_symbol_true} + ? (action_on_true => sub { $options->{action_on_symbol_true}->($symbol) }) + : () + ), + ( + $options->{action_on_symbol_false} && "CODE" eq ref $options->{action_on_symbol_false} + ? (action_on_false => sub { $options->{action_on_symbol_false}->($symbol) }) + : () + ), + } + ); + } + + $have_syms + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$have_syms + and $options->{action_on_false}->(); + + $have_syms; +} + +sub _have_func_define_name +{ + my $func = $_[0]; + my $have_name = "HAVE_" . uc($func); + $have_name =~ tr/_A-Za-z0-9/_/c; + $have_name; +} + +=head2 check_func( $function, \%options? ) + +This method actually tests whether I<$funcion> can be linked into a program +trying to call I<$function>. This method caches its result in the +ac_cv_func_FUNCTION variable. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +If any of I, I is defined, +both callbacks are passed to L as I or +I to C, respectively. + +Returns: True if the function was found, false otherwise + +=cut + +sub check_func +{ + my ($self, $function) = @_; + $self = $self->_get_instance(); + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + + # Build the name of the cache variable. + my $cache_name = $self->_cache_name('func', $function); + # Wrap the actual check in a closure so that we can use check_cached. + my $check_sub = sub { + my $have_func = $self->link_if_else( + $self->lang_call(q{}, $function), + { + ($options->{action_on_true} ? (action_on_true => $options->{action_on_true}) : ()), + ($options->{action_on_false} ? (action_on_false => $options->{action_on_false}) : ()) + } + ); + $have_func; + }; + + # Run the check and cache the results. + return $self->check_cached( + $cache_name, + "for $function", + $check_sub, + { + action_on_true => sub { + $self->define_var( + _have_func_define_name($function), + $self->cache_val($cache_name), + "Defined when $function is available" + ); + $options->{action_on_cache_true} + and ref $options->{action_on_cache_true} eq "CODE" + and $options->{action_on_cache_true}->(); + }, + action_on_false => sub { + $self->define_var(_have_func_define_name($function), undef, "Defined when $function is available"); + $options->{action_on_cache_false} + and ref $options->{action_on_cache_false} eq "CODE" + and $options->{action_on_cache_false}->(); + }, + } + ); +} + +=head2 check_funcs( \@functions-list, $action-if-true?, $action-if-false? ) + +The same as check_func, but takes a list of functions in I<\@functions-list> +to look for and checks for each in turn. Define HAVE_FUNCTION for each +function that was found. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +If any of I, I is defined, +both callbacks are passed to L as I or +I to C, respectively. Given callbacks +for I or I are called for +each symbol checked using L receiving the symbol as first +argument. + +=cut + +sub check_funcs +{ + my ($self, $functions_ref) = @_; + $self = $self->_get_instance(); + + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + + my %pass_options; + defined $options->{action_on_cache_true} and $pass_options{action_on_cache_true} = $options->{action_on_cache_true}; + defined $options->{action_on_cache_false} and $pass_options{action_on_cache_false} = $options->{action_on_cache_false}; + + # Go through the list of functions and call check_func for each one. We + # generate new closures for the found and not-found functions that pass in + # the relevant function name. + my $have_funcs = 1; + for my $function (@{$functions_ref}) + { + # Build the code reference to run when a function was found. This defines + # a HAVE_FUNCTION symbol, plus runs the current $action-if-true if there is + # one. + $pass_options{action_on_true} = sub { + # Run the user-provided hook, if there is one. + defined $options->{action_on_function_true} + and ref $options->{action_on_function_true} eq "CODE" + and $options->{action_on_function_true}->($function); + }; + + defined $options->{action_on_function_false} + and ref $options->{action_on_function_false} eq "CODE" + and $pass_options{action_on_false} = sub { $options->{action_on_function_false}->($function); }; + + $have_funcs &= check_func($self, $function, \%pass_options); + } + + $have_funcs + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$have_funcs + and $options->{action_on_false}->(); + + return $have_funcs; +} + +=head2 check_builtin( $builtin, \%options? ) + +This method actually tests whether I<$builtin> is a supported built-in +known by the compiler. Either, by giving us the type of the built-in or +by taking the value from C<__has_builtin>. This method caches its result +in the ac_cv_builtin_FUNCTION variable. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +If any of I, I is defined, +both callbacks are passed to L as I or +I to C, respectively. + +Returns: True if the function was found, false otherwise + +=cut + +sub _have_builtin_define_name +{ + my $builtin = $_[0]; + my $have_name = "HAVE_BUILTIN_" . uc($builtin); + $have_name =~ tr/_A-Za-z0-9/_/c; + $have_name; +} + +sub check_builtin +{ + my ($self, $builtin) = @_; + $self = $self->_get_instance(); + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + + # Build the name of the cache variable. + my $cache_name = $self->_cache_name('builtin', $builtin); + # Wrap the actual check in a closure so that we can use check_cached. + my $check_sub = sub { + my $have_builtin = $self->link_if_else( + $self->lang_builtin(q{}, $builtin), + { + ($options->{action_on_true} ? (action_on_true => $options->{action_on_true}) : ()), + ($options->{action_on_false} ? (action_on_false => $options->{action_on_false}) : ()) + } + ); + $have_builtin; + }; + + # Run the check and cache the results. + return $self->check_cached( + $cache_name, + "for builtin $builtin", + $check_sub, + { + action_on_true => sub { + $self->define_var( + _have_builtin_define_name($builtin), + $self->cache_val($cache_name), + "Defined when builtin $builtin is available" + ); + $options->{action_on_cache_true} + and ref $options->{action_on_cache_true} eq "CODE" + and $options->{action_on_cache_true}->(); + }, + action_on_false => sub { + $self->define_var(_have_builtin_define_name($builtin), undef, "Defined when builtin $builtin is available"); + $options->{action_on_cache_false} + and ref $options->{action_on_cache_false} eq "CODE" + and $options->{action_on_cache_false}->(); + }, + } + ); +} + +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; + $have_name; +} + +=head2 check_type( $symbol, \%options? ) + +Check whether type is defined. It may be a compiler builtin type or defined +by the includes. 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. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be favoured +over C (represented by L). If any of +I, I is defined, both callbacks +are passed to L as I or I to +C, respectively. + +=cut + +sub check_type +{ + my ($self, $type) = @_; + $self = $self->_get_instance(); + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + + defined($type) or return croak("No type to check for"); + ref($type) eq "" or return croak("No type to check for"); + + my $cache_name = $self->_cache_type_name("type", $type); + my $check_sub = sub { + + my $body = <lang_build_program($options->{prologue}, $body); + + my $have_type = $self->compile_if_else( + $conftest, + { + ($options->{action_on_true} ? (action_on_true => $options->{action_on_true}) : ()), + ($options->{action_on_false} ? (action_on_false => $options->{action_on_false}) : ()) + } + ); + $have_type; + }; + + $self->check_cached( + $cache_name, + "for $type", + $check_sub, + { + action_on_true => sub { + $self->define_var(_have_type_define_name($type), $self->cache_val($cache_name), + "defined when $type is available"); + $options->{action_on_cache_true} + and ref $options->{action_on_cache_true} eq "CODE" + and $options->{action_on_cache_true}->(); + }, + action_on_false => sub { + $self->define_var(_have_type_define_name($type), undef, "defined when $type is available"); + $options->{action_on_cache_false} + and ref $options->{action_on_cache_false} eq "CODE" + and $options->{action_on_cache_false}->(); + }, + } + ); +} + +=head2 check_types( \@type-list, \%options? ) + +For each type in I<@type-list>, call L is called to check +for type and return the accumulated result (accumulation op is binary and). + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be favoured +over C (represented by L). If any of +I, I is defined, both callbacks +are passed to L as I or I to +C, respectively. +Given callbacks for I or I are +called for each symbol checked using L receiving the symbol as +first argument. + +=cut + +sub check_types +{ + my ($self, $types) = @_; + $self = $self->_get_instance(); + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + + my %pass_options; + defined $options->{prologue} and $pass_options{prologue} = $options->{prologue}; + defined $options->{action_on_cache_true} and $pass_options{action_on_cache_true} = $options->{action_on_cache_true}; + defined $options->{action_on_cache_false} and $pass_options{action_on_cache_false} = $options->{action_on_cache_false}; + + my $have_types = 1; + foreach my $type (@$types) + { + $have_types &= $self->check_type( + $type, + { + %pass_options, + ( + $options->{action_on_type_true} && "CODE" eq ref $options->{action_on_type_true} + ? (action_on_true => sub { $options->{action_on_type_true}->($type) }) + : () + ), + ( + $options->{action_on_type_false} && "CODE" eq ref $options->{action_on_type_false} + ? (action_on_false => sub { $options->{action_on_type_false}->($type) }) + : () + ), + } + ); + } + + $have_types + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$have_types + and $options->{action_on_false}->(); + + $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, @decls?, \%options ) + +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. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be favoured +over C (represented by L). If any of +I, I is defined, both callbacks +are passed to L as I or I to +C, respectively. + +=cut + +sub _expr_value_define_name +{ + my $expr = $_[0]; + my $have_name = "EXPR_" . uc($expr); + $have_name =~ tr/*/P/; + $have_name =~ tr/_A-Za-z0-9/_/c; + $have_name; +} + +sub compute_int +{ + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + my ($self, $expr, @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, $options->{prologue}, @decls); + + defined $val + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !defined $val + and $options->{action_on_false}->(); + + $val; + }; + + $self->check_cached( + $cache_name, + "for compute result of ($expr)", + $check_sub, + { + action_on_true => sub { + $self->define_var( + _expr_value_define_name($expr), + $self->cache_val($cache_name), + "defined when ($expr) could computed" + ); + $options->{action_on_cache_true} + and ref $options->{action_on_cache_true} eq "CODE" + and $options->{action_on_cache_true}->(); + }, + action_on_false => sub { + $self->define_var(_expr_value_define_name($expr), undef, "defined when ($expr) could computed"); + $options->{action_on_cache_false} + and ref $options->{action_on_cache_false} eq "CODE" + and $options->{action_on_cache_false}->(); + }, + } + ); +} + +=head2 check_sizeof_type( $type, \%options? ) + +Checks for the size of the specified type by compiling and define +C 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", { prologue => $include_perl } ); + # or + $ac->check_sizeof_type( "struct utmpx.ut_id", { prologue => "#include " } ); + +This method caches its result in the Cset langE>_type variable. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be favoured +over C (represented by L). If any of +I, I is defined, both callbacks +are passed to L as I or I to +C, respectively. + +=cut + +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; + $have_name; +} + +sub check_sizeof_type +{ + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + my ($self, $type) = @_; + $self = $self->_get_instance(); + defined($type) or return croak("No type to check for"); + ref($type) eq "" or return croak("No type to check for"); + + 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)", $options->{prologue}, @decls); + + $typesize + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$typesize + and $options->{action_on_false}->(); + + $typesize; + }; + + $self->check_cached( + $cache_name, + "for size of $type", + $check_sub, + { + action_on_true => sub { + $self->define_var( + _sizeof_type_define_name($type), + $self->cache_val($cache_name), + "defined when sizeof($type) is available" + ); + $options->{action_on_cache_true} + and ref $options->{action_on_cache_true} eq "CODE" + and $options->{action_on_cache_true}->(); + }, + action_on_false => sub { + $self->define_var(_sizeof_type_define_name($type), undef, "defined when sizeof($type) is available"); + $options->{action_on_cache_false} + and ref $options->{action_on_cache_false} eq "CODE" + and $options->{action_on_cache_false}->(); + }, + } + ); +} + +=head2 check_sizeof_types( type, \%options? ) + +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. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be favoured +over C (represented by L). If any of +I, I is defined, both callbacks +are passed to L as I or I to +C, respectively. +Given callbacks for I or I are +called for each symbol checked using L receiving the +symbol as first argument. + +=cut + +sub check_sizeof_types +{ + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + my ($self, $types) = @_; + $self = $self->_get_instance(); + + my %pass_options; + defined $options->{prologue} and $pass_options{prologue} = $options->{prologue}; + defined $options->{action_on_cache_true} and $pass_options{action_on_cache_true} = $options->{action_on_cache_true}; + defined $options->{action_on_cache_false} and $pass_options{action_on_cache_false} = $options->{action_on_cache_false}; + + my $have_sizes = 1; + foreach my $type (@$types) + { + $have_sizes &= !!( + $self->check_sizeof_type( + $type, + { + %pass_options, + ( + $options->{action_on_size_true} && "CODE" eq ref $options->{action_on_size_true} + ? (action_on_true => sub { $options->{action_on_size_true}->($type) }) + : () + ), + ( + $options->{action_on_size_false} && "CODE" eq ref $options->{action_on_size_false} + ? (action_on_false => sub { $options->{action_on_size_false}->($type) }) + : () + ), + } + ) + ); + } + + $have_sizes + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$have_sizes + and $options->{action_on_false}->(); + + $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; + $have_name; +} + +=head2 check_alignof_type( type, \%options? ) + +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. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be favoured +over C (represented by L). If any of +I, I is defined, both callbacks +are passed to L as I or I to +C, respectively. + +=cut + +sub check_alignof_type +{ + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + my ($self, $type) = @_; + $self = $self->_get_instance(); + defined($type) or return croak("No type to check for"); + ref($type) eq "" or return croak("No type to check for"); + + 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)", $options->{prologue}, @decls); + + $typealign + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$typealign + and $options->{action_on_false}->(); + + $typealign; + }; + + $self->check_cached( + $cache_name, + "for align of $type", + $check_sub, + { + action_on_true => sub { + $self->define_var( + _alignof_type_define_name($type), + $self->cache_val($cache_name), + "defined when alignof($type) is available" + ); + $options->{action_on_cache_true} + and ref $options->{action_on_cache_true} eq "CODE" + and $options->{action_on_cache_true}->(); + }, + action_on_false => sub { + $self->define_var(_alignof_type_define_name($type), undef, "defined when alignof($type) is available"); + $options->{action_on_cache_false} + and ref $options->{action_on_cache_false} eq "CODE" + and $options->{action_on_cache_false}->(); + }, + } + ); +} + +=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. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be favoured +over C (represented by L). If any of +I, I is defined, both callbacks +are passed to L as I or I to +C, respectively. +Given callbacks for I or I are +called for each symbol checked using L receiving the +symbol as first argument. + +=cut + +sub check_alignof_types +{ + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + my ($self, $types) = @_; + $self = $self->_get_instance(); + + my %pass_options; + defined $options->{prologue} and $pass_options{prologue} = $options->{prologue}; + defined $options->{action_on_cache_true} and $pass_options{action_on_cache_true} = $options->{action_on_cache_true}; + defined $options->{action_on_cache_false} and $pass_options{action_on_cache_false} = $options->{action_on_cache_false}; + + my $have_aligns = 1; + foreach my $type (@$types) + { + $have_aligns &= !!( + $self->check_alignof_type( + $type, + { + %pass_options, + ( + $options->{action_on_align_true} && "CODE" eq ref $options->{action_on_align_true} + ? (action_on_true => sub { $options->{action_on_align_true}->($type) }) + : () + ), + ( + $options->{action_on_align_false} && "CODE" eq ref $options->{action_on_align_false} + ? (action_on_false => sub { $options->{action_on_align_false}->($type) }) + : () + ), + } + ) + ); + } + + $have_aligns + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$have_aligns + and $options->{action_on_false}->(); + + $have_aligns; +} + +sub _have_member_define_name +{ + my $member = $_[0]; + my $have_name = "HAVE_" . uc($member); + $have_name =~ tr/_A-Za-z0-9/_/c; + $have_name; +} + +=head2 check_member( member, \%options? ) + +Check whether I is in form of I.I and +I is a member of the I aggregate. + +which are used prior to the aggregate under test. + + Config::AutoConf->check_member( + "struct STRUCT_SV.sv_refcnt", + { + action_on_false => sub { Config::AutoConf->msg_failure( "sv_refcnt member required for struct STRUCT_SV" ); }, + prologue => "#include \n#include " + } + ); + +This function will return a true value (1) if the member is found. + +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. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be favoured +over C (represented by L). If any of +I, I is defined, both callbacks +are passed to L as I or I to +C, respectively. + +=cut + +sub check_member +{ + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + my ($self, $member) = @_; + $self = $self->_get_instance(); + defined($member) or return croak("No type to check for"); + ref($member) eq "" or return croak("No type to check for"); + + $member =~ m/^([^.]+)\.([^.]+)$/ or return croak("check_member(\"struct foo.member\", \%options)"); + my $type = $1; + $member = $2; + + my $cache_name = $self->_cache_type_name("$type.$member"); + my $check_sub = sub { + + my $body = <lang_build_program($options->{prologue}, $body); + my $have_member = $self->compile_if_else($conftest); + + unless ($have_member) + { + $body = <lang_build_program($options->{prologue}, $body); + $have_member = $self->compile_if_else($conftest); + } + + $have_member + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and $options->{action_on_false}->() + unless $have_member; + + $have_member; + }; + + $self->check_cached( + $cache_name, + "for $type.$member", + $check_sub, + { + action_on_true => sub { + $self->define_var( + _have_member_define_name("$type.$member"), + $self->cache_val($cache_name), + "defined when $type.$member is available" + ); + $options->{action_on_cache_true} + and ref $options->{action_on_cache_true} eq "CODE" + and $options->{action_on_cache_true}->(); + }, + action_on_false => sub { + $self->define_var(_have_member_define_name("$type.$member"), undef, "defined when $type.$member is available"); + $options->{action_on_cache_false} + and ref $options->{action_on_cache_false} eq "CODE" + and $options->{action_on_cache_false}->(); + }, + } + ); +} + +=head2 check_members( members, \%options? ) + +For each member L is called to check for member of aggregate. + +This function will return a true value (1) if at least one member is found. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be favoured +over C (represented by L). If any of +I, I is defined, both callbacks +are passed to L as I or I to +C, respectively. +Given callbacks for I or I are +called for each symbol checked using L receiving the symbol as +first argument. + +=cut + +sub check_members +{ + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + my ($self, $members) = @_; + $self = $self->_get_instance(); + + my %pass_options; + defined $options->{prologue} and $pass_options{prologue} = $options->{prologue}; + defined $options->{action_on_cache_true} and $pass_options{action_on_cache_true} = $options->{action_on_cache_true}; + defined $options->{action_on_cache_false} and $pass_options{action_on_cache_false} = $options->{action_on_cache_false}; + + my $have_members = 0; + foreach my $member (@$members) + { + $have_members |= ( + $self->check_member( + $member, + { + %pass_options, + ( + $options->{action_on_member_true} && "CODE" eq ref $options->{action_on_member_true} + ? (action_on_true => sub { $options->{action_on_member_true}->($member) }) + : () + ), + ( + $options->{action_on_member_false} && "CODE" eq ref $options->{action_on_member_false} + ? (action_on_false => sub { $options->{action_on_member_false}->($member) }) + : () + ), + } + ) + ); + } + + $have_members + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$have_members + and $options->{action_on_false}->(); + + $have_members; +} + +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 $options = {}; + scalar @_ > 4 and ref $_[-1] eq "HASH" and $options = pop @_; + my ($self, $header, $prologue, $body) = @_; + + $prologue .= <<"_ACEOF"; + #include <$header> +_ACEOF + my $conftest = $self->lang_build_program($prologue, $body); + + $self->compile_if_else($conftest, $options); +} + +=head2 check_header( $header, \%options? ) + +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. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +When a I exists in the optional hash at end, it will be prepended +to the tested header. If any of I, +I is defined, both callbacks are passed to +L as I or I to +C, respectively. + +=cut + +sub check_header +{ + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + my ($self, $header) = @_; + $self = $self->_get_instance(); + defined($header) or return croak("No type to check for"); + ref($header) eq "" or return croak("No type to check for"); + + return 0 unless $header; + my $cache_name = $self->_cache_name($header); + my $check_sub = sub { + my $prologue = defined $options->{prologue} ? $options->{prologue} : ""; + + my $have_header = $self->_check_header( + $header, + $prologue, + "", + { + ($options->{action_on_true} ? (action_on_true => $options->{action_on_true}) : ()), + ($options->{action_on_false} ? (action_on_false => $options->{action_on_false}) : ()) + } + ); + + $have_header; + }; + + $self->check_cached( + $cache_name, + "for $header", + $check_sub, + { + action_on_true => sub { + $self->define_var( + _have_header_define_name($header), + $self->cache_val($cache_name), + "defined when $header is available" + ); + $options->{action_on_cache_true} + and ref $options->{action_on_cache_true} eq "CODE" + and $options->{action_on_cache_true}->(); + }, + action_on_false => sub { + $self->define_var(_have_header_define_name($header), undef, "defined when $header is available"); + $options->{action_on_cache_false} + and ref $options->{action_on_cache_false} eq "CODE" + and $options->{action_on_cache_false}->(); + }, + } + ); +} + +=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. + +Passes an optional \%options hash to each L call. + +=cut + +sub check_headers +{ + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + my $self = shift->_get_instance(); + $self->check_header($_, $options) and return $_ for (@_); + return; +} + +=head2 check_all_headers + +This function checks each given header for usability and returns true +when each header can be used -- otherwise false. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +Each of existing key/value pairs using I, I +or I as key are passed-through to each call of +L. +Given callbacks for I or I are +called for each symbol checked using L receiving the symbol as +first argument. + +=cut + +sub check_all_headers +{ + my $options = {}; + scalar @_ > 2 and ref $_[-1] eq "HASH" and $options = pop @_; + my $self = shift->_get_instance(); + @_ or return; + + my %pass_options; + defined $options->{prologue} and $pass_options{prologue} = $options->{prologue}; + defined $options->{action_on_cache_true} and $pass_options{action_on_cache_true} = $options->{action_on_cache_true}; + defined $options->{action_on_cache_false} and $pass_options{action_on_cache_false} = $options->{action_on_cache_false}; + + my $all_headers = 1; + foreach my $header (@_) + { + $all_headers &= $self->check_header( + $header, + { + %pass_options, + ( + $options->{action_on_header_true} && "CODE" eq ref $options->{action_on_header_true} + ? (action_on_true => sub { $options->{action_on_header_true}->($header) }) + : () + ), + ( + $options->{action_on_header_false} && "CODE" eq ref $options->{action_on_header_false} + ? (action_on_false => sub { $options->{action_on_header_false}->($header) }) + : () + ), + } + ); + } + + $all_headers + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$all_headers + and $options->{action_on_false}->(); + + $all_headers; +} + +=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. + +Passes an optional \%options hash to each L call. + +=cut + +my @ansi_c_headers = qw(stdlib stdarg string float assert ctype errno limits locale math setjmp signal stddef stdio time); + +sub check_stdc_headers +{ + my $options = {}; + scalar @_ > 1 and ref $_[-1] eq "HASH" and $options = pop @_; + my $self = shift->_get_instance(); + + # XXX for C++ the map should look like "c${_}" ... + my @c_ansi_c_headers = map { "${_}.h" } @ansi_c_headers; + my $rc = $self->check_all_headers(@c_ansi_c_headers, $options); + $rc and $self->define_var("STDC_HEADERS", 1, "Define to 1 if you have the ANSI C header files."); + $rc; +} + +=head2 check_default_headers + +This function checks for some default headers, the std c89 headers and +sys/types.h, sys/stat.h, memory.h, strings.h, inttypes.h, stdint.h and unistd.h + +Passes an optional \%options hash to each L call. + +=cut + +sub check_default_headers +{ + my $options = {}; + scalar @_ > 1 and ref $_[-1] eq "HASH" and $options = pop @_; + my $self = shift->_get_instance(); + $self->check_stdc_headers($options) + and $self->check_all_headers(qw(sys/types.h sys/stat.h memory.h strings.h inttypes.h stdint.h unistd.h), $options); +} + +=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. + +For the found header, the macro HAVE_DIRENT_IN_${header} is defined. + +This method might be obsolescent, as all current systems with directory +libraries have C<< Edirent.hE >>. Programs supporting only newer OS +might not need to use this method. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +Each of existing key/value pairs using I, I +(as I having the name of the tested header as first argument) +or I (as I having the name of the +tested header as first argument) as key are passed-through to each call of +L. +Given callbacks for I or I are +passed to the call of L. + +=cut + +sub _have_dirent_header_define_name +{ + my $header = $_[0]; + my $have_name = "HAVE_DIRENT_IN_" . uc($header); + $have_name =~ tr/_A-Za-z0-9/_/c; + return $have_name; +} + +sub check_dirent_header +{ + my $options = {}; + scalar @_ > 1 and ref $_[-1] eq "HASH" and $options = pop @_; + my $self = shift->_get_instance(); + + my %pass_options; + defined $options->{prologue} and $pass_options{prologue} = $options->{prologue}; + + my $have_dirent; + foreach my $header (qw(dirent.h sys/ndir.h sys/dir.h ndir.h)) + { + if ($self->check_header($header)) + { + my $cache_name = $self->_cache_name("dirent", $header); + my $check_sub = sub { + my $have_dirent; + $have_dirent = $self->_check_header( + $header, + "#include \n", + "if ((DIR *) 0) { return 0; }", + { + %pass_options, + ( + $options->{action_on_header_true} && "CODE" eq ref $options->{action_on_header_true} + ? (action_on_true => sub { $options->{action_on_header_true}->($header) }) + : () + ), + ( + $options->{action_on_header_false} && "CODE" eq ref $options->{action_on_header_false} + ? (action_on_false => sub { $options->{action_on_header_false}->($header) }) + : () + ), + } + ); + }; + + $have_dirent = $self->check_cached( + $cache_name, + "for header defining DIR *", + $check_sub, + { + action_on_true => sub { + $self->define_var( + _have_dirent_header_define_name($header), + $self->cache_val($cache_name), + "defined when $header is available" + ); + $options->{action_on_cache_true} + and ref $options->{action_on_cache_true} eq "CODE" + and $options->{action_on_cache_true}->(); + }, + action_on_false => sub { + $self->define_var(_have_dirent_header_define_name($header), undef, "defined when $header is available"); + $options->{action_on_cache_false} + and ref $options->{action_on_cache_false} eq "CODE" + and $options->{action_on_cache_false}->(); + }, + } + ); + + $have_dirent and $have_dirent = $header and last; + } + } + + $have_dirent + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$have_dirent + and $options->{action_on_false}->(); + + $have_dirent; +} + +=head2 _check_perlapi_program + +This method provides the program source which is suitable to do basic +compile/link tests to prove perl development environment. + +=cut + +sub _check_perlapi_program +{ + my $self = shift; + + my $includes = $self->_default_includes_with_perl(); + my $perl_check_body = <<'EOB'; + I32 rc; + SV *foo = newSVpv("Perl rocks", 11); + rc = SvCUR(foo); +EOB + $self->lang_build_program($includes, $perl_check_body); +} + +=head2 _check_compile_perlapi + +This method can be used from other checks to prove whether we have a perl +development environment or not (perl.h, reasonable basic checks - types, etc.) + +=cut + +sub _check_compile_perlapi +{ + my $self = shift; + + my $conftest = $self->_check_perlapi_program(); + $self->compile_if_else($conftest); +} + +=head2 check_compile_perlapi + +This method can be used from other checks to prove whether we have a perl +development environment or not (perl.h, reasonable basic checks - types, etc.) + +=cut + +sub check_compile_perlapi +{ + my $self = shift->_get_instance; + my $cache_name = $self->_cache_name(qw(compile perlapi)); + + $self->check_cached($cache_name, "whether perlapi is accessible", sub { $self->_check_compile_perlapi }); +} + +=head2 check_compile_perlapi_or_die + +Dies when not being able to compile using the Perl API + +=cut + +sub check_compile_perlapi_or_die +{ + my $self = shift; + $self->check_compile_perlapi(@_) or $self->msg_error("Cannot use Perl API - giving up"); +} + +=head2 check_linkable_xs_so + +Checks whether a dynamic loadable object containing an XS module can be +linked or not. Due the nature of the beast, this test currently always +succeed. + +=cut + +sub check_linkable_xs_so { 1 } + +=head2 check_linkable_xs_so_or_die + +Dies when L fails. + +=cut + +sub check_linkable_xs_so_or_die +{ + my $self = shift; + $self->check_linkable_xs_so(@_) or $self->msg_error("Cannot link XS dynamic loadable - giving up"); +} + +=head2 check_loadable_xs_so + +Checks whether a dynamic loadable object containing an XS module can be +loaded or not. Due the nature of the beast, this test currently always +succeed. + +=cut + +sub check_loadable_xs_so { 1 } + +=head2 check_loadable_xs_so_or_die + +Dies when L fails. + +=cut + +sub check_loadable_xs_so_or_die +{ + my $self = shift; + $self->check_loadable_xs_so(@_) or $self->msg_error("Cannot load XS dynamic loadable - giving up"); +} + +=head2 _check_link_perlapi + +This method can be used from other checks to prove whether we have a perl +development environment including a suitable libperl or not (perl.h, +reasonable basic checks - types, etc.) + +Caller must ensure that the linker flags are set appropriate (C<-lperl> +or similar). + +=cut + +sub _check_link_perlapi +{ + my $self = shift; + + my $conftest = $self->_check_perlapi_program(); + my @save_libs = @{$self->{extra_libs}}; + my @save_extra_link_flags = @{$self->{extra_link_flags}}; + + my $libperl = $Config{libperl}; + $libperl =~ s/^lib//; + $libperl =~ s/\.[^\.]*$//; + + push @{$self->{extra_link_flags}}, "-L" . File::Spec->catdir($Config{installarchlib}, "CORE"); + push @{$self->{extra_libs}}, "$libperl"; + if ($Config{perllibs}) + { + foreach my $perllib (split(" ", $Config{perllibs})) + { + $perllib =~ m/^\-l(\w+)$/ and push @{$self->{extra_libs}}, "$1" and next; + push @{$self->{extra_link_flags}}, $perllib; + } + } + + my $have_libperl = $self->link_if_else($conftest); + + $have_libperl or $self->{extra_libs} = [@save_libs]; + $have_libperl or $self->{extra_link_flags} = [@save_extra_link_flags]; + + $have_libperl; +} + +=head2 check_link_perlapi + +This method can be used from other checks to prove whether we have a perl +development environment or not (perl.h, libperl.la, reasonable basic +checks - types, etc.) + +=cut + +sub check_link_perlapi +{ + my $self = shift->_get_instance; + my $cache_name = $self->_cache_name(qw(link perlapi)); + + $self->check_cached($cache_name, "whether perlapi is linkable", sub { $self->_check_link_perlapi }); +} + +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_lib( lib, func, @other-libs?, \%options? ) + +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. + +In case of function found, the HAVE_LIBlibrary (all in capitals) +preprocessor macro is defined with 1 and $lib together with @other_libs +are added to the list of libraries to link with. + +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. + +This method caches its result in the Clib_func variable. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +If any of I, I is defined, +both callbacks are passed to L as I or +I to C, respectively. + +It's recommended to use L instead of check_lib these days. + +=cut + +sub check_lib +{ + my $options = {}; + scalar @_ > 1 and ref $_[-1] eq "HASH" and $options = pop @_; + my $self = shift->_get_instance(); + my ($lib, $func, @other_libs) = @_; + + return 0 unless $lib and $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, + { + ($options->{action_on_true} ? (action_on_true => $options->{action_on_true}) : ()), + ($options->{action_on_false} ? (action_on_false => $options->{action_on_false}) : ()) + } + ); + $self->{extra_libs} = [@save_libs]; + + $have_lib; + }; + + $self->check_cached( + $cache_name, + "for $func in -l$lib", + $check_sub, + { + action_on_true => sub { + $self->define_var( + _have_lib_define_name($lib), + $self->cache_val($cache_name), + "defined when library $lib is available" + ); + push(@{$self->{extra_libs}}, $lib, @other_libs); + $options->{action_on_cache_true} + and ref $options->{action_on_cache_true} eq "CODE" + and $options->{action_on_cache_true}->(); + }, + action_on_false => sub { + $self->define_var(_have_lib_define_name($lib), undef, "defined when library $lib is available"); + $options->{action_on_cache_false} + and ref $options->{action_on_cache_false} eq "CODE" + and $options->{action_on_cache_false}->(); + }, + } + ); +} + +=head2 search_libs( function, search-libs, @other-libs?, \%options? ) + +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. + +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. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +If any of I, I is defined, +both callbacks are passed to L as I or +I to C, respectively. Given callbacks +for I or I are called for +each library checked using L receiving the library as +first argument and all C<@other_libs> subsequently. + +=cut + +sub search_libs +{ + my $options = {}; + scalar @_ > 1 and ref $_[-1] eq "HASH" and $options = pop @_; + my $self = shift->_get_instance(); + my ($func, $libs, @other_libs) = @_; + + (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, + { + ( + $options->{action_on_lib_true} && "CODE" eq ref $options->{action_on_lib_true} + ? (action_on_true => sub { $options->{action_on_lib_true}->($libstest, @other_libs, @_) }) + : () + ), + ( + $options->{action_on_lib_false} && "CODE" eq ref $options->{action_on_lib_false} + ? (action_on_false => sub { $options->{action_on_lib_false}->($libstest, @other_libs, @_) }) + : () + ), + } + ) + and ($have_lib = defined($libstest) ? $libstest : "none required") + and last; + } + $self->{extra_libs} = [@save_libs]; + + $have_lib + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$have_lib + and $options->{action_on_false}->(); + + $have_lib; + }; + + return $self->check_cached( + $cache_name, + "for library containing $func", + $check_sub, + { + action_on_true => sub { + $self->cache_val($cache_name) eq "none required" + or unshift(@{$self->{extra_libs}}, $self->cache_val($cache_name)); + + $options->{action_on_cache_true} + and ref $options->{action_on_cache_true} eq "CODE" + and $options->{action_on_cache_true}->(); + }, + ($options->{action_on_cache_false} ? (action_on_false => $options->{action_on_cache_false}) : ()) + } + ); +} + +sub _check_lm_funcs { qw(log2 pow log10 log exp sqrt) } + +=head2 check_lm( \%options? ) + +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. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +Each of existing key/value pairs using I (as +I having the name of the tested functions as first argument), +I (as I having the name of the tested +functions as first argument), I (as +I having the name of the tested functions as first +argument), I (as I having +the name of the tested functions as first argument) as key are passed- +through to each call of L. +Given callbacks for I, I, +I or I are passed to the +call of L. + +B that I and I or +I and I cannot be used +at the same time, respectively. + +=cut + +sub check_lm +{ + my $options = {}; + scalar @_ > 1 and ref $_[-1] eq "HASH" and $options = pop @_; + my $self = shift->_get_instance(); + + defined $options->{action_on_lib_true} + and defined $options->{action_on_func_lib_true} + and croak("action_on_lib_true and action_on_func_lib_true cannot be used together"); + defined $options->{action_on_lib_false} + and defined $options->{action_on_func_lib_false} + and croak("action_on_lib_false and action_on_func_lib_false cannot be used together"); + + my %pass_options; + defined $options->{action_on_cache_true} and $pass_options{action_on_cache_true} = $options->{action_on_cache_true}; + defined $options->{action_on_cache_false} and $pass_options{action_on_cache_false} = $options->{action_on_cache_false}; + defined $options->{action_on_lib_true} and $pass_options{action_on_lib_true} = $options->{action_on_lib_true}; + defined $options->{action_on_lib_false} and $pass_options{action_on_lib_false} = $options->{action_on_lib_false}; + + my $fail = 0; + my $required = ""; + my @math_funcs = $self->_check_lm_funcs; + for my $func (@math_funcs) + { + my $ans = $self->search_libs( + $func, + ['m'], + { + %pass_options, + ( + $options->{action_on_func_true} && "CODE" eq ref $options->{action_on_func_true} + ? (action_on_true => sub { $options->{action_on_func_true}->($func, @_) }) + : () + ), + ( + $options->{action_on_func_false} && "CODE" eq ref $options->{action_on_func_false} + ? (action_on_false => sub { $options->{action_on_func_false}->($func, @_) }) + : () + ), + ( + $options->{action_on_func_lib_true} && "CODE" eq ref $options->{action_on_func_lib_true} + ? (action_on_lib_true => sub { $options->{action_on_func_lib_true}->($func, @_) }) + : () + ), + ( + $options->{action_on_func_lib_false} && "CODE" eq ref $options->{action_on_func_lib_false} + ? (action_on_lib_false => sub { $options->{action_on_func_lib_false}->($func, @_) }) + : () + ), + }, + ); + + $ans or $fail = 1; + $ans ne "none required" and $required = $ans; + } + + !$fail + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $fail + and $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and $options->{action_on_false}->(); + + $required; +} + +=head2 pkg_config_package_flags($package, \%options?) + +Search for pkg-config flags for package as specified. The flags which are +extracted are C<--cflags> and C<--libs>. The extracted flags are appended +to the global C and C, respectively. + +Call it with the package you're looking for and optional callback whether +found or not. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. +If any of I, I is defined, +both callbacks are passed to L as I or +I to L, respectively. + +=cut + +my $_pkg_config_prog; + +sub _pkg_config_flag +{ + defined $_pkg_config_prog or croak("pkg_config_prog required"); + my @pkg_config_args = @_; + my ($stdout, $stderr, $exit) = + capture { system($_pkg_config_prog, @pkg_config_args); }; + chomp $stdout; + 0 == $exit and return $stdout; + return; +} + +sub pkg_config_package_flags +{ + my $options = {}; + scalar @_ > 1 and ref $_[-1] eq "HASH" and $options = pop @_; + my ($self, $package) = @_; + $self = $self->_get_instance(); + + (my $pkgpfx = $package) =~ s/^(\w+).*?$/$1/; + my $cache_name = $self->_cache_name("pkg", $pkgpfx); + + defined $_pkg_config_prog or $_pkg_config_prog = $self->check_prog_pkg_config; + my $check_sub = sub { + my (@pkg_cflags, @pkg_libs); + + (my $ENV_CFLAGS = $package) =~ s/^(\w+).*?$/$1_CFLAGS/; + my $CFLAGS = + defined $ENV{$ENV_CFLAGS} + ? $ENV{$ENV_CFLAGS} + : _pkg_config_flag($package, "--cflags"); + $CFLAGS and @pkg_cflags = ( + map { $_ =~ s/^\s+//; $_ =~ s/\s+$//; Text::ParseWords::shellwords $_; } + split(m/\n/, $CFLAGS) + ) and push @{$self->{extra_preprocess_flags}}, @pkg_cflags; + + (my $ENV_LIBS = $package) =~ s/^(\w+).*?$/$1_LIBS/; + # do not separate between libs and extra (for now) - they come with -l prepended + my $LIBS = + defined $ENV{$ENV_LIBS} + ? $ENV{$ENV_LIBS} + : _pkg_config_flag($package, "--libs"); + $LIBS and @pkg_libs = ( + map { $_ =~ s/^\s+//; $_ =~ s/\s+$//; Text::ParseWords::shellwords $_; } + split(m/\n/, $LIBS) + ) and push @{$self->{extra_link_flags}}, @pkg_libs; + + my $pkg_config_flags = join(" ", @pkg_cflags, @pkg_libs); + + $pkg_config_flags + and $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + $options->{action_on_false} + and ref $options->{action_on_false} eq "CODE" + and !$pkg_config_flags + and $options->{action_on_false}->(); + + $pkg_config_flags; + }; + + $self->check_cached( + $cache_name, + "for pkg-config package of $package", + $check_sub, + { + ($options->{action_on_cache_true} ? (action_on_true => $options->{action_on_cache_true}) : ()), + ($options->{action_on_cache_false} ? (action_on_false => $options->{action_on_cache_false}) : ()) + } + ); +} + +=head2 _check_mm_pureperl_build_wanted + +This method proves the C<_argv> attribute and (when set) the C +whether they contain I or not. The attribute C<_force_xs> +is set as appropriate, which allows a compile test to bail out when C +is called with I. + +=cut + +sub _check_mm_pureperl_build_wanted +{ + my $self = shift->_get_instance; + + defined $ENV{PERL_MM_OPT} and my @env_args = split " ", $ENV{PERL_MM_OPT}; + + foreach my $arg (@{$self->{_argv}}, @env_args) + { + $arg =~ m/^PUREPERL_ONLY=(.*)$/ and return int($1); + } + + 0; +} + +=head2 _check_mb_pureperl_build_wanted + +This method proves the C<_argv> attribute and (when set) the C +whether they contain I<--pureperl-only> or not. + +=cut + +sub _check_mb_pureperl_build_wanted +{ + my $self = shift->_get_instance; + + defined $ENV{PERL_MB_OPT} and my @env_args = split " ", $ENV{PERL_MB_OPT}; + + foreach my $arg (@{$self->{_argv}}, @env_args) + { + $arg eq "--pureperl-only" and return 1; + } + + 0; +} + +=head2 _check_pureperl_required + +This method calls C<_check_mm_pureperl_build_wanted> when running under +L (C) or C<_check_mb_pureperl_build_wanted> +when running under a C (L compatible) environment. + +When neither is found (C<$0> contains neither C nor C), +simply 0 is returned. + +=cut + +sub _check_pureperl_required +{ + my $self = shift; + $0 =~ m/Makefile\.PL$/i and return $self->_check_mm_pureperl_build_wanted(@_); + $0 =~ m/Build\.PL$/i and return $self->_check_mb_pureperl_build_wanted(@_); + + 0; +} + +=head2 check_pureperl_required + +This check method proves whether a pure perl build is wanted or not by +cached-checking C<< $self->_check_pureperl_required >>. + +=cut + +sub check_pureperl_required +{ + my $self = shift->_get_instance; + my $cache_name = $self->_cache_name(qw(pureperl required)); + $self->check_cached($cache_name, "whether pureperl is required", sub { $self->_check_pureperl_required }); +} + +=head2 check_produce_xs_build + +This routine checks whether XS can be produced. Therefore it does +following checks in given order: + +=over 4 + +=item * + +check pure perl environment variables (L) or +command line arguments and return false when pure perl is requested + +=item * + +check whether a compiler is available (L) and +return false if none found + +=item * + +check whether a test program accessing Perl API can be compiled and +die with error if not + +=back + +When all checks passed successfully, return a true value. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. + +=cut + +sub check_produce_xs_build +{ + my $options = {}; + scalar @_ > 1 and ref $_[-1] eq "HASH" and $options = pop @_; + my $self = shift->_get_instance; + $self->check_pureperl_required() and return _on_return_callback_helper(0, $options, "action_on_false"); + eval { $self->check_valid_compilers($_[0] || [qw(C)]) } + or return _on_return_callback_helper(0, $options, "action_on_false"); + # XXX necessary check for $Config{useshrlib}? (need to dicuss with eg. TuX, 99% likely return 0) + $self->check_compile_perlapi_or_die(); + + $options->{action_on_true} + and ref $options->{action_on_true} eq "CODE" + and $options->{action_on_true}->(); + + return 1; +} + +=head2 check_produce_loadable_xs_build + +This routine proves whether XS should be built and it's possible to create +a dynamic linked object which can be loaded using Perl's Dynaloader. + +The extension over L can be avoided by adding the +C to C<$ENV{PERL5_AC_OPTS}>. + +If the very last parameter contains a hash reference, C references +to I or I are executed, respectively. + +=cut + +sub check_produce_loadable_xs_build +{ + my $self = shift->_get_instance; + $self->check_produce_xs_build(@_) + and !$self->{c_ac_flags}->{notest_loadable_xs} + and $self->check_linkable_xs_so_or_die + and $self->check_loadable_xs_so_or_die; +} + +# +# +# Auxiliary funcs +# + +=head2 _set_argv + +Intended to act as a helper for evaluating given command line arguments. +Stores given arguments in instances C<_argv> attribute. + +Call once at very begin of C or C: + + Your::Pkg::Config::AutoConf->_set_args(@ARGV); + +=cut + +sub _set_argv +{ + my ($self, @argv) = @_; + $self = $self->_get_instance; + $self->{_argv} = \@argv; + return; +} + +sub _sanitize +{ + # This is hard coded, and maybe a little stupid... + my $x = shift; + $x =~ s/ //g; + $x =~ s/\///g; + $x =~ s/\\//g; + $x; +} + +sub _get_instance +{ + ref $_[0] and return $_[0]; + defined $glob_instance or $glob_instance = $_[0]->new(); + $glob_instance; +} + +sub _get_builder +{ + my $self = $_[0]->_get_instance(); + + ref $self->{lang_supported}->{$self->{lang}} eq "CODE" and $self->{lang_supported}->{$self->{lang}}->($self); + defined($self->{lang_supported}->{$self->{lang}}) or croak("Unsupported compile language \"" . $self->{lang} . "\""); + + $self->{lang_supported}->{$self->{lang}}->new(); +} + +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; + + ref $self->{lang_supported}->{$lang} eq "CODE" and $self->{lang_supported}->{$lang}->($self); + 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 _on_return_callback_helper +{ + my $callback = pop @_; + my $options = pop @_; + $options->{$callback} + and ref $options->{$callback} eq "CODE" + and $options->{$callback}->(); + @_ and wantarray and return @_; + 1 == scalar @_ and return $_[0]; + 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"; + + $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 + +my $_default_includes = <<"_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 + +sub _default_includes { $_default_includes } + +sub _default_main { $_[0]->_build_main("") } + +my $_main_tpl = <<"_ACEOF"; + int + main () + { + %s; + return 0; + } +_ACEOF + +sub _build_main +{ + my $self = shift->_get_instance(); + my $body = shift || ""; + sprintf($_main_tpl, $body); +} + +=head2 _default_includes_with_perl + +returns a string containing default includes for program prologue containing +I<_default_includes> plus + + #include + #include + +=cut + +my $_include_perl = <<"_ACEOF"; +#include +#include +#include /* for perl context in threaded perls */ +_ACEOF + +sub _default_includes_with_perl +{ + join("\n", $_[0]->_default_includes, $_include_perl); +} + +sub _cache_prefix { "ac" } + +sub _cache_name +{ + my ($self, @names) = @_; + my $cache_name = join("_", $self->_cache_prefix(), "cv", @names); + $cache_name =~ tr/_A-Za-z0-9/_/c; + $cache_name; +} + +sub _get_log_fh +{ + my $self = $_[0]->_get_instance(); + unless (defined($self->{logfh})) + { + my $open_mode = defined $self->{logfile_mode} ? $self->{logfile_mode} : ">"; + open(my $fh, $open_mode, $self->{logfile}) or croak "Could not open file $self->{logfile}: $!"; + $self->{logfh} = [$fh]; + } + + $self->{logfh}; +} + +sub _add_log_entry +{ + my ($self, @logentries) = @_; + ref($self) or $self = $self->_get_instance(); + $self->_get_log_fh(); + foreach my $logentry (@logentries) + { + foreach my $fh (@{$self->{logfh}}) + { + print {$fh} "$logentry"; + } + } + + return; +} + +sub _add_log_lines +{ + my ($self, @logentries) = @_; + ref($self) or $self = $self->_get_instance(); + $self->_get_log_fh(); + my $logmsg = join("\n", @logentries) . "\n"; + foreach my $fh (@{$self->{logfh}}) + { + print {$fh} $logmsg; + } + + return; +} + +=head2 add_log_fh + +Push new file handles at end of log-handles to allow tee-ing log-output + +=cut + +sub add_log_fh +{ + my ($self, @newh) = @_; + $self->_get_log_fh(); + SKIP_DUP: + foreach my $fh (@newh) + { + foreach my $eh (@{$self->{logfh}}) + { + $fh == $eh and next SKIP_DUP; + } + push @{$self->{logfh}}, $fh; + } + return; +} + +=head2 delete_log_fh + +Removes specified log file handles. This method allows you to shoot +yourself in the foot - it doesn't prove whether the primary nor the last handle +is removed. Use with caution. + +=cut + +sub delete_log_fh +{ + my ($self, @xh) = @_; + $self->_get_log_fh(); + SKIP_DUP: + foreach my $fh (@xh) + { + foreach my $ih (0 .. $#{$self->{logfh}}) + { + $fh == $self->{logfh}->[$ih] or next; + splice @{$self->{logfh}}, $ih, 1; + last; + } + } + return; +} + +sub _cache_type_name +{ + my ($self, @names) = @_; + $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}}}; + join(" ", @ppflags, @cflags); +} + +sub _get_extra_linker_flags +{ + my $self = shift->_get_instance(); + my @libs = @{$self->{extra_libs}}; + my @lib_dirs = @{$self->{extra_lib_dirs}}; + my @ldflags = @{$self->{extra_link_flags}}; + join(" ", @ldflags, map('-L' . $self->_sanitize_prog($_), @lib_dirs), map("-l$_", @libs)); +} + +=head1 AUTHOR + +Alberto Simões, C<< >> + +Jens Rehsack, C<< >> + +=head1 NEXT STEPS + +Although a lot of work needs to be done, these are the next steps I +intend 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. We will +be notified, and then you'll automatically be notified of progress +on your bug as we make changes. + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc Config::AutoConf + +You can also look for information at: + +=over 4 + +=item * AnnoCPAN: Annotated CPAN documentation + +L + +=item * CPAN Ratings + +L + +=item * MetaCPAN + +L + +=item * Git Repository + +L + +=back + +=head1 ACKNOWLEDGEMENTS + +Michael Schwern for kind MacOS X help. + +Ken Williams for ExtUtils::CBuilder + +Peter Rabbitson for help on refactoring and making the API more Perl'ish + +=head1 COPYRIGHT & LICENSE + +Copyright 2004-2017 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 diff --git a/t/00.load.t b/t/00.load.t new file mode 100644 index 0000000..72c77cb --- /dev/null +++ b/t/00.load.t @@ -0,0 +1,8 @@ +# -*- cperl -*- + +use Test::More tests => 1; + +BEGIN +{ + use_ok('Config::AutoConf') or BAIL_OUT("Can't load Config::AutoConf"); +} diff --git a/t/01.checkprog.t b/t/01.checkprog.t new file mode 100644 index 0000000..e46b114 --- /dev/null +++ b/t/01.checkprog.t @@ -0,0 +1,118 @@ +# -*- cperl -*- + +use strict; +use warnings; + +use Test::More tests => 18; +use Config; +use Config::AutoConf; + +END { -e "config.log" and unlink "config.log"; } + +ok(Config::AutoConf->check_prog("perl"), "Find perl"); + +ok(!Config::AutoConf->check_prog("hopingnobodyhasthiscommand"), "Don't find ''hopingnobodyhasthiscommand"); + +like(Config::AutoConf->check_progs("___perl___", "__perl__", "_perl_", "perl"), qr/perl(?:\.exe)?$/i, "Find perl only"); +is(Config::AutoConf->check_progs("___perl___", "__perl__", "_perl_"), undef, "Find no _xn surrounded perl"); + +SCOPE: +{ + my $ac = Config::AutoConf->new(); # avoid cache influences tests below + local $ENV{AWK} = "/somewhere/over/the/rainbow"; + my $awk = $ac->check_prog_awk; + is($awk, $ENV{AWK}, "\$ENV{AWK} honored"); + + local $ENV{SED} = "/somewhere/over/the/rainbow"; + my $sed = $ac->check_prog_sed; + is($sed, $ENV{SED}, "\$ENV{SED} honored"); + + local $ENV{EGREP} = "/somewhere/over/the/rainbow"; + my $egrep = $ac->check_prog_egrep; + is($egrep, $ENV{EGREP}, "\$ENV{EGREP} honored"); + + local $ENV{YACC} = "/somewhere/over/the/rainbow"; + my $yacc = $ac->check_prog_yacc; + is($yacc, $ENV{YACC}, "\$ENV{YACC} honored"); +} + +SCOPE: +{ + my $ac = Config::AutoConf->new(); # avoid cache influences tests below + local $ENV{ac_cv_prog_AWK} = "/somewhere/over/the/rainbow"; + my $awk = $ac->check_prog_awk; + is($awk, $ENV{ac_cv_prog_AWK}, "\$ENV{ac_cv_prog_AWK} honored"); + + local $ENV{ac_cv_prog_SED} = "/somewhere/over/the/rainbow"; + my $sed = $ac->check_prog_sed; + is($sed, $ENV{ac_cv_prog_SED}, "\$ENV{ac_cv_prog_SED} honored"); + + local $ENV{ac_cv_prog_EGREP} = "/somewhere/over/the/rainbow"; + my $egrep = $ac->check_prog_egrep; + is($egrep, $ENV{ac_cv_prog_EGREP}, "\$ENV{ac_cv_prog_EGREP} honored"); + + local $ENV{ac_cv_prog_YACC} = "/somewhere/over/the/rainbow"; + my $yacc = $ac->check_prog_yacc; + is($yacc, $ENV{ac_cv_prog_YACC}, "\$ENV{ac_cv_prog_YACC} honored"); +} + +diag("Check for some progs to get an overview about world outside"); + +sub _is_x +{ + $^O =~ m/MSWin32/i and return $_[0] =~ m/\.(?:exe|com|bat|cmd)$/; + return -x $_[0]; +} + +SKIP: +{ + my $awk = Config::AutoConf->check_prog_awk; + $awk or skip "No awk", 1; + my $awk_bin = (map { $_ =~ s/^\s+//; $_ =~ s/\s+$//; $_ } Text::ParseWords::shellwords $awk )[0]; + ok(_is_x($awk_bin), "$awk_bin is executable"); + diag("Found AWK as $awk"); +} + +SKIP: +{ + my $sed = Config::AutoConf->check_prog_sed; + $sed or skip "No sed", 1; + my $sed_bin = (map { $_ =~ s/^\s+//; $_ =~ s/\s+$//; $_ } Text::ParseWords::shellwords $sed )[0]; + ok(_is_x($sed_bin), "$sed_bin is executable"); + diag("Found SED as $sed"); +} + +SKIP: +{ + my $grep = Config::AutoConf->check_prog_egrep; + $grep or skip "No egrep", 1; + my $grep_bin = (map { $_ =~ s/^\s+//; $_ =~ s/\s+$//; $_ } Text::ParseWords::shellwords $grep )[0]; + ok(_is_x($grep_bin), "$grep_bin is executable"); + diag("Found EGREP as $grep"); +} + +SKIP: +{ + my $yacc = Config::AutoConf->check_prog_yacc; + $yacc or skip "No yacc", 1; + my $yacc_bin = (map { $_ =~ s/^\s+//; $_ =~ s/\s+$//; $_ } Text::ParseWords::shellwords $yacc )[0]; + ok(_is_x($yacc_bin), "$yacc is executable"); + diag("Found YACC as $yacc"); +} + +SKIP: +{ + my $lex = Config::AutoConf->check_prog_lex; + $lex or skip "No lex", 1; + my $lex_bin = (map { $_ =~ s/^\s+//; $_ =~ s/\s+$//; $_ } Text::ParseWords::shellwords $lex )[0]; + ok(_is_x($lex_bin), "$lex is executable"); + diag("Found LEX as $lex"); +} + +SKIP: +{ + my $pkg_config = Config::AutoConf->check_prog_pkg_config; + $pkg_config or skip "No pkg-config", 1; + ok(_is_x($pkg_config), "$pkg_config is executable"); + diag("Found PKG-CONFIG as $pkg_config"); +} diff --git a/t/02.compile.t b/t/02.compile.t new file mode 100644 index 0000000..7cc05f7 --- /dev/null +++ b/t/02.compile.t @@ -0,0 +1,184 @@ +# -*- cperl -*- + +use strict; +use warnings; + +use Test::More; + +use Config::AutoConf; + +END +{ + foreach my $f () + { + -e $f and unlink $f; + } +} + +## OK, we really hope people have sdtio.h around +ok(Config::AutoConf->check_header("stdio.h")) or plan skip_all => "No working compile environment"; +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", {prologue => $include_perl}), "PERL_VERSION_STRING declared"; + + ok $ac->check_decls( + [qw(PERL_API_REVISION PERL_API_VERSION PERL_API_SUBVERSION)], + {prologue => $ac->_default_includes_with_perl} + ), + "PERL_API_* declared"; +} + +ok $ac->check_decl("perl_parse(PerlInterpreter *, XSINIT_t , int , char** , char** )", {prologue => $include_perl}), + "perl_parse() declared"; + +SCOPE: +{ + # test outside cache control + local $ENV{ac_cv_type_complete_useless_datatype} = 1; + ok $ac->check_type("complete_useless_datatype"), "External overwritten type test"; +} + +# check declared types +ok $ac->check_type("I32", {prologue => $include_perl}), "I32 is valid type"; + +ok $ac->check_types(["SV *", "AV *", "HV *"], {prologue => $include_perl}), "[SAH]V * are valid types"; + +# check size of perl types +my $typesize = $ac->check_sizeof_type("I32", {prologue => $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"], {prologue => $include_perl}), + "Could determined sizes for I32, SV *, AV, HV *, SV.sv_refcnt"; + +my $compute = $ac->compute_int("-sizeof(I32)", {prologue => $include_perl}); +cmp_ok($compute, "==", 0 - $typesize, "Compute (-sizeof(I32))"); + +# check perl data structure members +ok $ac->check_member("struct av.sv_any", {prologue => $include_perl}), "have struct av.sv_any member"; + +ok $ac->check_members(["struct hv.sv_any", "struct STRUCT_SV.sv_any"], {prologue => $include_perl}), + "have struct hv.sv_any and struct STRUCT_SV.sv_any members"; + +my $struct_in_struct_prlg = <check_member("struct S2.s1", {prologue => $struct_in_struct_prlg}), "have struct S2.s1 member"; + +# check aligning +ok $ac->check_alignof_type("I32", {prologue => $include_perl}), "Align of I32"; +ok $ac->check_alignof_type("SV.sv_refcnt", {prologue => $include_perl}), "Align of SV.sv_refcnt"; +ok $ac->check_alignof_types(["I32", "U32", "AV", "HV *", "SV.sv_refcnt"], {prologue => $include_perl}), + "Could determine the sizes of I32, U32, AV, HV *, SV.sv_refcnt"; + +# +# Let's take REGEXP structure members as of perlreapi to test check_members +# +my @members = + qw/jdd jdd2 engine mother_re extflags minlen minlenret gofs substrs nparens intflags pprivate lastparen lastcloseparen swap offs subbeg saved_copy sublen suboffset subcoffset prelen precomp wrapped wraplen seen_evals paren_names refcnt/; + +ok( + $ac->check_members( + [map { "struct regexp.$_" } @members], + { + prologue => "#include \"EXTERN.h\" +#include \"perl.h\" +#include \"XSUB.h\"" + } + ), + "Check struct regexp" +); + +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); + +if ($] < 5.008) +{ + require IO::String; + $fh = IO::String->new($dbuf); +} +else +{ + open($fh, "+>", \$dbuf); +} +$ac->write_config_h($fh); +close($fh); +$fh = undef; + +cmp_ok($dbuf, "eq", $fbuf, "file and direct write computes equal"); + +like($dbuf, qr/COMPLETE_USELESS_DATATYPE/, "complete_useless_datatype in config.h even if injected"); + +TODO: +{ + -f "META.yml" or $ENV{AUTOMATED_TESTING} = 1; + local $TODO = "Quick fix: TODO - analyse diag later" unless $ENV{AUTOMATED_TESTING}; + my @old_logfh; + $dbuf = ""; + + if ($] < 5.008) + { + $fh = IO::String->new($dbuf); + } + else + { + open($fh, "+>", \$dbuf); + } + @old_logfh = @{$ac->{logfh}}; + $ac->add_log_fh($fh); + cmp_ok(scalar @{$ac->{logfh}}, "==", 2, "Successfully added 2nd loghandle"); + + ok($ac->check_compile_perlapi(), "Could compile perl extensions") or diag($dbuf); + scalar @old_logfh and $ac->delete_log_fh($fh); + scalar @old_logfh and is_deeply(\@old_logfh, $ac->{logfh}, "add_log_fh/delete_log_fh"); + defined $fh and close($fh); + $fh = undef; +} + +SCOPE: +{ + local $ENV{ac_cv_insane_h} = "/usr/include/insane.h"; + my $insane_h = $ac->check_header("insane.h"); + is($insane_h, $ENV{ac_cv_insane_h}, "Cache override for header files work"); +} + +done_testing; diff --git a/t/03.link.t b/t/03.link.t new file mode 100644 index 0000000..286ee0b --- /dev/null +++ b/t/03.link.t @@ -0,0 +1,115 @@ +# -*- cperl -*- + +use strict; +use warnings; + +use Test::More; +use Config::AutoConf; + +END +{ + foreach my $f () + { + -e $f and unlink $f; + } +} + +my $ac_1; + +ok($ac_1 = Config::AutoConf->new(logfile => "config3.log"), "Instantiating Config::AutoConf for check_lib() tests"); +ok($ac_1->check_header("stdio.h")) or plan skip_all => "No working compile environment"; + +ok($ac_1->check_func("printf"), "Every system should have a printf"); +my $set_me; +$ac_1->check_func( + "scanf", + { + action_on_true => sub { $set_me = 1 }, + action_on_false => sub { $set_me = 0 } + } +); +ok(defined $set_me, "Having scanf or not, but now we know"); +ok($ac_1->check_funcs([qw(sprintf sscanf)]), "Every system should have sprintf and sscanf"); + +TODO: +{ + local $TODO = "It seems some Windows machine doesn't have -lm" if $^O eq "MSWin32"; + + ## OK, we really hope people have -lm around + ok(!$ac_1->check_lib("m", "foobar"), "foobar() not in -lm"); + ok($ac_1->check_lib("m", "atan"), "atan() in -lm"); + + my ($where_atan, $ac_2); + ok($ac_2 = Config::AutoConf->new(logfile => "config4.log"), "Instantiating Config::AutoConf for search_libs() tests"); + 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)"); +} + +TODO: +{ + local $TODO = "__builtin_\$1 isn't supported overall - sane prove would need compiler detection"; + + ok($ac_1->check_builtin("expect"), "__buitin_expect available"); +} + +my ($ac_3, %math_funcs); +ok($ac_3 = Config::AutoConf->new(logfile => "config4_2.log"), "Instantiating Config::AutoConf for check_lm() tests"); +$ac_3->check_lm( + { + action_on_func_lib_true => sub { my ($func, $lib, @extra) = @_; $math_funcs{$func} = $lib }, + action_on_func_lib_false => sub { my ($func, $lib, @extra) = @_; $math_funcs{$func} = 0 }, + } +); +is_deeply( + [sort keys %math_funcs], + [sort $ac_3->_check_lm_funcs], + "Math functions (" . join(", ", $ac_3->_check_lm_funcs) . ") tested for -lm" +); + +eval { + $ac_3->check_lm( + { + action_on_lib_true => sub { }, + action_on_func_lib_true => sub { }, + } + ); +}; +ok($@, "action_on_lib_true and action_on_func_lib_true cannot be used together"); + +eval { + $ac_3->check_lm( + { + action_on_lib_false => sub { }, + action_on_func_lib_false => sub { }, + } + ); +}; +ok($@, "action_on_lib_false and action_on_func_lib_false cannot be used together"); + +TODO: +{ + -f "META.yml" or $ENV{AUTOMATED_TESTING} = 1; + local $TODO = "Quick fix: TODO - analyse diag later" unless $ENV{AUTOMATED_TESTING}; + my ($fh, $fbuf, $dbuf, @old_logfh); + $dbuf = ""; + + if ($] < 5.008) + { + require IO::String; + $fh = IO::String->new($dbuf); + } + else + { + open($fh, "+>", \$dbuf); + } + @old_logfh = @{$ac_1->{logfh}}; + $ac_1->add_log_fh($fh); + cmp_ok(scalar @{$ac_1->{logfh}}, "==", 2, "Successfully added 2nd loghandle"); + ok($ac_1->check_link_perlapi(), "Could link perl extensions") or diag($dbuf); + scalar @old_logfh and $ac_1->delete_log_fh($fh); + scalar @old_logfh and is_deeply(\@old_logfh, $ac_1->{logfh}, "add_log_fh/delete_log_fh"); + defined $fh and close($fh); + $fh = undef; +} + +done_testing; diff --git a/t/testdata/foo.pc b/t/testdata/foo.pc new file mode 100644 index 0000000..b57c14a --- /dev/null +++ b/t/testdata/foo.pc @@ -0,0 +1,11 @@ +# $Id$ +prefix=/base/path +exec_prefix=/base/path +libdir=${exec_prefix}/lib/foo +includedir=${prefix}/include/foo-0 + +Name: foo +Description: Provides some testable flags for Config::AutoConf +Version: 0.23 +Libs: -L${libdir} -lfoo +Cflags: -I${includedir}