xref: /curl/tests/testcurl.pl (revision 88f1b705)
1#!/usr/bin/env perl
2#***************************************************************************
3#                                  _   _ ____  _
4#  Project                     ___| | | |  _ \| |
5#                             / __| | | | |_) | |
6#                            | (__| |_| |  _ <| |___
7#                             \___|\___/|_| \_\_____|
8#
9# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
10#
11# This software is licensed as described in the file COPYING, which
12# you should have received as part of this distribution. The terms
13# are also available at https://curl.se/docs/copyright.html.
14#
15# You may opt to use, copy, modify, merge, publish, distribute and/or sell
16# copies of the Software, and permit persons to whom the Software is
17# furnished to do so, under the terms of the COPYING file.
18#
19# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20# KIND, either express or implied.
21#
22# SPDX-License-Identifier: curl
23#
24###########################################################################
25
26###########################
27#  What is This Script?
28###########################
29
30# testcurl.pl is the master script to use for automatic testing of curl
31# directly off its source repository.
32# This is written for the purpose of being run from a crontab job or similar
33# at a regular interval. The output is suitable to be mailed to
34# curl-autocompile@haxx.se to be dealt with automatically (make sure the
35# subject includes the word "autobuild" as the mail gets silently discarded
36# otherwise).  The most current build status (with a reasonable backlog) will
37# be published on the curl site, at https://curl.se/auto/
38
39# USAGE:
40# testcurl.pl [options] [curl-daily-name] > output
41
42# Options:
43#
44# --configure=[options]    Configure options
45# --crosscompile           This is a crosscompile
46# --desc=[desc]            Description of your test system
47# --email=[email]          Set email address to report as
48# --extvercmd=[command]    Command to use for displaying version with cross compiles.
49# --mktarball=[command]    Command to run after completed test
50# --name=[name]            Set name to report as
51# --notes=[notes]          More human-readable information about this configuration
52# --nocvsup                Don't pull from git even though it is a git tree
53# --nogitpull              Don't pull from git even though it is a git tree
54# --nobuildconf            Don't run buildconf
55# --noconfigure            Don't run configure
56# --runtestopts=[options]  Options to pass to runtests.pl
57# --setup=[file name]      File name to read setup from (deprecated)
58# --target=[your os]       Specify your target environment.
59#
60# if [curl-daily-name] is omitted, a 'curl' git directory is assumed.
61#
62
63use strict;
64
65use Cwd;
66use File::Spec;
67
68# Turn on warnings (equivalent to -w, which can't be used with /usr/bin/env)
69#BEGIN { $^W = 1; }
70
71use vars qw($version $fixed $infixed $CURLDIR $git $pwd $build $buildlog
72            $buildlogname $configurebuild $targetos $confheader $binext
73            $libext);
74
75use vars qw($name $email $desc $confopts $runtestopts $setupfile $mktarball
76            $extvercmd $nogitpull $nobuildconf $crosscompile
77            $timestamp $notes);
78
79# version of this script
80$version='2023-03-28';
81$fixed=0;
82
83# Determine if we're running from git or a canned copy of curl,
84# or if we got a specific target option or setup file option.
85$CURLDIR="curl";
86if (-f ".git/config") {
87  $CURLDIR = "./";
88}
89
90$git=1;
91$setupfile = 'setup';
92$configurebuild = 1;
93while ($ARGV[0]) {
94  if ($ARGV[0] =~ /--target=/) {
95    $targetos = (split(/=/, shift @ARGV, 2))[1];
96  }
97  elsif ($ARGV[0] =~ /--setup=/) {
98    $setupfile = (split(/=/, shift @ARGV, 2))[1];
99  }
100  elsif ($ARGV[0] =~ /--extvercmd=/) {
101    $extvercmd = (split(/=/, shift @ARGV, 2))[1];
102  }
103  elsif ($ARGV[0] =~ /--mktarball=/) {
104    $mktarball = (split(/=/, shift @ARGV, 2))[1];
105  }
106  elsif ($ARGV[0] =~ /--name=/) {
107    $name = (split(/=/, shift @ARGV, 2))[1];
108  }
109  elsif ($ARGV[0] =~ /--email=/) {
110    $email = (split(/=/, shift @ARGV, 2))[1];
111  }
112  elsif ($ARGV[0] =~ /--desc=/) {
113    $desc = (split(/=/, shift @ARGV, 2))[1];
114  }
115  elsif ($ARGV[0] =~ /--notes=/) {
116    $notes = (split(/=/, shift @ARGV, 2))[1];
117  }
118  elsif ($ARGV[0] =~ /--configure=(.*)/) {
119    $confopts = $1;
120    shift @ARGV;
121  }
122  elsif (($ARGV[0] eq "--nocvsup") || ($ARGV[0] eq "--nogitpull")) {
123    $nogitpull=1;
124    shift @ARGV;
125  }
126  elsif ($ARGV[0] =~ /--nobuildconf/) {
127    $nobuildconf=1;
128    shift @ARGV;
129  }
130  elsif ($ARGV[0] =~ /--noconfigure/) {
131    $configurebuild=0;
132    shift @ARGV;
133  }
134  elsif ($ARGV[0] =~ /--crosscompile/) {
135    $crosscompile=1;
136    shift @ARGV;
137  }
138  elsif ($ARGV[0] =~ /--runtestopts=/) {
139    $runtestopts = (split(/=/, shift @ARGV, 2))[1];
140  }
141  else {
142    $CURLDIR=shift @ARGV;
143    $git=0; # a given dir, assume not using git
144  }
145}
146
147# Do the platform-specific stuff here
148$confheader = 'curl_config.h';
149$binext = '';
150$libext = '.la'; # .la since both libcurl and libcares are made with libtool
151if ($^O eq 'MSWin32' || $targetos) {
152  if (!$targetos) {
153    # If no target defined on Win32 lets assume vc
154    $targetos = 'vc';
155  }
156  if ($targetos =~ /vc/ || $targetos =~ /borland/) {
157    $binext = '.exe';
158    $libext = '.lib';
159  }
160  elsif ($targetos =~ /mingw/) {
161    $binext = '.exe';
162    if ($^O eq 'MSWin32') {
163      $libext = '.a';
164    }
165  }
166}
167
168if (($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys') &&
169    ($targetos =~ /vc/ || $targetos =~ /mingw32/ ||
170     $targetos =~ /borland/)) {
171
172  # Set these things only when building ON Windows and for Win32 platform.
173  # FOR Windows since we might be cross-compiling on another system. Non-
174  # Windows builds still default to configure-style builds with curl_config.h.
175
176  $configurebuild = 0;
177  $confheader = 'config-win32.h';
178}
179
180$ENV{LC_ALL}="C" if (($ENV{LC_ALL}) && ($ENV{LC_ALL} !~ /^C$/));
181$ENV{LC_CTYPE}="C" if (($ENV{LC_CTYPE}) && ($ENV{LC_CTYPE} !~ /^C$/));
182$ENV{LANG}="C";
183
184sub rmtree($) {
185    my $target = $_[0];
186    if ($^O eq 'MSWin32') {
187      foreach (glob($target)) {
188        s:/:\\:g;
189        system("rd /s /q $_");
190      }
191    } else {
192      system("rm -rf $target");
193    }
194}
195
196sub grepfile($$) {
197    my ($target, $fn) = @_;
198    open(my $fh, "<", $fn) or die;
199    while (<$fh>) {
200      if (/$target/) {
201        close($fh);
202        return 1;
203      }
204    }
205    close($fh);
206    return 0;
207}
208
209sub logit($) {
210    my $text=$_[0];
211    if ($text) {
212      print "testcurl: $text\n";
213    }
214}
215
216sub logit_spaced($) {
217    my $text=$_[0];
218    if ($text) {
219      print "\ntestcurl: $text\n\n";
220    }
221}
222
223sub mydie($){
224    my $text=$_[0];
225    logit "$text";
226    chdir $pwd; # cd back to the original root dir
227
228    if ($pwd && $build) {
229      # we have a build directory name, remove the dir
230      logit "removing the $build dir";
231      rmtree "$pwd/$build";
232    }
233    if (-r $buildlog) {
234      # we have a build log output file left, remove it
235      logit "removing the $buildlogname file";
236      unlink "$buildlog";
237    }
238    logit "ENDING HERE"; # last line logged!
239    exit 1;
240}
241
242sub get_host_triplet {
243  my $triplet;
244  my $configfile = "$pwd/$build/lib/curl_config.h";
245
246  if(-f $configfile && -s $configfile && open(my $libconfigh, "<", "$configfile")) {
247    while(<$libconfigh>) {
248      if($_ =~ /^\#define\s+OS\s+"*([^"][^"]*)"*\s*/) {
249        $triplet = $1;
250        last;
251      }
252    }
253    close($libconfigh);
254  }
255  return $triplet;
256}
257
258if($name && $email && $desc) {
259  # having these fields set are enough to continue, skip reading the setup
260  # file
261  $infixed=4;
262  $fixed=4;
263}
264elsif (open(my $f, "<", "$setupfile")) {
265  while (<$f>) {
266    if (/(\w+)=(.*)/) {
267      eval "\$$1=$2;";
268    }
269  }
270  close($f);
271  $infixed=$fixed;
272}
273else {
274  $infixed=0;    # so that "additional args to configure" works properly first time...
275}
276
277if (!$name) {
278  print "please enter your name\n";
279  $name = <>;
280  chomp $name;
281  $fixed=1;
282}
283
284if (!$email) {
285  print "please enter your contact email address\n";
286  $email = <>;
287  chomp $email;
288  $fixed=2;
289}
290
291if (!$desc) {
292  print "please enter a one line system description\n";
293  $desc = <>;
294  chomp $desc;
295  $fixed=3;
296}
297
298if (!$confopts) {
299  if ($infixed < 4) {
300    print "please enter your additional arguments to configure\n";
301    print "examples: --with-openssl --enable-debug --enable-ipv6\n";
302    $confopts = <>;
303    chomp $confopts;
304  }
305}
306
307
308if ($fixed < 4) {
309    $fixed=4;
310    open(my $f, ">", "$setupfile") or die;
311    print $f "name='$name'\n";
312    print $f "email='$email'\n";
313    print $f "desc='$desc'\n";
314    print $f "confopts='$confopts'\n";
315    print $f "notes='$notes'\n";
316    print $f "fixed='$fixed'\n";
317    close($f);
318}
319
320# Enable picky compiler warnings unless explicitly disabled
321if (($confopts !~ /--enable-debug/) &&
322    ($confopts !~ /--enable-warnings/) &&
323    ($confopts !~ /--disable-warnings/)) {
324  $confopts .= " --enable-warnings";
325}
326
327my $str1066os = 'o' x 1066;
328
329# Set timestamp to the UTC this script is running. Its value might
330# be changed later in the script to the value present in curlver.h
331$timestamp = scalar(gmtime)." UTC";
332
333logit "STARTING HERE"; # first line logged, for scripts to trigger on
334logit 'TRANSFER CONTROL ==== 1120 CHAR LINE' . $str1066os . 'LINE_END';
335logit "NAME = $name";
336logit "EMAIL = $email";
337logit "DESC = $desc";
338logit "NOTES = $notes";
339logit "CONFOPTS = $confopts";
340logit "RUNTESTOPTS = ".$runtestopts;
341logit "CPPFLAGS = ".$ENV{CPPFLAGS};
342logit "CFLAGS = ".$ENV{CFLAGS};
343logit "LDFLAGS = ".$ENV{LDFLAGS};
344logit "LIBS = ".$ENV{LIBS};
345logit "CC = ".$ENV{CC};
346logit "TMPDIR = ".$ENV{TMPDIR};
347logit "MAKEFLAGS = ".$ENV{MAKEFLAGS};
348logit "ACLOCAL_FLAGS = ".$ENV{ACLOCAL_FLAGS};
349logit "PKG_CONFIG_PATH = ".$ENV{PKG_CONFIG_PATH};
350logit "DYLD_LIBRARY_PATH = ".$ENV{DYLD_LIBRARY_PATH};
351logit "LD_LIBRARY_PATH = ".$ENV{LD_LIBRARY_PATH};
352logit "LIBRARY_PATH = ".$ENV{LIBRARY_PATH};
353logit "SHLIB_PATH = ".$ENV{SHLIB_PATH};
354logit "LIBPATH = ".$ENV{LIBPATH};
355logit "target = ".$targetos;
356logit "version = $version"; # script version
357logit "date = $timestamp";  # When the test build starts
358
359$str1066os = undef;
360
361# Make $pwd to become the path without newline. We'll use that in order to cut
362# off that path from all possible logs and error messages etc.
363$pwd = getcwd();
364
365my $have_embedded_ares = 0;
366
367if (-d $CURLDIR) {
368  if ($git && -d "$CURLDIR/.git") {
369    logit "$CURLDIR is verified to be a fine git source dir";
370    # remove the generated sources to force them to be re-generated each
371    # time we run this test
372    unlink "$CURLDIR/src/tool_hugehelp.c";
373    # find out if curl source dir has an in-tree c-ares repo
374    $have_embedded_ares = 1 if (-f "$CURLDIR/ares/GIT-INFO");
375  } elsif (!$git && -f "$CURLDIR/tests/testcurl.pl") {
376    logit "$CURLDIR is verified to be a fine daily source dir";
377    # find out if curl source dir has an in-tree c-ares extracted tarball
378    $have_embedded_ares = 1 if (-f "$CURLDIR/ares/ares_build.h");
379  } else {
380    mydie "$CURLDIR is not a daily source dir or checked out from git!"
381  }
382}
383
384# make the path absolute so we can use it everywhere
385$CURLDIR = File::Spec->rel2abs("$CURLDIR");
386
387$build="build-$$";
388$buildlogname="buildlog-$$";
389$buildlog="$pwd/$buildlogname";
390
391# remove any previous left-overs
392rmtree "build-*";
393rmtree "buildlog-*";
394
395# this is to remove old build logs that ended up in the wrong dir
396foreach (glob("$CURLDIR/buildlog-*")) { unlink $_; }
397
398# create a dir to build in
399mkdir $build, 0777;
400
401if (-d $build) {
402  logit "build dir $build was created fine";
403} else {
404  mydie "failed to create dir $build";
405}
406
407# get in the curl source tree root
408chdir $CURLDIR;
409
410# Do the git thing, or not...
411if ($git) {
412  my $gitstat = 0;
413  my @commits;
414
415  # update quietly to the latest git
416  if($nogitpull) {
417    logit "skipping git pull (--nogitpull)";
418  } else {
419    logit "run git pull in curl";
420    system("git pull 2>&1");
421    $gitstat += $?;
422    logit "failed to update from curl git ($?), continue anyway" if ($?);
423
424    # Set timestamp to the UTC the git update took place.
425    $timestamp = scalar(gmtime)." UTC" if (!$gitstat);
426  }
427
428  # get the last 5 commits for show (even if no pull was made)
429  @commits=`git log --pretty=oneline --abbrev-commit -5`;
430  logit "The most recent curl git commits:";
431  for (@commits) {
432    chomp ($_);
433    logit "  $_";
434  }
435
436  if (-d "ares/.git") {
437    chdir "ares";
438
439    if($nogitpull) {
440      logit "skipping git pull (--nogitpull) in ares";
441    } else {
442      logit "run git pull in ares";
443      system("git pull 2>&1");
444      $gitstat += $?;
445      logit "failed to update from ares git ($?), continue anyway" if ($?);
446
447      # Set timestamp to the UTC the git update took place.
448      $timestamp = scalar(gmtime)." UTC" if (!$gitstat);
449    }
450
451    # get the last 5 commits for show (even if no pull was made)
452    @commits=`git log --pretty=oneline --abbrev-commit -5`;
453    logit "The most recent ares git commits:";
454    for (@commits) {
455      chomp ($_);
456      logit "  $_";
457    }
458
459    chdir "$CURLDIR";
460  }
461
462  if($nobuildconf) {
463    logit "told to not run buildconf";
464  }
465  elsif ($configurebuild) {
466    # remove possible left-overs from the past
467    unlink "configure";
468    unlink "autom4te.cache";
469
470    # generate the build files
471    logit "invoke autoreconf";
472    open(my $f, "-|", "autoreconf -fi 2>&1") or die;
473    open(my $log, ">", "$buildlog") or die;
474    while (<$f>) {
475      my $ll = $_;
476      print $ll;
477      print $log $ll;
478    }
479    close($f);
480    close($log);
481
482    logit "buildconf was successful";
483  }
484  else {
485    logit "buildconf was successful (dummy message)";
486  }
487}
488
489# Set timestamp to the one in curlver.h if this isn't a git test build.
490if ((-f "include/curl/curlver.h") &&
491    (open(my $f, "<", "include/curl/curlver.h"))) {
492  while (<$f>) {
493    chomp;
494    if ($_ =~ /^\#define\s+LIBCURL_TIMESTAMP\s+\"(.+)\".*$/) {
495      my $stampstring = $1;
496      if ($stampstring !~ /DEV/) {
497          $stampstring =~ s/\s+UTC//;
498          $timestamp = $stampstring." UTC";
499      }
500      last;
501    }
502  }
503  close($f);
504}
505
506# Show timestamp we are using for this test build.
507logit "timestamp = $timestamp";
508
509if ($configurebuild) {
510  if (-f "configure") {
511    logit "configure created (at least it exists)";
512  } else {
513    mydie "no configure created/found";
514  }
515} else {
516  logit "configure created (dummy message)"; # dummy message to feign success
517}
518
519sub findinpath {
520  my $c;
521  my $e;
522  my $x = ($^O eq 'MSWin32') ? '.exe' : '';
523  my $s = ($^O eq 'MSWin32') ? ';' : ':';
524  my $p=$ENV{'PATH'};
525  my @pa = split($s, $p);
526  for $c (@_) {
527    for $e (@pa) {
528      if( -x "$e/$c$x") {
529        return $c;
530      }
531    }
532  }
533}
534
535my $make = findinpath("gmake", "make", "nmake");
536if(!$make) {
537    mydie "Couldn't find make in the PATH";
538}
539# force to 'nmake' for VC builds
540$make = "nmake" if ($targetos =~ /vc/);
541logit "going with $make as make";
542
543# change to build dir
544chdir "$pwd/$build";
545
546if ($configurebuild) {
547  # run configure script
548  print `$CURLDIR/configure $confopts 2>&1`;
549
550  if (-f "lib/Makefile") {
551    logit "configure seems to have finished fine";
552  } else {
553    mydie "configure didn't work";
554  }
555} else {
556  logit "copying files to build dir ...";
557  if ($^O eq 'MSWin32') {
558    system("xcopy /s /q \"$CURLDIR\" .");
559    system("buildconf.bat");
560  }
561  elsif ($^O eq 'linux') {
562    system("cp -afr $CURLDIR/* .");
563    system("cp -af $CURLDIR/Makefile.dist Makefile");
564    system("$make -i -C lib -f Makefile.$targetos prebuild");
565    system("$make -i -C src -f Makefile.$targetos prebuild");
566    if (-d "$CURLDIR/ares") {
567      system("cp -af $CURLDIR/ares/ares_build.h.dist ./ares/ares_build.h");
568      system("$make -i -C ares -f Makefile.$targetos prebuild");
569    }
570  }
571}
572
573if(-f "./libcurl.pc") {
574  logit_spaced "display libcurl.pc";
575  if(open(my $f, "<", "libcurl.pc")) {
576    while(<$f>) {
577      my $ll = $_;
578      print $ll if(($ll !~ /^ *#/) && ($ll !~ /^ *$/));
579    }
580    close($f);
581  }
582}
583
584logit_spaced "display lib/$confheader";
585open(my $f, "<", "lib/$confheader") or die "lib/$confheader: $!";
586while (<$f>) {
587  print if /^ *#/;
588}
589close($f);
590
591if (($have_embedded_ares) &&
592    (grepfile("^#define USE_ARES", "lib/$confheader"))) {
593  print "\n";
594  logit "setup to build ares";
595
596  if(-f "./ares/libcares.pc") {
597    logit_spaced  "display ares/libcares.pc";
598    if(open($f, "<", "ares/libcares.pc")) {
599      while(<$f>) {
600        my $ll = $_;
601        print $ll if(($ll !~ /^ *#/) && ($ll !~ /^ *$/));
602      }
603      close($f);
604    }
605  }
606
607  if(-f "./ares/ares_build.h") {
608    logit_spaced "display ares/ares_build.h";
609    if(open($f, "<", "ares/ares_build.h")) {
610      while(<$f>) {
611        my $ll = $_;
612        print $ll if(($ll =~ /^ *# *define *CARES_/) && ($ll !~ /__CARES_BUILD_H/));
613      }
614      close($f);
615    }
616  }
617  else {
618    mydie "no ares_build.h created/found";
619  }
620
621  $confheader =~ s/curl/ares/;
622  logit_spaced "display ares/$confheader";
623  if(open($f, "<", "ares/$confheader")) {
624      while (<$f>) {
625          print if /^ *#/;
626      }
627      close($f);
628  }
629
630  print "\n";
631  logit "build ares";
632  chdir "ares";
633
634  if ($targetos && !$configurebuild) {
635      logit "$make -f Makefile.$targetos";
636      open($f, "-|", "$make -f Makefile.$targetos 2>&1") or die;
637  }
638  else {
639      logit "$make";
640      open($f, "-|", "$make 2>&1") or die;
641  }
642  while (<$f>) {
643    s/$pwd//g;
644    print;
645  }
646  close($f);
647
648  if (-f "libcares$libext") {
649    logit "ares is now built successfully (libcares$libext)";
650  } else {
651    mydie "ares build failed (libcares$libext)";
652  }
653
654  # cd back to the curl build dir
655  chdir "$pwd/$build";
656}
657
658my $mkcmd = "$make -i" . ($targetos && !$configurebuild ? " $targetos" : "");
659logit "$mkcmd";
660open(my $f, "-|", "$mkcmd 2>&1") or die;
661while (<$f>) {
662  s/$pwd//g;
663  print;
664}
665close($f);
666
667if (-f "lib/libcurl$libext") {
668  logit "libcurl was created fine (libcurl$libext)";
669}
670else {
671  mydie "libcurl was not created (libcurl$libext)";
672}
673
674if (-f "src/curl$binext") {
675  logit "curl was created fine (curl$binext)";
676}
677else {
678  mydie "curl was not created (curl$binext)";
679}
680
681if (!$crosscompile || (($extvercmd ne '') && (-x $extvercmd))) {
682  logit "display curl${binext} --version output";
683  my $cmd = ($extvercmd ne '' ? $extvercmd.' ' : '')."./src/curl${binext} --version|";
684  open($f, "<", $cmd);
685  while(<$f>) {
686    # strip CR from output on non-win32 platforms (wine on Linux)
687    s/\r// if ($^O ne 'MSWin32');
688    print;
689  }
690  close($f);
691}
692
693if ($configurebuild && !$crosscompile) {
694  my $host_triplet = get_host_triplet();
695  # build example programs for selected build targets
696  if(($host_triplet =~ /([^-]+)-([^-]+)-irix(.*)/) ||
697     ($host_triplet =~ /([^-]+)-([^-]+)-aix(.*)/) ||
698     ($host_triplet =~ /([^-]+)-([^-]+)-osf(.*)/) ||
699     ($host_triplet =~ /([^-]+)-([^-]+)-solaris2(.*)/)) {
700    chdir "$pwd/$build/docs/examples";
701    logit_spaced "build examples";
702    open($f, "-|", "$make -i 2>&1") or die;
703    open(my $log, ">", "$buildlog") or die;
704    while (<$f>) {
705      s/$pwd//g;
706      print;
707      print $log $_;
708    }
709    close($f);
710    close($log);
711    chdir "$pwd/$build";
712  }
713  # build and run full test suite
714  my $o;
715  if($runtestopts) {
716      $o = "TEST_F=\"$runtestopts\" ";
717  }
718  logit "$make -k ${o}test-full";
719  open($f, "-|", "$make -k ${o}test-full 2>&1") or die;
720  open(my $log, ">", "$buildlog") or die;
721  while (<$f>) {
722    s/$pwd//g;
723    print;
724    print $log $_;
725  }
726  close($f);
727  close($log);
728
729  if (grepfile("^TEST", $buildlog)) {
730    logit "tests were run";
731  } else {
732    mydie "test suite failure";
733  }
734
735  if (grepfile("^TESTFAIL:", $buildlog)) {
736    logit "the tests were not successful";
737  } else {
738    logit "the tests were successful!";
739  }
740}
741else {
742  if($crosscompile) {
743    my $host_triplet = get_host_triplet();
744    # build example programs for selected cross-compiles
745    if(($host_triplet =~ /([^-]+)-([^-]+)-mingw(.*)/) ||
746       ($host_triplet =~ /([^-]+)-([^-]+)-android(.*)/)) {
747      chdir "$pwd/$build/docs/examples";
748      logit_spaced "build examples";
749      open($f, "-|", "$make -i 2>&1") or die;
750      open(my $log, ">", "$buildlog") or die;
751      while (<$f>) {
752        s/$pwd//g;
753        print;
754        print $log $_;
755      }
756      close($f);
757      close($log);
758      chdir "$pwd/$build";
759    }
760    # build test harness programs for selected cross-compiles
761    if($host_triplet =~ /([^-]+)-([^-]+)-mingw(.*)/) {
762      chdir "$pwd/$build/tests";
763      logit_spaced "build test harness";
764      open(my $f, "-|", "$make -i 2>&1") or die;
765      open(my $log, ">", "$buildlog") or die;
766      while (<$f>) {
767        s/$pwd//g;
768        print;
769        print $log $_;
770      }
771      close($f);
772      close($log);
773      chdir "$pwd/$build";
774    }
775    logit_spaced "cross-compiling, can't run tests";
776  }
777  # dummy message to feign success
778  print "TESTDONE: 1 tests out of 0 (dummy message)\n";
779}
780
781# create a tarball if we got that option.
782if (($mktarball ne '') && (-x $mktarball)) {
783  system($mktarball);
784}
785
786# mydie to cleanup
787mydie "ending nicely";
788