root/openpgpsdk/trunk/configure

Revision 193 (checked in by ben, 8 years ago)

More headers needed.

  • Property svn:executable set to *
Line 
1 #!/usr/bin/perl -w
2
3 use strict;
4
5 use Carp;
6 use File::Temp;
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 sub trace {
17     return if !$Log;
18
19     $Log->seek(0,2);
20     print $Log join '',@_;
21 }
22
23 our %Subst=(
24             CRYPTO_LIBS => '-lcrypto',
25             ZLIB => '-lz',
26             INCLUDES => '',
27             CFLAGS => '',
28            );
29
30 my %Args=(
31           '--help' => \&usage,
32           '--use-dmalloc' => sub {
33               $Subst{DM_FLAGS}='-I/usr/local/include -DDMALLOC';
34               $Subst{DM_LIB}='/usr/local/lib/libdmalloc.a';
35           },
36           '--with-openssl=' => sub {
37               my $loc=shift;
38               $Subst{INCLUDES}.=" -I $loc/include";
39               $Subst{CRYPTO_LIBS}="$loc/libcrypto.a";
40           },
41           '--with-zlib=' => sub {
42               my $loc=shift;
43               $Subst{INCLUDES}.=" -I $loc";
44               $Subst{ZLIB}="$loc/libz.a";
45           },
46           '--log=' => sub {
47               $LogFile=shift;
48               $Log=new IO::File(">$LogFile");
49               $Log->autoflush(1);
50           },
51           '--64' => sub {
52               $Subst{CFLAGS}.=' -m64';
53           }
54          );
55
56 my %Functions=(
57                'socket' => { headers => ['sys/types.h','sys/socket.h'],
58                              call => 'socket(0,0,0)',
59                              libs => [[],['socket','nsl']] },
60                );
61
62 my @Headers=qw(alloca.h);
63 my @Types=qw(time_t);
64 my @RHeaders=qw(openssl/bn.h zlib.h);
65
66 our %Knowledge=(
67                 cc => sub { return chooseBinary('gcc','cc')
68                              || croak 'Can\'t find C compiler'; },
69                 path => sub { return [split /:/,$ENV{PATH}]; },
70                 time_t => sub { return typeInfo('time_t','time.h'); }
71               );
72
73 while(my $arg=shift) {
74     my $arg2;
75     if($arg =~ /^(.+=)(.+)$/) {
76         $arg=$1;
77         $arg2=$2;
78     }
79     my $code=$Args{$arg};
80     croak "Don't understand: $arg" if !defined $code;
81     &$code($arg2);
82 }
83
84 #my $os=`uname -s`;
85
86 checkHeaders(\@RHeaders);
87
88 $Subst{'CC'}=getKnowledge('cc');
89
90 findHeaders(\@Headers);
91 investigateTypes(\@Types);
92 my $libs=findLibraries(\%Functions);
93 $Subst{'LIBS'}=join(' ',map { "-l$_" } @$libs);
94 #exit;
95
96 fixSubst();
97
98 create('src/.depend');
99 create('examples/.depend');
100
101 fileSubst('src/Makefile','#','');
102 fileSubst('examples/Makefile','#','');
103 fileSubst('include/configure.h','/*','*/');
104
105 print "make clean\n";
106 system 'make clean' || exit;
107 print "make force_depend\n";
108 if(system('make force_depend') != 0) {
109     print STDERR "Configuration failed\n";
110     exit 1;
111 }
112
113 sub subst {
114     my $line=shift;
115
116     while(my($k,$v)=each %Subst) {
117         $line =~ s/\%$k\%/$v/g;
118     }
119     $line =~ s/\%.+?\%//g;
120     return $line;
121 }
122
123 sub chooseBinary {
124     my $path=getKnowledge('path');
125     while(my $bin=shift) {
126         foreach my $p (@$path) {
127             return $bin if -x "$p/$bin";
128         }
129     }
130     return 'false';
131 }
132
133 sub getKnowledge {
134     my $thing=shift;
135
136     croak "Asked for nonexistent knowledge $thing"
137       if !exists $Knowledge{$thing};
138
139     if(ref $Knowledge{$thing} eq 'CODE') {
140         print "Finding $thing\n";
141         $Knowledge{$thing}=&{$Knowledge{$thing}}();
142     }
143     return $Knowledge{$thing};
144 }
145
146 sub usage {
147     foreach my $k (keys %Args) {
148         print "$k\n";
149     }
150     exit;
151 }
152
153 sub findHeaders {
154     my $list=shift;
155
156     foreach my $h (@$list) {
157         my $n='HAVE_'.uc $h;
158         $n =~ s/[\.\/]/_/;
159         print "Looking for header $h ($n)\n";
160         if(-e "/usr/include/$h") {
161             $Subst{$n}="#define $n 0";
162         } else {
163             $Subst{$n}="#undef $n";
164         }
165     }
166 }
167
168 sub fileSubst {
169     my $file=shift;
170     my $cs=shift;
171     my $ce=shift;
172
173     open(T,"$file.template") || croak "Can't open $file.template: $!";
174     unlink $file;
175     open(M,">$file") || croak "Can't create $file: $!";
176
177     print M "$cs generated by configure from $file.template. Don't edit. $ce\n\n";
178
179     while(my $line=<T>) {
180         print M subst($line);
181     }
182
183     close M;
184     close T;
185
186     chmod 0444,"$file";
187 }
188
189 sub fixSubst {
190     foreach my $k (keys %Subst) {
191         $Subst{$k} =~ s/~/$ENV{HOME}/g;
192     }
193 }
194
195 sub create {
196     my $file=shift;
197
198     print "Creating $file\n";
199     open(D,">$file") || croak "Can't create $file: $!";
200     close D;
201 }
202
203 sub build {
204     my $code=shift;
205     my $link=shift;
206
207     my $cc=getKnowledge('cc');
208     my $fh=new File::Temp(SUFFIX => '.c');
209
210     my($v,$d,$f)=File::Spec->splitpath($fh->filename());
211
212     my $cur=File::Spec->rel2abs(File::Spec->curdir());
213     chdir($d) || croak "chdir($d): $!";
214
215     print $fh $code;
216     $fh->close();
217
218     my $cflag='';
219     $cflag='-c' if !defined $link;
220     my $cmd="$cc $Subst{CFLAGS} $Subst{INCLUDES} -Wall -Werror $cflag ".$f;
221     $cmd.=" $link" if defined $link;
222     trace("$cmd\n--code--\n$code--------\n");
223     my $ret=system("$cmd >> $LogFile 2>&1");
224
225     my $obj=$fh->filename();
226     $obj =~ s/\.c$/.o/;
227     unlink($obj) || $! == ENOENT || croak "unlink($obj): $!";
228     unlink('a.out') || $! == ENOENT || croak "unlink(a.out): $!";
229
230     chdir($cur) || croak "chdir($cur): $!";
231
232     return $ret == 0;
233 }
234
235 sub typeInfo {
236     my $type=shift;
237     my $header=shift;
238
239     my %info;
240
241     print "Getting info about $type.\n";
242
243     foreach my $fmt (qw(%d %ld)) {
244         my $code="#include <$header>\n";
245         $code .= "#include <stdio.h>\n";
246         $code .= "void f(void) { static $type t; printf(\"$fmt\",t); }\n";
247         if(build($code)) {
248             $info{fmt}=$fmt;
249             print "  $type printf format is $fmt\n";
250         }
251     }
252     croak "Can't determine print format for $type" if !defined $info{fmt};
253
254     return \%info;
255 }
256
257 sub investigateTypes {
258     my $types=shift;
259
260     foreach my $type (@$types) {
261         my $info=getKnowledge($type);
262         $Subst{uc($type)."_FMT"}="\"$info->{fmt}\"";
263     }
264 }
265
266 sub checkHeaders {
267     my $headers=shift;
268
269     foreach my $h (@$headers) {
270         print "Check required header $h\n";
271         build("#include <$h>\n") || croak "Can't find required header $h";
272     }
273 }
274
275 sub findLibraries {
276     my $funcs=shift;
277
278     my @libs;
279   func:
280     foreach my $func (keys %$funcs) {
281         print "Checking libraries for $func()\n";
282         my $code=join("\n",map { "#include <$_>" }
283                       @{$funcs->{$func}->{headers}});
284         $code.="\nint main() { $funcs->{$func}->{call}; return 0; }\n";
285         foreach my $lgroup (@{$funcs->{$func}->{libs}}) {
286             print "  trying ",@$lgroup ? join(', ',@$lgroup) : 'no libraries';
287             if(build($code,join(' ',map { "-l$_" } @$lgroup))) {
288                 push @libs,@$lgroup;
289                 print " ... OK\n";
290                 next func;
291             }
292             print " ... no\n";
293         }
294     }
295     return \@libs;
296 }
297
Note: See TracBrowser for help on using the browser.