root/openpgpsdk/trunk/configure

Revision 541 (checked in by rachel, 5 years ago)

CUnit only needs to be compiled once, not every time we make clean.

  • Property svn:executable set to *
Line 
1 #!/usr/bin/perl -w
2
3 use strict;
4
5 use Carp;
6 use File::Temp 0.14;
7 use File::Spec;
8 use POSIX qw(:errno_h);
9 use IO::File;
10
11 $|=1;
12
13 our $Log;
14 our $LogFile='/dev/null';
15
16 my $use_oink;
17
18 sub trace {
19     return if !$Log;
20
21     $Log->seek(0,2);
22     print $Log join '',@_;
23 }
24
25 our %Subst=(
26             CRYPTO_LIBS => '-lcrypto',
27             ZLIB => '-lz',
28             INCLUDES => '',
29             CFLAGS => '',
30            );
31
32 my %Args=(
33           '--help' => \&usage,
34           '--use-dmalloc' => sub {
35               $Subst{DM_FLAGS}='-I/usr/local/include -DDMALLOC';
36               $Subst{DM_LIB}='/usr/local/lib/libdmalloc.a';
37           },
38           '--with-openssl=' => sub {
39               my $loc=shift;
40               $Subst{INCLUDES}.=" -I $loc/include";
41               $Subst{CRYPTO_LIBS}="$loc/lib/libcrypto.a";
42               # assume developer version if library isn't in .../lib
43               $Subst{CRYPTO_LIBS}="$loc/libcrypto.a"
44                   if !-f $Subst{CRYPTO_LIBS};
45           },
46           '--with-zlib=' => sub {
47               my $loc=shift;
48               $Subst{INCLUDES}.=" -I $loc";
49               $Subst{ZLIB}="$loc/libz.a";
50           },
51           '--log=' => sub {
52               $LogFile=shift;
53               $Log=new IO::File(">$LogFile");
54               $Log->autoflush(1);
55           },
56           '--64' => sub {
57               $Subst{CFLAGS}.=' -m64';
58           },
59           '--maintainer' => sub {
60               $Subst{CFLAGS}.=' -fno-builtin';
61           },
62           '--cc=' => sub {
63               my $cc=shift;
64               $Subst{CC}=$cc;
65           },
66           '--oink=' => sub {
67               $Subst{OINK}=shift;
68           },
69          );
70
71 my %Functions=(
72                'socket' => { headers => ['sys/types.h','sys/socket.h'],
73                              call => 'socket(0,0,0)',
74                              libs => [[],['socket','nsl']] },
75                );
76
77 my @Headers=qw(alloca.h);
78 my @Types=qw(time_t);
79 my @RHeaders=qw(openssl/bn.h zlib.h);
80
81 our %Knowledge=(
82                 cc => sub { return $Subst{CC} || chooseBinary('gcc','cc')
83                              || croak 'Can\'t find C compiler'; },
84                 path => sub { return [split /:/,$ENV{PATH}]; },
85                 time_t => sub { return typeInfo('time_t','time.h'); },
86                 base_cflags => \&baseCFlags,
87                 is_gcc => \&isGCC,
88                 gcc_major => \&gccMajor,
89                 gcc_version => \&gccVersion,
90               );
91
92 while(my $arg=shift) {
93     my $arg2;
94     if($arg =~ /^(.+=)(.+)$/) {
95         $arg=$1;
96         $arg2=$2;
97     }
98     my $code=$Args{$arg};
99     croak "Don't understand: $arg" if !defined $code;
100     &$code($arg2);
101 }
102
103 #my $os=`uname -s`;
104
105 $Subst{'CC'}=getKnowledge('cc');
106
107 $Subst{'CFLAGS'}.=' '.getKnowledge('base_cflags');
108
109 checkHeaders(\@RHeaders);
110
111 findHeaders(\@Headers);
112 investigateTypes(\@Types);
113 my $libs=findLibraries(\%Functions);
114 $Subst{'LIBS'}=join(' ',map { "-l$_" } @$libs);
115 #exit;
116
117 if($Subst{OINK}) {
118     use Cwd;
119     my $path=getcwd();
120     $Subst{CC}="$path/util/oink_cc.pl --cc=$Subst{CC}";
121 }
122
123 fixSubst();
124
125 my $path=`pwd`;
126 chomp $path;
127
128
129 create('src/advanced/.depend');
130 create('src/standard/.depend');
131 create('src/app/.depend');
132 create('examples/.depend');
133 create('tests/.depend');
134
135 fileSubst('src/Makefile','#','');
136 fileSubst('src/advanced/Makefile','#','');
137 fileSubst('src/standard/Makefile','#','');
138 fileSubst('src/app/Makefile','#','');
139 fileSubst('examples/Makefile','#','');
140 fileSubst('tests/Makefile','#','');
141 fileSubst('util/Makefile.oink','#','');
142 fileSubst('include/openpgpsdk/configure.h','/*','*/');
143
144 print "make cunit\n";
145 system('make cunit') == 0 || exit;
146 print "make clean\n";
147 system('make clean') == 0 || exit;
148 print "make force_depend\n";
149 if(system('make force_depend') != 0) {
150     print STDERR "Configuration failed\n";
151     exit 1;
152 }
153
154 sub subst {
155     my $line=shift;
156
157     while(my($k,$v)=each %Subst) {
158         $line =~ s/\%$k\%/$v/g;
159     }
160     $line =~ s/\%.+?\%//g;
161     return $line;
162 }
163
164 sub chooseBinary {
165     my $path=getKnowledge('path');
166     while(my $bin=shift) {
167         foreach my $p (@$path) {
168             return $bin if -x "$p/$bin";
169         }
170     }
171     return 'false';
172 }
173
174 our $indent;
175
176 sub indent {
177     for my $n (2..$indent) {
178         print "  ";
179     }
180 }
181
182 sub showThing {
183     my $rthing=shift;
184
185     if(ref $rthing eq 'SCALAR') {
186         return $$rthing;
187     } elsif(ref $rthing eq 'REF') {
188         return showThing($$rthing);
189     } elsif(ref $rthing eq 'ARRAY') {
190         return join(' ',@$rthing);
191     } elsif(ref $rthing eq 'HASH') {
192         my $str;
193         foreach my $k (keys %$rthing) {
194             $str .= ' ' if $str;
195             $str .= "$k -> $rthing->{$k}";
196         }
197         return $str;
198     }
199
200     print "ref=", ref($rthing), "\n";
201     return '?Can\'t display?';
202 }
203
204 sub getKnowledge {
205     my $thing=shift;
206
207     croak "Asked for nonexistent knowledge $thing"
208       if !exists $Knowledge{$thing};
209
210     ++$indent;
211     if(ref $Knowledge{$thing} eq 'CODE') {
212         indent();
213         print "Finding $thing\n";
214         $Knowledge{$thing}=&{$Knowledge{$thing}}();
215         indent();
216         print "Found $thing: ", showThing(\$Knowledge{$thing}), "\n";
217     }
218     --$indent;
219     return $Knowledge{$thing};
220 }
221
222 sub usage {
223     foreach my $k (keys %Args) {
224         print "$k\n";
225     }
226     exit;
227 }
228
229 sub findHeaders {
230     my $list=shift;
231
232     foreach my $h (@$list) {
233         my $n='HAVE_'.uc $h;
234         $n =~ s/[\.\/]/_/;
235         print "Looking for header $h ($n)\n";
236         if(-e "/usr/include/$h") {
237             $Subst{$n}="#define $n 0";
238         } else {
239             $Subst{$n}="#undef $n";
240         }
241     }
242 }
243
244 sub fileSubst {
245     my $file=shift;
246     my $cs=shift;
247     my $ce=shift;
248
249     open(T,"$file.template") || croak "Can't open $file.template: $!";
250     unlink $file;
251     open(M,">$file") || croak "Can't create $file: $!";
252
253     print M "$cs generated by configure from $file.template. Don't edit. $ce\n\n";
254
255     while(my $line=<T>) {
256         print M subst($line);
257     }
258
259     close M;
260     close T;
261
262     chmod 0444,"$file";
263 }
264
265 sub fixSubst {
266     foreach my $k (keys %Subst) {
267         $Subst{$k} =~ s/~/$ENV{HOME}/g;
268     }
269 }
270
271 sub create {
272     my $file=shift;
273
274     print "Creating $file\n";
275     open(D,">$file") || croak "Can't create $file: $!";
276     close D;
277 }
278
279 sub build {
280     my $code=shift;
281     my $link=shift;
282
283     my $cc=getKnowledge('cc');
284     my $fh=new File::Temp(SUFFIX => '.c');
285
286     my($v,$d,$f)=File::Spec->splitpath($fh->filename());
287
288     my $cur=File::Spec->rel2abs(File::Spec->curdir());
289     chdir($d) || croak "chdir($d): $!";
290
291     print $fh $code;
292     $fh->close();
293
294     my $cflag='';
295     $cflag='-c' if !defined $link;
296     my $cmd="$cc $Subst{CFLAGS} $Subst{INCLUDES} $cflag ".$f;
297     $cmd.=" $link" if defined $link;
298     trace("$cmd\n--code--\n$code--------\n");
299     my $ret=system("$cmd >> $LogFile 2>&1");
300
301     my $obj=$fh->filename();
302     $obj =~ s/\.c$/.o/;
303     unlink($obj) || $! == ENOENT || croak "unlink($obj): $!";
304     unlink('a.out') || $! == ENOENT || croak "unlink(a.out): $!";
305
306     chdir($cur) || croak "chdir($cur): $!";
307
308     return $ret == 0;
309 }
310
311 sub typeInfo {
312     my $type=shift;
313     my $header=shift;
314
315     my %info;
316
317     print "Getting info about $type.\n";
318
319     foreach my $fmt (qw(%d %ld)) {
320         my $code="#include <$header>\n";
321         $code .= "#include <stdio.h>\n";
322         $code .= "void f(void) { static $type t; printf(\"$fmt\",t); }\n";
323         if(build($code)) {
324             $info{fmt}=$fmt;
325             print "  $type printf format is $fmt\n";
326         }
327     }
328     croak "Can't determine print format for $type" if !defined $info{fmt};
329
330     return \%info;
331 }
332
333 sub investigateTypes {
334     my $types=shift;
335
336     foreach my $type (@$types) {
337         my $info=getKnowledge($type);
338         $Subst{uc($type)."_FMT"}="\"$info->{fmt}\"";
339     }
340 }
341
342 sub checkHeaders {
343     my $headers=shift;
344
345     foreach my $h (@$headers) {
346         print "Check required header $h\n";
347         build("#include <$h>\n") || croak "Can't find required header $h";
348     }
349 }
350
351 sub findLibraries {
352     my $funcs=shift;
353
354     my @libs;
355   func:
356     foreach my $func (keys %$funcs) {
357         print "Checking libraries for $func()\n";
358         my $code=join("\n",map { "#include <$_>" }
359                       @{$funcs->{$func}->{headers}});
360         $code.="\nint main() { $funcs->{$func}->{call}; return 0; }\n";
361         foreach my $lgroup (@{$funcs->{$func}->{libs}}) {
362             print "  trying ",@$lgroup ? join(', ',@$lgroup) : 'no libraries';
363             if(build($code,join(' ',map { "-l$_" } @$lgroup))) {
364                 push @libs,@$lgroup;
365                 print " ... OK\n";
366                 next func;
367             }
368             print " ... no\n";
369         }
370     }
371     return \@libs;
372 }
373
374 sub baseCFlags {
375     my $flags='';
376     if(getKnowledge('is_gcc')) {
377         $flags='-Wall -Werror -W -g';
378 #       my $v=getKnowledge('gcc_major');
379 #       $flags.=' -Wdeclaration-after-statement' if $v >= 3;
380     }
381     return $flags;
382 }
383
384 sub isGCC {
385     my $cc=getKnowledge('cc');
386
387     my $ret=build("int main()\n{\n#ifndef __GNUC__\n  syntax error\n#endif\n return 0; }\n");
388     trace("isGCC=$ret\n");
389     return $ret;
390 }
391
392 sub gccVersion {
393     return undef if !getKnowledge('is_gcc');
394
395     my $cc=getKnowledge('cc');
396     my $vstr=`$cc --version`;
397
398     my($v)=$vstr =~ /(\d+\.\d+\.\d+)/;
399
400     trace("gcc version=$v\n");
401
402     return $v;
403 }
404
405 sub gccMajor {
406     my $v=getKnowledge('gcc_version');
407     return undef if !defined $v;
408
409     ($v)=$v =~ /^(\d+)/;
410
411     trace("gcc major=$v\n");
412
413     return $v;
414 }
Note: See TracBrowser for help on using the browser.