root/openpgpsdk/trunk/configure

Revision 647 (checked in by ben, 4 years ago)

Reinstate CUnit header check. Switch unshift to push.

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