Ugly hack to avoid recompiling the same thing multiple times in parallel.
[openssl.git] / util / pl / unix.pl
1 #!/usr/local/bin/perl
2 #
3 # unix.pl - the standard unix makefile stuff.
4 #
5
6 $o='/';
7 $cp='/bin/cp';
8 $rm='/bin/rm -f';
9
10 # C compiler stuff
11
12 if ($gcc)
13         {
14         $cc='gcc';
15         if ($debug)
16                 { $cflags="-g2 -ggdb"; }
17         else
18                 { $cflags="-O3 -fomit-frame-pointer"; }
19         }
20 else
21         {
22         $cc='cc';
23         if ($debug)
24                 { $cflags="-g"; }
25         else
26                 { $cflags="-O"; }
27         }
28 $obj='.o';
29 $asm_suffix='.s';
30 $ofile='-o ';
31
32 # EXE linking stuff
33 $link='${CC}';
34 $lflags='${CFLAG}';
35 $efile='-o ';
36 $exep='';
37 $ex_libs="";
38
39 # static library stuff
40 $mklib='ar r';
41 $mlflags='';
42 $ranlib=&which("ranlib") or $ranlib="true";
43 $plib='lib';
44 $libp=".a";
45 $shlibp=".a";
46 $lfile='';
47
48 $asm='as';
49 $afile='-o ';
50 $bn_asm_obj="";
51 $bn_asm_src="";
52 $des_enc_obj="";
53 $des_enc_src="";
54 $bf_enc_obj="";
55 $bf_enc_src="";
56
57 %perl1 = (
58           'md5-x86_64' => 'crypto/md5',
59           'x86_64-mont' => 'crypto/bn',
60           'x86_64-mont5' => 'crypto/bn',
61           'x86_64-gf2m' => 'crypto/bn',
62           'modexp512-x86_64' => 'crypto/bn',
63           'aes-x86_64' => 'crypto/aes',
64           'vpaes-x86_64' => 'crypto/aes',
65           'bsaes-x86_64' => 'crypto/aes',
66           'aesni-x86_64' => 'crypto/aes',
67           'aesni-sha1-x86_64' => 'crypto/aes',
68           'sha1-x86_64' => 'crypto/sha',
69           'e_padlock-x86_64' => 'engines',
70           'rc4-x86_64' => 'crypto/rc4',
71           'rc4-md5-x86_64' => 'crypto/rc4',
72           'ghash-x86_64' => 'crypto/modes',
73           'aesni-gcm-x86_64' => 'crypto/modes',
74          );
75
76 # If I were feeling more clever, these could probably be extracted
77 # from makefiles.
78 sub platform_perlasm_compile_target
79         {
80         local($target, $source, $bname) = @_;
81
82         for $p (keys %perl1)
83                 {
84                 if ($target eq "\$(OBJ_D)/$p.o")
85                         {
86                         return << "EOF";
87 \$(TMP_D)/$p.s: $perl1{$p}/asm/$p.pl
88         \$(PERL) $perl1{$p}/asm/$p.pl \$(PERLASM_SCHEME) > \$@
89 EOF
90                         }
91                 }
92         if ($target eq '$(OBJ_D)/x86_64cpuid.o')
93                 {
94                 return << 'EOF';
95 $(TMP_D)/x86_64cpuid.s: crypto/x86_64cpuid.pl
96         $(PERL) crypto/x86_64cpuid.pl $(PERLASM_SCHEME) > $@
97 EOF
98                 }
99         elsif ($target eq '$(OBJ_D)/sha256-x86_64.o')
100                 {
101                 return << 'EOF';
102 $(TMP_D)/sha256-x86_64.s: crypto/sha/asm/sha512-x86_64.pl
103         $(PERL) crypto/sha/asm/sha512-x86_64.pl $(PERLASM_SCHEME) $@
104 EOF
105                 }
106         elsif ($target eq '$(OBJ_D)/sha512-x86_64.o')
107                 {
108                 return << 'EOF';
109 $(TMP_D)/sha512-x86_64.s: crypto/sha/asm/sha512-x86_64.pl
110         $(PERL) crypto/sha/asm/sha512-x86_64.pl $(PERLASM_SCHEME) $@
111 EOF
112                 }
113         elsif ($target eq '$(OBJ_D)/sha512-x86_64.o')
114                 {
115                 return << 'EOF';
116 $(TMP_D)/sha512-x86_64.s: crypto/sha/asm/sha512-x86_64.pl
117         $(PERL) crypto/sha/asm/sha512-x86_64.pl $(PERLASM_SCHEME) $@
118 EOF
119                 }
120
121         die $target;
122         }
123
124 sub special_compile_target
125         {
126         local($target) = @_;
127
128         if ($target eq 'crypto/bn/x86_64-gcc')
129                 {
130                 return << "EOF";
131 \$(TMP_D)/x86_64-gcc.o: crypto/bn/asm/x86_64-gcc.c
132         \$(CC) \$(CFLAGS) -c -o \$@ crypto/bn/asm/x86_64-gcc.c
133 EOF
134                 }
135         return undef;
136         }
137
138 sub do_lib_rule
139         {
140         local($obj,$target,$name,$shlib)=@_;
141         local($ret,$_,$Name);
142
143         $target =~ s/\//$o/g if $o ne '/';
144         $target="$target";
145         ($Name=$name) =~ tr/a-z/A-Z/;
146
147         $ret.="$target: \$(${Name}OBJ)\n";
148         $ret.="\t\$(RM) $target\n";
149         $ret.="\t\$(MKLIB) $target \$(${Name}OBJ)\n";
150         $ret.="\t\$(RANLIB) $target\n\n";
151         }
152
153 sub do_link_rule
154         {
155         local($target,$files,$dep_libs,$libs)=@_;
156         local($ret,$_);
157
158         $file =~ s/\//$o/g if $o ne '/';
159         $n=&bname($target);
160         $ret.="$target: $files $dep_libs\n";
161         $ret.="\t\$(LINK) ${efile}$target \$(LFLAGS) $files $libs\n\n";
162         return($ret);
163         }
164
165 sub which
166         {
167         my ($name)=@_;
168         my $path;
169         foreach $path (split /:/, $ENV{PATH})
170                 {
171                 if (-x "$path/$name")
172                         {
173                         return "$path/$name";
174                         }
175                 }
176         }
177
178 sub fixtests
179   {
180   my ($str, $tests) = @_;
181
182   foreach my $t (keys %$tests)
183     {
184     $str =~ s/(\.\/)?\$\($t\)/\$(TEST_D)\/$tests->{$t}/g;
185     }
186
187   return $str;
188   }
189
190 sub fixdeps
191   {
192   my ($str, $fakes) = @_;
193
194   my @t = split(/\s+/, $str);
195   $str = '';
196   foreach my $t (@t)
197     {
198     $str .= ' ' if $str ne '';
199     if (exists($fakes->{$t}))
200       {
201       $str .= $fakes->{$t};
202       next;
203       }
204     if ($t =~ /^[^\/]+$/)
205       {
206       $str .= '$(TEST_D)/' . $t;
207       }
208     else
209       {
210       $str .= $t;
211       }
212     }
213
214   return $str;
215   }
216
217 sub fixrules
218   {
219   my ($str) = @_;
220
221   # Compatible with -j...
222   $str =~ s/^(\s+@?)/$1cd \$(TEST_D) && /;
223   return $str;
224
225   # Compatible with not -j.
226   my @t = split("\n", $str);
227   $str = '';
228   my $prev;
229   foreach my $t (@t)
230     {
231     $t =~ s/^\s+//;
232     if (!$prev)
233       {
234       if ($t =~ /^@/)
235         {
236         $t =~ s/^@/\@cd \$(TEST_D) && /;
237         }
238       elsif ($t !~ /^\s*#/)
239         {
240         $t = 'cd $(TEST_D) && ' . $t;
241         }
242       }
243     $str .= "\t$t\n";
244     $prev = $t =~/\\$/;
245     }
246   return $str;
247 }
248
249 sub copy_scripts
250   {
251   my ($sed, $src, @targets) = @_;
252
253   my $s = '';
254   foreach my $t (@targets)
255     {
256     # Copy first so we get file modes...
257     $s .= "\$(TEST_D)/$t: \$(SRC_D)/$src/$t\n\tcp \$(SRC_D)/$src/$t \$(TEST_D)/$t\n";
258     $s .= "\tsed -e 's/\\.\\.\\/apps/..\\/\$(OUT_D)/' -e 's/\\.\\.\\/util/..\\/\$(TEST_D)/' < \$(SRC_D)/$src/$t > \$(TEST_D)/$t\n" if $sed;
259     $s .= "\n";
260     }
261   return $s;
262   }
263
264 sub get_tests
265   {
266   my ($makefile) = @_;
267
268   open(M, $makefile) || die "Can't open $makefile: $!";
269   my %targets;
270   my %deps;
271   my %tests;
272   my %alltests;
273   my %fakes;
274   while (my $line = <M>)
275     {
276     chomp $line;
277     while ($line =~ /^(.*)\\$/)
278       {
279       $line = $1 . <M>;
280       }
281
282     if ($line =~ /^alltests:(.*)$/)
283       {
284       my @t = split(/\s+/, $1);
285       foreach my $t (@t)
286         {
287         $targets{$t} = '';
288         $alltests{$t} = undef;
289         }
290       }
291
292     if (($line =~ /^(?<t>\S+):(?<d>.*)$/ && exists $targets{$1})
293         || $line =~ /^(?<t>test_(ss|gen) .*):(?<d>.*)/)
294       {
295       my $t = $+{t};
296       my $d = $+{d};
297       # If there are multiple targets stupid FreeBSD make runs the
298       # rules once for each dependency that matches one of the
299       # targets. Running the same rule twice concurrently causes
300       # breakage, so replace with a fake target.
301       if ($t =~ /\s/)
302         {
303         ++$fake;
304         my @targets = split /\s+/, $t;
305         $t = "_fake$fake";
306         foreach my $f (@targets)
307           {
308           $fakes{$f} = $t;
309           }
310         }
311       $deps{$t} = $d;
312       $deps{$t} =~ s/#.*$//;
313       for (;;)
314         {
315         $line = <M>;
316         chomp $line;
317         last if $line eq '';
318         $targets{$t} .= "$line\n";
319         }
320       next;
321       }
322
323     if ($line =~ /^(\S+TEST)=\s*(\S+)$/)
324       {
325       $tests{$1} = $2;
326       next;
327       }
328     }
329
330   delete $alltests{test_jpake} if $no_jpake;
331   delete $targets{test_ige} if $no_ige;
332   delete $alltests{test_md2} if $no_md2;
333   delete $alltests{test_rc5} if $no_rc5;
334
335   my $tests;
336   foreach my $t (keys %tests)
337     {
338     $tests .= "$t = $tests{$t}\n";
339     }
340
341   my $each;
342   foreach my $t (keys %targets)
343     {
344     next if $t eq '';
345
346     my $d = $deps{$t};
347     $d =~ s/\.\.\/apps/\$(BIN_D)/g;
348     $d =~ s/\.\.\/util/\$(TEST_D)/g;
349     $d = fixtests($d, \%tests);
350     $d = fixdeps($d, \%fakes);
351
352     my $r = $targets{$t};
353     $r =~ s/\.\.\/apps/..\/\$(BIN_D)/g;
354     $r =~ s/\.\.\/util/..\/\$(TEST_D)/g;
355     $r =~ s/\.\.\/(\S+)/\$(SRC_D)\/$1/g;
356     $r = fixrules($r);
357
358     next if $r eq '';
359
360     $t =~ s/\s+/ \$(TEST_D)\//g;
361
362     $each .= "$t: test_scripts $d\n\t\@echo '$t test started'\n$r\t\@echo '$t test done'\n\n";
363     }
364
365   # FIXME: Might be a clever way to figure out what needs copying
366   my @copies = ( 'bctest',
367                  'testgen',
368                  'cms-test.pl',
369                  'tx509',
370                  'test.cnf',
371                  'testenc',
372                  'tocsp',
373                  'testca',
374                  'CAss.cnf',
375                  'testtsa',
376                  'CAtsa.cnf',
377                  'Uss.cnf',
378                  'P1ss.cnf',
379                  'P2ss.cnf',
380                  'tcrl',
381                  'tsid',
382                  'treq',
383                  'tpkcs7',
384                  'tpkcs7d',
385                  'testcrl.pem',
386                  'testx509.pem',
387                  'v3-cert1.pem',
388                  'v3-cert2.pem',
389                  'testreq2.pem',
390                  'testp7.pem',
391                  'pkcs7-1.pem',
392                  'trsa',
393                  'testrsa.pem',
394                  'testsid.pem',
395                  'testss',
396                );
397   my $copies = copy_scripts(1, 'test', @copies);
398   $copies .= copy_scripts(0, 'test', ('smcont.txt'));
399
400   my @utils = ( 'shlib_wrap.sh',
401                 'opensslwrap.sh',
402               );
403   $copies .= copy_scripts(1, 'util', @utils);
404
405   my @apps = ( 'CA.sh',
406                'openssl.cnf',
407              );
408   $copies .= copy_scripts(1, 'apps', @apps);
409
410   $copies .= copy_scripts(1, 'crypto/evp', ('evptests.txt'));
411
412   $scripts = "test_scripts: \$(TEST_D)/CA.sh \$(TEST_D)/opensslwrap.sh \$(TEST_D)/openssl.cnf \$(TEST_D)/shlib_wrap.sh ocsp smime\n";
413   $scripts .= "\nocsp:\n\tcp -R test/ocsp-tests \$(TEST_D)\n";
414   $scripts .= "\smime:\n\tcp -R test/smime-certs \$(TEST_D)\n";
415
416   my $all = 'test:';
417   foreach my $t (keys %alltests)
418     {
419     if (exists($fakes{$t}))
420       {
421       $all .= " $fakes{$t}";
422       }
423     else
424       {
425       $all .= " $t";
426       }
427     }
428
429   return "$scripts\n$copies\n$tests\n$all\n\n$each";
430   }
431
432 1;