crossroads

Git mirror of https://crossroads.e-tunity.com/
git clone git://git.finwo.net/app/crossroads
Log | Files | Refs | LICENSE

c-conf (19232B)


      1 #!/usr/bin/env perl
      2 
      3 use strict;
      4 use Getopt::Std;
      5 
      6 # Globals
      7 my $VER = "1.18";
      8 # 1.18 [KK 2013-04-05] Added /usr/lib/arm-linux-gnueabihf for Raspberry Pi
      9 # 1.17 [KK 2013-03-15] /lib/x86_64-linux-gnu added for Ubuntu
     10 # 1.16 [KK 2011-10-10] /usr/lib/x86_64-linux-gnu added to the libdirs for
     11 #                      Ubuntu 11 64-bits.
     12 # 1.15 [KK 2008-10-12] Option "optflags" implemented.
     13 # 1.14 [KK 2008-08-22] c-compiler and c++-compiler attempt to find by
     14 #		       version, eg. '/opt/local/bin/g++-mp-4.2' is better
     15 #		       than '/usr/bin/g++'
     16 # 1.13 [KK 2008-07-15] Opimized subfiles() - way faster when nonrecursive now
     17 # 1.12 [KK 2008-04-15] Messaging improved upon -v flag
     18 # 1.11 [KK 2008-01-14] Added /opt/local/{lib,include} to the standard libs.
     19 #		       Also added /sw
     20 # 1.10 [KK 2007-08-29] Added libvariable01 and flag -l. Flags -l/L get
     21 #		       used upon libfunction/libvariable checks.
     22 # 1.09 [KK 2007-06-13] Added 'lib64' variants to libdirs, for 64bit Linux
     23 # 1.08 [KK 2007-05-22] -L{dir} shown only once for identical dirs during 'lib'
     24 # 1.07 [KK 2007-05-18] Flag -c for caching implemented
     25 # 1.06 [KK 2007-04-27] Added ifheader01 and libfunction01
     26 # 1.05 [KK 2006-09-28] Flag -s (silent) implemented. Usage text updated.
     27 # 1.04 [KK 2006-09-05] C-compilers: gcc/g++ get selected first, instead of
     28 #			cc/c++. Helps HP-UX ports. [Thanks, Bernd Krumboeck.]
     29 # 1.03 [KK 2006-07-19] 'subfiles' keeps track of visited dirs incase of
     30 #		       recursion. Testing is now by inode, used to be by name.
     31 # 1.02 [KK 2006-06-01] 'findbin' searches for .exe too now, for Cygwin support
     32 # 1.01 [KK 2005-09-29] Implemented context-sensitive help via -h.
     33 #		       Action 'header' implemented.
     34 # 1.00 [KK 2005-09-28] First version
     35 
     36 # Configuration
     37 my @def_headerdirs = ('/usr/include',
     38 		      '/usr/local/include',
     39 		      '/opt/local/include',
     40 		      '/sw/include',
     41 		      "$ENV{HOME}/include",
     42 		     );
     43 my @def_libdirs = ('/usr/lib',
     44 		   '/usr/lib64',
     45 		   '/lib/x86_64-linux-gnu',
     46 		   '/usr/lib/x86_64-linux-gnu',
     47 		   '/usr/lib/arm-linux-gnueabihf',
     48 		   '/usr/local/lib',		   
     49 		   '/usr/local/lib64',
     50 		   '/opt/local/lib',
     51 		   '/opt/local/lib64',
     52 		   '/usr/ucblib',
     53 		   '/sw/lib',
     54 		   '/sw/lib64',
     55 		   "$ENV{HOME}/lib",
     56 		  );
     57 my @c_compilers = ('gcc', 'cc');
     58 my @cpp_compilers = ('g++', 'c++');
     59 
     60 # Globals
     61 my %opts;
     62 my $base;
     63 my @warnings;
     64 my $printed;
     65 my @headerdirs;
     66 my @libdirs;
     67 my @libs;
     68 my $cachekey;
     69 my $cacheval;
     70 
     71 # Show usage and croak
     72 sub usage {
     73     die <<"ENDUSAGE"
     74 
     75 This is c-conf, the C compilation configuration helper V$VER
     76 Copyright (c) e-tunity. Contact <info\@e-tunity.com> for information.
     77 
     78 Usage:
     79     $base [flags] header FILE.H [FILE.H...] Searches for directories
     80 	containing the named header(s), returns appropriate -I flags.
     81     $base [flags] headerdir DIR [DIR...]: Searches for directory
     82 	containing headers, returns appropriate -I flags.
     83     $base [flags] ifheader FILE.H DEFINE Searches for the named header.
     84 	If found, a compilation flag -DDEFINE is returned, indicating that
     85 	the header is found.
     86     $base [flags] ifheader01 FILE.H DEFINE Similar to ifheader, but the
     87         returned define is either DEFINE=0 or DEFINE=1
     88     $base [flags] lib NAME [NAME...]: Searches for libNAME.{a,so,...},
     89 	returns appropriate -L and -l flags.
     90     $base [flags] libfunction FUNC DEFINE Creates a small program that
     91 	tries to use FUNC. If this succeeds, a -DDEFINE=1 flag is returned.
     92     $base [flags] libfunction01 FUNC DEFINE Similar to libfunction, but
     93         the returned define is DEFINE=0 or DEFINE=1
     94     $base [flags] libvariable01 VAR DEFINE Creates a small program that
     95         accesses variable VAR. If this succeeds, -DDEFINE=1 is returned.
     96     $base [flags] so-name NAME: Returns filename of a shared-object for NAME,
     97         e.g. libNAME.so
     98     $base [flags] so-cflags: Returns compilation flags to build shared
     99         objects
    100     $base [flags] so-lflags: Returns linkage flags to produce a shared-object
    101 	library
    102     $base [flags] c-compiler: Returns name of C compiler
    103     $base [flags] c++-compiler: Returns name of C++ compiler
    104     $base [flags] optflags: Returns fast-code optimization flags.
    105 
    106 Optional flags:
    107     -c CACHE: settings will be dynamically determined unless present in
    108        CACHE; new settings will be added to CACHE
    109     -h: to show short help for an action, e.g. try '$base -h so-name'
    110     -s: to suppress showing of warnings
    111     -v: to show verbose messages
    112     -I DIR[,DIR..]: to add DIR(s) to the searchpath for headers, default
    113 	searchpath is @headerdirs
    114     -L DIR[,DIR..]: to add DIR(s) to the searchpath for libraries, default
    115 	searchpath is @libdirs
    116     -l LIB[,LIB..]: to add LIB(s) to C compiler invocations, when checking
    117         for lib functions or variables
    118 
    119 Meaningful output is returned on stdout. Verbose messages, warnings and
    120 errors go to stderr.
    121 
    122 ENDUSAGE
    123 }
    124 
    125 # Issue a warning
    126 sub warning {
    127     push (@warnings, "@_");
    128 }
    129 
    130 # Show a message
    131 sub msg {
    132     return unless ($opts{v});
    133     print STDERR ("$base: ", @_);
    134 }
    135 
    136 # Show help info if -h was given
    137 sub checkhelp {
    138     return unless ($opts{h});
    139     print STDERR (@_);
    140     exit (1);
    141 }
    142 
    143 # Basename / dirname of a file.
    144 sub basename ($) {
    145     my $name = shift;
    146     $name =~ s{.*/}{};
    147     return ($name);
    148 }
    149 sub dirname ($) {
    150     my $name = shift;
    151     return (undef) unless ($name =~ /\//);
    152     $name =~ s{/[^/]$}{};
    153     return ($name);
    154 }
    155 
    156 # Get the uname.
    157 sub uname() {
    158     my $ret = `uname`;
    159     chomp ($ret);
    160     return ($ret);
    161 }
    162 
    163 # Find a binary along the path.
    164 sub findbin($) {
    165     my $bin = shift;
    166     my $bestx = undef;
    167     my $bestver = -1;
    168     foreach my $d (split (/:/, $ENV{PATH})) {
    169 	my @cand = (glob("$d/$bin"), glob("$d/$bin.exe"),
    170 		    glob("$d/$bin-*"), glob("$d/$bin-*.exe"));
    171 	msg ("Candidates for '$bin' in '$d': [@cand]\n");
    172 	for my $x (@cand) {
    173 	    if (-x $x) {
    174 		my $ver = $x;
    175 		$ver =~ s{^.*/[^\d]*}{};
    176 		$ver = sprintf("%g", $ver);
    177 		msg ("Version of $x: $ver\n");
    178 		if ($bestver < $ver or !$bestx) {
    179 		    $bestver = $ver;
    180 		    $bestx = $x;
    181 		    msg ("  .. best so far\n");
    182 		}
    183 	    }
    184 	}
    185     }
    186     msg ("Failed to locate executable '$bin'!\n") unless ($bestx);
    187     return ($bestx);
    188 }
    189 
    190 # Recursively determine the files under a given dir.
    191 my %_dir_visited;
    192 sub subfiles ($$$) {
    193     my ($dir, $mask, $recursive) = @_;
    194 
    195     %_dir_visited = ();
    196     my ($dev, $ino) = stat($dir)
    197       or return (undef);
    198     my $tag = sprintf ("%d-%d", $dev, $ino);
    199     return (undef) if ($_dir_visited{$tag});
    200     $_dir_visited{$tag} = $dir;
    201     return (undef) unless (-d $dir);
    202 
    203     my @ret = ();
    204     foreach my $f (glob ("$dir/$mask")) {
    205 	push (@ret, $f) if (-f $f);
    206     }
    207 
    208     if ($recursive) {
    209 	foreach my $d (glob ("$dir/*")) {
    210 	    next unless (-d $d);
    211 	    my @subret = subfiles ("$d", $mask, 1);
    212 	    my $added = 0;
    213 	    foreach my $f (@subret) {
    214 		if (-f $f) {
    215 		    push (@ret, $f);
    216 		    $added++;
    217 		}
    218 	    }
    219 	}
    220     }
    221 
    222     if ($#ret > -1) {
    223 	return (@ret);
    224     } else {
    225 	return (undef);
    226     }
    227 }
    228 
    229 # Output stuff, update $cacheval incase we'll add it to the cache later.
    230 sub output {
    231     if ($printed++) {
    232 	print (' ');
    233 	$cacheval .= ' ';
    234     }
    235     print (@_);
    236     for my $a (@_) {
    237 	$cacheval .= $a;
    238     }
    239 }
    240 
    241 # Find a header, output a define if found.
    242 sub if_header {
    243     checkhelp <<"ENDHELP";
    244 'ifheader' tries to find a header file in the 'include' directories.
    245 When found, a define-flag for the C compiler is returned.
    246 E.g.: $base ifheader malloc.h HAVE_MALLOC_H (may return -DHAVE_MALLOC_H)
    247 Use in a Makefile as in:
    248 CFLAGS = \$(CFLAGS) \$(shell c-conf ifheader malloc.h HAVE_MALLOC_H)
    249 Then in a C source as:
    250 #ifdef HAVE_MALLOC_H
    251 #include <malloc.h>
    252 #endif
    253 ENDHELP
    254 
    255     usage() if ($#_ != 1);
    256 
    257     my ($h, $def) = @_;
    258 
    259     foreach my $d (@headerdirs) {
    260 	if (-f "$d/$h") {
    261 	    msg ("Header '$h' found as '$d/$h'\n");
    262 	    output ("-D$def");
    263 	    return;
    264 	}
    265     }
    266 }
    267 
    268 # Find a header, output define=0 or define=1
    269 sub if_header01 {
    270     checkhelp <<"ENDHELP";
    271 'ifheader01' tries to find a header in the 'include' directories. When
    272 found, a define for the C compiler is returned having value 1. When not
    273 found, the value is 0. Use in a Makefile as follows:
    274 CFLAGS = \$(shell c-conf ifheader01 malloc.h HAVE_MALLOC_H)
    275 Then in a C source as:
    276 #if HAVE_MALLOC_H == 1
    277 #include <malloc.h>
    278 #endif
    279 ENDHELP
    280 
    281     usage() if ($#_ != 1);
    282     my ($h, $def) = @_;
    283     foreach my $d (@headerdirs) {
    284 	if (-f "$d/$h") {
    285 	    output ("-D$def=1");
    286 	    return;
    287 	}
    288     }
    289     output ("-D$def=0");
    290     return;
    291 }
    292 
    293 # Find a header
    294 sub header {
    295     checkhelp <<"ENDHELP";
    296 'header' locates one or more C headers in the 'include' directories.
    297 E.g.: $base header e-lib.h stdio.h (may return -I/usr/include -I/usr/e/include)
    298 Use in a Makefile as in:
    299 CFLAGS = -C -Wall \$(shell c-conf header e-lib.h)
    300 Then in a C source as:
    301 #include <e-lib.h>
    302 ENDHELP
    303 
    304     usage() if ($#_ == -1);
    305     foreach my $h (@_) {
    306 	my $found = 0;
    307 	foreach my $d (@headerdirs) {
    308 	    if (-f "$d/$h") {
    309 		$found++;
    310 		msg ("Header '$h' found as '$d/$h\n");
    311 		output ("-I$d");
    312 		last;
    313 	    }
    314 	}
    315 	warning ("Failed to locate header '$h' in @headerdirs\n")
    316 	  unless ($found);
    317     }
    318 }
    319 
    320 # Find a header directory
    321 sub headerdir {
    322     checkhelp <<"ENDHELP";
    323 'headerdir' locates directories under which (in steps) C headers are
    324 E.g.: $base headerdir libxml2 (may return '-I/usr/include/libxml2')
    325 Use in a Makefile as in:
    326 CFLAGS = -C -Wall \$(shell c-conf headerdir libxml2)
    327 Then in a C source as:
    328 #include <libxml/xpath.h>
    329 ENDHELP
    330 
    331     usage() if ($#_ == -1);
    332     foreach my $headerdir (@_) {
    333 	my $found = 0;
    334 	foreach my $d (@headerdirs) {
    335 	    my $target = "$d/$headerdir";
    336 	    if (subfiles ($target, '*.h', 0)) {
    337 		msg ("Header directory '$headerdir' found as '$target'\n");
    338 		output ("-I$target");
    339 		$found++;
    340 	    }
    341 	}
    342 	warning ("Header dir '$headerdir' not found\n")
    343 	  unless ($found);
    344     }
    345 }
    346 
    347 # Find a library
    348 sub lib {
    349     checkhelp <<"ENDHELP";
    350 'lib' generates the linkage flags for a given library name. The name
    351 is bare, without 'lib' and '.so' and the like.
    352 E.g.: $base lib xml2 (may return '-L/usr/lib -lxml2')
    353 Use in a Makefile as in:
    354 LDFLAGS = \$(shell c-conf lib xml2)
    355 ENDHELP
    356 
    357     usage() if ($#_ == -1);
    358 
    359     my %dirshown;
    360     foreach my $lib (@_) {
    361 	my $found = 0;
    362 	foreach my $d (@libdirs) {
    363 	    my $hit = (subfiles ($d, "lib$lib.*", 0))[0];
    364 	    if ($hit) {
    365 		msg ("Library '$lib' found as '$hit'\n");
    366 		$found++;
    367 		$hit =~ s{/[^/]*$}{};
    368 		if (! $dirshown{$hit}) {
    369 		    output ("-L$hit");
    370 		    $dirshown{$hit} = 1;
    371 		}
    372 		output ("-l$lib");
    373 	    }
    374 	}
    375 	#warning ("Library '$lib' not found\n")
    376 	#  unless ($found);
    377     }
    378 }
    379 
    380 # Compilation flags to make a so-ready object.
    381 sub so_cflags {
    382     checkhelp <<"ENDHELP";
    383 'so-cflags' returns the compilation flags that are necessary when
    384 building objects for a shared library.
    385 E.g.: $base so-cflags (may return '-fPIC')
    386 Use in a Makefile as in:
    387 CFLAGS = -c -g -Wall \$(shell c-conf so-cflags)
    388 ENDHELP
    389 
    390     usage() if ($#_ > -1);
    391     my $flags;
    392     if (uname() eq 'Darwin') {
    393 	$flags = '-fPIC';
    394     } elsif (uname() eq 'Linux') {
    395 	$flags = '-fpic';
    396     }
    397     msg ("Shared object compilation flags: '$flags'\n");
    398     output ($flags);
    399 }
    400 
    401 # Linkage flags to make an so.
    402 sub so_lflags {
    403     checkhelp << "ENDHELP";
    404 'so-lflags' returns the linkage flags that are necessary when
    405 combining objects into a shared library.
    406 E.g.: $base so-lflags (may return '-dynamiclib -Wl,-single_module')
    407 Use in a Makefile as in:
    408 MY_SO = \$(shell c-conf so-name my)
    409 \$(MY_SO): *.o
    410 	\$(CC) -o \$(MY_SO) \$(shell c-conf so-lflags) *.o
    411 ENDHELP
    412 
    413     usage() if ($#_ > -1);
    414     my $lib = shift;
    415 
    416     my $flags;
    417     if (uname() eq 'Darwin') {
    418 	$flags = "-dynamiclib -Wl,-single_module";
    419     } else {
    420 	$flags = "-shared";
    421     }
    422     msg ("Shared library linkage flags: '$flags'\n");
    423     output ($flags);
    424 }
    425 
    426 # Find the C compiler and return it, or die trying.
    427 sub find_c_compiler {
    428     foreach my $c (@c_compilers) {
    429 	my $full = findbin($c);
    430 	return ($full) if ($full);
    431     }
    432     die ("No C compiler found\n");
    433 }
    434 
    435 # Get the C compiler
    436 sub c_compiler {
    437     checkhelp <<"ENDHELP";
    438 'c-compiler' tries to find a C compiler and returns its (bare) name.
    439 E.g.: $base c-compiler
    440       -> gcc
    441 ENDHELP
    442 
    443     usage() if ($#_ > -1);
    444     my $cc;
    445     eval { $cc = find_c_compiler(); };
    446     if ($@) {
    447 	warning ($@);
    448     } else {
    449 	msg ("C compiler: '$cc'\n");
    450 	output ($cc);
    451     }
    452 }
    453 
    454 # Get the C++ compiler
    455 sub cpp_compiler {
    456     checkhelp <<"ENDHELP";
    457 'c++-compiler' tries to find a C++ compiler and returns its (bare) name.
    458 E.g.: $base c++-compiler
    459       -> g++
    460 ENDHELP
    461 
    462     usage() if ($#_ > -1);
    463     foreach my $c (@cpp_compilers) {
    464 	my $full = findbin($c);
    465 	if ($full) {
    466 	    msg ("C++ compiler: '$full'\n");
    467 	    output ($full);
    468 	    return;
    469 	}
    470     }
    471     warning ("No C++ compiler found\n");
    472 }
    473 
    474 # Get fast code optimization flags.
    475 sub optflags {
    476     checkhelp <<"ENDHELP";
    477 'optflags' tries to determine optimization flags.
    478 E.g.: $base optflags
    479       -> -O3
    480 ENDHELP
    481     usage() if ($#_ > -1);
    482     for my $optflag ('-fast', '-O3', '-O2') {
    483 	if (test_compile ("int main() {}\n", $optflag)) {
    484 	    output ($optflag);
    485 	    return;
    486 	}
    487     }
    488     warning ("No optimization flag found.");
    489 }
    490 
    491 
    492 # Get the name for an SO.
    493 sub so_name {
    494     checkhelp <<"ENDHELP";
    495 'so-name' returns the filename of a shared library, based on the LIB
    496 argument.
    497 E.g.: $base so-name test
    498       -> libtest.so
    499 ENDHELP
    500 
    501     usage() if ($#_ != 0);
    502     my $name = shift;
    503 
    504     my $dir  = dirname ($name);
    505     my $base = basename ($name);
    506 
    507     my $dest;
    508     if (uname() eq 'Darwin') {
    509 	$dest = "lib$base.dylib";
    510     } else {
    511 	$dest = "lib$base.so";
    512     }
    513 
    514     if ($dir ne '') {
    515 	msg ("Shared library name for '$name': '$dir/$dest'\n");
    516 	output ("$dir/$dest");
    517     } else {
    518 	msg ("Shared library name for '$name': '$dest'\n");
    519 	output ("$dest");
    520     }
    521 }
    522 
    523 # Check that a libfunction is present.
    524 sub libfunction {
    525     checkhelp <<"ENDHELP";
    526 'libfunction' checks whether a library function is present. There are
    527 two arguments: the function to check, and a define to output when the
    528 function is found. The output is a -D flag for the compiler commandline.
    529 E.g.: $base libfunction printf HAVE_PRINTF
    530       -> -DHAVE_PRINTF=1
    531       $base libfunction foo_bar HAVE_FOOBAR
    532       -> (nothing)      
    533 ENDHELP
    534 
    535     if (test_libfunction (@_)) {
    536 	msg ("Library function '$_[0]' present\n");
    537 	output ("-D$_[1]=1");
    538     } else {
    539 	msg ("Library function '$_[0]' absent\n");
    540     }
    541 }
    542 
    543 # Check that a lib variable is present, 01 version
    544 sub libvariable01 {
    545     checkhelp <<"ENDHELP";
    546 'libvariable01' checks whether a library variable is present. There are
    547 two arguments: a variable name, and a define to output with value 0 or 1.
    548 E.g.: $base libvariable01 errno HAVE_ERRNO
    549       -> -DHAVE_ERRNO=1
    550 ENDHELP
    551 
    552     if (test_libvariable(@_)) {
    553 	msg ("Library variable '$_[1]' present\n");
    554 	output ("-D$_[1]=1");
    555     } else  {
    556 	msg ("Library variable '$_[1]' absent\n");
    557 	output ("-D$_[1]=0");
    558     }
    559 }
    560 
    561 # Check that a libfunction is present, 01-version
    562 sub libfunction01 {
    563     checkhelp <<"ENDHELP";
    564 'libfunction01' checks whether a library function is present. There are
    565 two arguments: the function to check, and a define to output when the
    566 function is found. When the lib function is found, then the define is
    567 returned with a value 1, else with a value 0.
    568 E.g.: $base libfunction01 printf HAVE_PRINTF
    569       -> -DHAVE_PRINTF=1
    570       $base libfunction foo_bar HAVE_FOOBAR
    571       -> -DHAVE_FOOBAR=0      
    572 ENDHELP
    573 
    574     if (test_libfunction (@_)) {
    575 	msg ("Library function '$_[1]' present\n");
    576 	output ("-D$_[1]=1");
    577     } else  {
    578 	msg ("Library function '$_[1]' absent\n");
    579 	output ("-D$_[1]=0");
    580     }
    581 }
    582 
    583 sub test_compile {
    584     my $sourcecode = shift;
    585     my $cc = find_c_compiler();
    586 
    587     # Create a temp .c file.
    588     my $src = "/tmp/$$.c";
    589     my $dst = "/tmp/$$.out";
    590     open (my $of, ">$src")
    591       or die ("Cannot write $src: $!\n");
    592     print $of ($sourcecode);
    593     close ($of);
    594 
    595     my $cmd = "$cc ";
    596     for my $flag (@_) {
    597 	$cmd .= "$flag ";
    598     }
    599     $cmd .= "$src -o $dst " .
    600       cc_inc_flags() . ' ' . cc_libdir_flags() . ' ' . cc_lib_flags();
    601     # print ($cmd, "\n");
    602     my $ret = system ("$cmd >/dev/null 2>&1");
    603     unlink ($src, $dst);
    604 
    605     return ($ret == 0 ? 1 : 0);
    606 }
    607 
    608 # Return @headerdirs as C flags
    609 sub cc_inc_flags() {
    610     my $ret = '';
    611     for my $h (@headerdirs) {
    612 	$ret .= " -I$h";
    613     }
    614     msg ("C compilation include flags: '$ret'\n");
    615     return ($ret);
    616 }
    617 
    618 # Return @libdirs as C flags
    619 sub cc_libdir_flags() {
    620     my $ret = '';
    621     for my $l (@libdirs) {
    622 	$ret .= " -L$l" if (-d $l);
    623     }
    624     msg ("C library directory flags: '$ret'\n");
    625     return ($ret);
    626 }
    627 
    628 # Return @libs as C flags
    629 sub cc_lib_flags() {
    630     my $ret = '';
    631     for my $l (@libs) {
    632 	$ret .= " -l$l";
    633     }
    634     msg ("C library flags: '$ret'\n");
    635     return ($ret);
    636 }
    637 
    638 # Test whether a lib function is present.
    639 sub test_libfunction {
    640 
    641     usage() if ($#_ != 1);
    642     my ($func, $def) = @_;
    643     return (test_compile ("main () {\n" .
    644 			  "    void $func (void);\n" .
    645 			  "    $func();\n" .
    646 			  "}\n"));
    647 }
    648 
    649 # Test whether a lib variable is present.
    650 sub test_libvariable {
    651 
    652     usage() if ($#_ != 1);
    653     my ($var, $def) = @_;
    654     return (test_compile ("main () {\n" .
    655 			  "    extern int $var;\n" .
    656 			  "    $var = 42;\n" .
    657 			  "}\n"));
    658 }
    659 
    660 # Main starts here
    661 
    662 $base = $0;
    663 $base =~ s{.*/}{};
    664 usage () unless (getopts ('vhI:L:sc:l:', \%opts));
    665 
    666 # See if we got a cache with the requests in it.
    667 # If we can match the request, return the result.
    668 if ($opts{c}) {
    669     $cachekey = '';
    670     for my $a (@ARGV) {
    671 	$cachekey .= ' ' if ($cachekey ne '');
    672 	$cachekey .= $a;
    673     }
    674     if (open (my $if, $opts{c})) {
    675 	while (my $line = <$if>) {
    676 	    chomp ($line);
    677 	    my ($key, $val) = split (/\t/, $line);
    678 	    if ($key eq $cachekey) {
    679 		output ($val);
    680 		print ("\n");
    681 		exit (0);
    682 	    }
    683 	}
    684     }
    685 }
    686 
    687 foreach my $d (split (/,/, $opts{L})) {
    688     push (@libdirs, $d);
    689 }
    690 foreach my $d (split (/,/, $opts{I})) {
    691     push (@headerdirs, $d);
    692 }    
    693 foreach my $d (split (/,/, $opts{l})) {
    694     push (@libs, $d);
    695 }    
    696 
    697 push (@libdirs, @def_libdirs);
    698 push (@headerdirs, @def_headerdirs);
    699 my $action = shift (@ARGV);
    700 
    701 if ($action eq 'header') {
    702     header (@ARGV);
    703 } elsif ($action eq 'headerdir') {
    704     headerdir (@ARGV);
    705 } elsif ($action eq 'lib') {
    706     lib (@ARGV);
    707 } elsif ($action eq 'so-cflags') {
    708     so_cflags (@ARGV);
    709 } elsif ($action eq 'so-lflags') {
    710     so_lflags (@ARGV);
    711 } elsif ($action eq 'c-compiler') {
    712     c_compiler(@ARGV);
    713 } elsif ($action eq 'c++-compiler') {
    714     cpp_compiler(@ARGV);
    715 } elsif ($action eq 'so-name') {
    716     so_name (@ARGV);
    717 } elsif ($action eq 'ifheader') {
    718     if_header (@ARGV);
    719 } elsif ($action eq 'ifheader01') {
    720     if_header01 (@ARGV);
    721 } elsif ($action eq 'libfunction') {
    722     libfunction (@ARGV);
    723 } elsif ($action eq 'libfunction01') {
    724     libfunction01 (@ARGV);
    725 } elsif ($action eq 'libvariable01') {
    726     libvariable01 (@ARGV);
    727 } elsif ($action eq 'optflags') {
    728     optflags (@ARGV);
    729 } else {
    730     usage ();
    731 }
    732 
    733 print ("\n") if ($printed);
    734 
    735 # Add to the cache if necessary.
    736 if ($opts{c}) {
    737     open (my $of, ">>$opts{c}")
    738       or die ("Cannot append to cache file $opts{c}: $!\n");
    739     print $of ("$cachekey\t$cacheval\n");
    740 }
    741 
    742 if ($#warnings > -1) {
    743     foreach my $w (@warnings) {
    744 	print STDERR ("$base WARNING: $w") unless ($opts{s});
    745     }
    746     exit (1);
    747 }
    748 exit (0);
    749