[PATCH] testbot/build: Move the common build functions to Build::Utils.

Francois Gouget fgouget at codeweavers.com
Wed Aug 22 03:18:58 CDT 2018


This reduces the build scripts code duplication.
A side-effect is that the status lines now all start with the 'Task:'
prefix.

Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
 testbot/bin/build/Build.pl        |  89 +-------
 testbot/bin/build/Reconfig.pl     | 113 +---------
 testbot/bin/build/WineReconfig.pl | 247 ++------------------
 testbot/bin/build/WineTest.pl     | 111 +--------
 testbot/lib/Build/Utils.pm        | 363 ++++++++++++++++++++++++++++++
 5 files changed, 409 insertions(+), 514 deletions(-)
 create mode 100644 testbot/lib/Build/Utils.pm

diff --git a/testbot/bin/build/Build.pl b/testbot/bin/build/Build.pl
index e1133aaee..7f94c8595 100755
--- a/testbot/bin/build/Build.pl
+++ b/testbot/bin/build/Build.pl
@@ -43,98 +43,23 @@ sub BEGIN
   }
   $::BuildEnv = 1;
 }
-my $Name0 = $0;
-$Name0 =~ s+^.*/++;
-
 
+use Build::Utils;
 use WineTestBot::Config;
-use WineTestBot::PatchUtils;
 use WineTestBot::Utils;
 
 
-#
-# Logging and error handling helpers
-#
-
-sub InfoMsg(@)
-{
-  print @_;
-}
-
-sub LogMsg(@)
-{
-  print "Build: ", @_;
-}
-
-sub Error(@)
-{
-  print STDERR "$Name0:error: ", @_;
-}
-
-
 #
 # Build helpers
 #
 
-my $ncpus;
-sub CountCPUs()
-{
-  if (open(my $fh, "<", "/proc/cpuinfo"))
-  {
-    # Linux
-    map { $ncpus++ if (/^processor/); } <$fh>;
-    close($fh);
-  }
-  $ncpus ||= 1;
-}
-
-sub ApplyPatch($)
-{
-  my ($PatchFile) = @_;
-
-  InfoMsg "Applying patch\n";
-  system("cd '$DataDir/wine' && ".
-         "echo wine:HEAD=`git rev-parse HEAD` && ".
-         "set -x && ".
-         "git apply --verbose ". ShQuote($PatchFile) ." && ".
-         "git add -A");
-  if ($? != 0)
-  {
-    LogMsg "Patch failed to apply\n";
-    return undef;
-  }
-
-  my $Impacts = GetPatchImpact($PatchFile, "nounits");
-  if ($Impacts->{MakeMakefiles})
-  {
-    InfoMsg "\nRunning make_makefiles\n";
-    system("cd '$DataDir/wine' && set -x && ./tools/make_makefiles");
-    if ($? != 0)
-    {
-      LogMsg "make_makefiles failed\n";
-      return undef;
-    }
-  }
-
-  if ($Impacts->{Autoconf} && !$Impacts->{HasConfigure})
-  {
-    InfoMsg "\nRunning autoconf\n";
-    system("cd '$DataDir/wine' && set -x && autoconf");
-    if ($? != 0)
-    {
-      LogMsg "Autoconf failed\n";
-      return undef;
-    }
-  }
-
-  return $Impacts;
-}
 
 sub BuildNative()
 {
   InfoMsg "\nRebuilding native tools\n";
+  my $CPUCount = GetCPUCount();
   system("cd '$DataDir/build-native' && set -x && ".
-         "time make -j$ncpus __tooldeps__");
+         "time make -j$CPUCount __tooldeps__");
   if ($? != 0)
   {
     LogMsg "Rebuild of native tools failed\n";
@@ -160,8 +85,9 @@ sub BuildTestExecutables($$$)
   }
 
   InfoMsg "\nBuilding the $Bits-bit test executable(s)\n";
+  my $CPUCount = GetCPUCount();
   system("cd '$DataDir/build-mingw$Bits' && set -x && ".
-         "time make -j$ncpus ". join(" ", sort @BuildDirs));
+         "time make -j$CPUCount ". join(" ", sort @BuildDirs));
   if ($? != 0)
   {
     LogMsg "Rebuild of $Bits-bit crossbuild failed\n";
@@ -262,6 +188,7 @@ if (!defined $Usage)
 }
 if (defined $Usage)
 {
+  my $Name0 = GetToolName();
   if ($Usage)
   {
     Error "try '$Name0 --help' for more information\n";
@@ -292,9 +219,7 @@ if ($DataDir =~ /'/)
 # Run the builds
 #
 
-CountCPUs();
-
-my $Impacts = ApplyPatch($PatchFile);
+my $Impacts = ApplyPatch("wine", $PatchFile);
 
 if (!$Impacts or
     ($Impacts->{WineBuild} and !BuildNative()) or
diff --git a/testbot/bin/build/Reconfig.pl b/testbot/bin/build/Reconfig.pl
index 4aada3242..36748d66e 100755
--- a/testbot/bin/build/Reconfig.pl
+++ b/testbot/bin/build/Reconfig.pl
@@ -39,112 +39,15 @@ sub BEGIN
   }
   $::BuildEnv = 1;
 }
-my $Name0 = $0;
-$Name0 =~ s+^.*/++;
-
 
+use Build::Utils;
 use WineTestBot::Config;
-use WineTestBot::PatchUtils;
-
-
-#
-# Logging and error handling helpers
-#
-
-sub InfoMsg(@)
-{
-  print @_;
-}
-
-sub LogMsg(@)
-{
-  print "Reconfig: ", @_;
-}
-
-sub Error(@)
-{
-  print STDERR "$Name0:error: ", @_;
-}
 
 
 #
 # Build helpers
 #
 
-my $ncpus;
-sub CountCPUs()
-{
-  if (open(my $fh, "<", "/proc/cpuinfo"))
-  {
-    # Linux
-    map { $ncpus++ if (/^processor/); } <$fh>;
-    close($fh);
-  }
-  $ncpus ||= 1;
-}
-
-sub BuildTestAgentd()
-{
-  # If testagentd already exists it's likely already running
-  # so don't rebuild it.
-  if (! -x "$BinDir/build/testagentd")
-  {
-    InfoMsg "\nBuilding the native testagentd\n";
-    system("cd '$::RootDir/src/testagentd' && set -x && ".
-           "time make -j$ncpus build");
-    if ($? != 0)
-    {
-      LogMsg "Build testagentd failed\n";
-      return !1;
-    }
-  }
-
-  InfoMsg "\nRebuilding the Windows TestAgentd\n";
-  system("cd '$::RootDir/src/testagentd' && set -x && ".
-         "time make -j$ncpus iso");
-  if ($? != 0)
-  {
-    LogMsg "Build winetestbot.iso failed\n";
-    return !1;
-  }
-
-  return 1;
-}
-
-sub BuildTestLauncher()
-{
-  InfoMsg "\nRebuilding TestLauncher\n";
-  system("cd '$::RootDir/src/TestLauncher' && set -x && ".
-         "time make -j$ncpus");
-  if ($? != 0)
-  {
-    LogMsg "Build TestLauncher failed\n";
-    return !1;
-  }
-
-  return 1;
-}
-
-sub GitPull()
-{
-  InfoMsg "\nUpdating the Wine source\n";
-  system("cd '$DataDir/wine' && git pull");
-  if ($? != 0)
-  {
-    LogMsg "Git pull failed\n";
-    return !1;
-  }
-
-  my $ErrMessage = UpdateWineData("$DataDir/wine");
-  if ($ErrMessage)
-  {
-    LogMsg "$ErrMessage\n";
-    return !1;
-  }
-
-  return 1;
-}
-
 sub BuildNative($)
 {
   my ($NoRm) = @_;
@@ -153,10 +56,11 @@ sub BuildNative($)
 
   # Rebuild from scratch to make sure cruft will not accumulate
   InfoMsg "\nRebuilding native tools\n";
+  my $CPUCount = GetCPUCount();
   system("cd '$DataDir/build-native' && set -x && ".
          ($NoRm ? "" : "rm -rf * && ") .
          "time ../wine/configure --enable-win64 --without-x --without-freetype --disable-winetest && ".
-         "time make -j$ncpus __tooldeps__");
+         "time make -j$CPUCount __tooldeps__");
 
   if ($? != 0)
   {
@@ -176,11 +80,12 @@ sub BuildCross($$$)
 
   # Rebuild from scratch to make sure cruft will not accumulate
   InfoMsg "\nRebuilding the $Bits-bit test executables\n";
+  my $CPUCount = GetCPUCount();
   my $Host = ($Bits == 64 ? "x86_64-w64-mingw32" : "i686-w64-mingw32");
   system("cd '$DataDir/build-mingw$Bits' && set -x && ".
          ($NoRm ? "" : "rm -rf * && ") .
          "time ../wine/configure --host=$Host --with-wine-tools=../build-native --without-x --without-freetype --disable-winetest && ".
-         "time make -j$ncpus buildtests");
+         "time make -j$CPUCount buildtests");
   if ($? != 0)
   {
     LogMsg "Build cross ($Bits bits) failed\n";
@@ -271,6 +176,7 @@ if (!defined $Usage)
 }
 if (defined $Usage)
 {
+  my $Name0 = GetToolName();
   if ($Usage)
   {
     Error "try '$Name0 --help' for more information\n";
@@ -308,10 +214,9 @@ if (! -d "$DataDir/staging" and ! mkdir "$DataDir/staging")
 # Run the builds
 #
 
-CountCPUs();
-
-exit(1) if (!BuildTestAgentd() or !BuildTestLauncher());
-exit(1) if ($OptUpdate and !GitPull());
+exit(1) if (!BuildNativeTestAgentd() or !BuildWindowsTestAgentd());
+exit(1) if (!BuildTestLauncher());
+exit(1) if ($OptUpdate and !GitPull("wine"));
 exit(1) if ($OptBuild and !UpdateWineBuilds($Targets, $OptNoRm));
 
 LogMsg "ok\n";
diff --git a/testbot/bin/build/WineReconfig.pl b/testbot/bin/build/WineReconfig.pl
index 77722734c..b30ddd190 100755
--- a/testbot/bin/build/WineReconfig.pl
+++ b/testbot/bin/build/WineReconfig.pl
@@ -36,92 +36,15 @@ sub BEGIN
   }
   $::BuildEnv = 1;
 }
-my $Name0 = $0;
-$Name0 =~ s+^.*/++;
-
-
-use Digest::SHA;
-use File::Path;
 
+use Build::Utils;
 use WineTestBot::Config;
-use WineTestBot::PatchUtils;
-
-
-#
-# Logging and error handling helpers
-#
-
-sub InfoMsg(@)
-{
-  print @_;
-}
-
-sub LogMsg(@)
-{
-  print "Reconfig: ", @_;
-}
-
-sub Error(@)
-{
-  print STDERR "$Name0:error: ", @_;
-}
 
 
 #
 # Build helpers
 #
 
-my $ncpus;
-sub CountCPUs()
-{
-  if (open(my $fh, "<", "/proc/cpuinfo"))
-  {
-    # Linux
-    map { $ncpus++ if (/^processor/); } <$fh>;
-    close($fh);
-  }
-  $ncpus ||= 1;
-}
-
-sub BuildTestAgentd()
-{
-  # If testagentd already exists it's likely already running
-  # so don't rebuild it.
-  if (! -x "$BinDir/build/testagentd")
-  {
-    InfoMsg "\nBuilding the native testagentd\n";
-    system("cd '$::RootDir/src/testagentd' && set -x && ".
-           "time make -j$ncpus build");
-    if ($? != 0)
-    {
-      LogMsg "Build testagentd failed\n";
-      return !1;
-    }
-  }
-
-  return 1;
-}
-
-sub GitPull()
-{
-  InfoMsg "\nUpdating the Wine source\n";
-  system("cd '$DataDir/wine' && git pull");
-  if ($? != 0)
-  {
-    LogMsg "Git pull failed\n";
-    return !1;
-  }
-
-  my $ErrMessage = UpdateWineData("$DataDir/wine");
-  if ($ErrMessage)
-  {
-    LogMsg "$ErrMessage\n";
-    return !1;
-  }
-
-  return 1;
-}
-
 sub BuildWine($$$$)
 {
   my ($Targets, $NoRm, $Build, $Extras) = @_;
@@ -132,10 +55,11 @@ sub BuildWine($$$$)
   # If $NoRm is not set, rebuild from scratch to make sure cruft will not
   # accumulate
   InfoMsg "\nRebuilding the $Build Wine\n";
+  my $CPUCount = GetCPUCount();
   system("cd '$DataDir/build-$Build' && set -x && ".
          ($NoRm ? "" : "rm -rf * && ") .
          "time ../wine/configure $Extras && ".
-         "time make -j$ncpus");
+         "time make -j$CPUCount");
   if ($? != 0)
   {
     LogMsg "The $Build build failed\n";
@@ -159,160 +83,30 @@ sub UpdateWineBuilds($$)
 # WinePrefix helpers
 #
 
-sub VerifyAddOn($$)
-{
-  my ($AddOn, $Arch) = @_;
-
-  my $Sha256 = Digest::SHA->new(256);
-  eval { $Sha256->addfile("$DataDir/$AddOn->{name}/$AddOn->{filename}") };
-  return "$@" if ($@);
-
-  my $Checksum = $Sha256->hexdigest();
-  return undef if ($Checksum eq $AddOn->{$Arch});
-  return "Bad checksum for '$AddOn->{filename}'";
-}
-
-sub UpdateAddOn($$$)
+sub UpdateWinePrefixes($)
 {
-  my ($AddOn, $Name, $Arch) = @_;
+  my ($Targets) = @_;
 
-  if (!defined $AddOn)
-  {
-    LogMsg "Could not get information on the $Name addon\n";
-    return 0;
-  }
-  if (!$AddOn->{version})
-  {
-    LogMsg "Could not get the $Name version\n";
-    return 0;
-  }
-  if (!$AddOn->{$Arch})
+  # Set up brand new WinePrefixes ready for use for testing.
+  # This way we do it once instead of doing it for every test, thus saving
+  # time. Note that this requires using a different wineprefix for each build.
+  foreach my $Build ("win32", "wow64", "wow32")
   {
-    LogMsg "Could not get the $Name $Arch checksum\n";
-    return 0;
-  }
-
-  $AddOn->{filename} = "wine". ($Name eq "gecko" ? "_" : "-") .
-                       "$Name-$AddOn->{version}".
-                       ($Arch eq "" ? "" : "-$Arch") .".msi";
-  return 1 if (!VerifyAddOn($AddOn, $Arch));
+    next if (!$Targets->{$Build});
 
-  InfoMsg "Downloading $AddOn->{filename}\n";
-  mkdir "$DataDir/$Name";
-
-  my $Url="http://dl.winehq.org/wine/wine-$Name/$AddOn->{version}/$AddOn->{filename}";
-  for (1..3)
-  {
-    system("cd '$DataDir/$Name' && set -x && ".
-           "wget --no-verbose -O- '$Url' >'$AddOn->{filename}'");
-    last if ($? == 0);
-  }
-  my $ErrMessage = VerifyAddOn($AddOn, $Arch);
-  return 1 if (!defined $ErrMessage);
-  LogMsg "$ErrMessage\n";
-  return 0;
-}
-
-sub UpdateAddOns()
-{
-  my %AddOns;
-  if (open(my $fh, "<", "$DataDir/wine/dlls/appwiz.cpl/addons.c"))
-  {
-    my $Arch = "";
-    while (my $Line= <$fh>)
+    # Wait for the wineprefix creation to complete so it is really done
+    # before the snapshot gets updated.
+    SetupWineEnvironment($Build);
+    my $ErrMessage = CreateWinePrefix($Build, "wait");
+    if (defined $ErrMessage)
     {
-      if ($Line =~ /^\s*#\s*define\s+ARCH_STRING\s+"([^"]+)"/)
-      {
-        $Arch = $1;
-      }
-      elsif ($Line =~ /^\s*#\s*define\s*(GECKO|MONO)_VERSION\s*"([^"]+)"/)
-      {
-        my ($AddOn, $Version) = ($1, $2);
-        $AddOn =~ tr/A-Z/a-z/;
-        $AddOns{$AddOn}->{name} = $AddOn;
-        $AddOns{$AddOn}->{version} = $Version;
-      }
-      elsif ($Line =~ /^\s*#\s*define\s*(GECKO|MONO)_SHA\s*"([^"]+)"/)
-      {
-        my ($AddOn, $Checksum) = ($1, $2);
-        $AddOn =~ tr/A-Z/a-z/;
-        $AddOns{$AddOn}->{$Arch} = $Checksum;
-        $Arch = "";
-      }
+      LogMsg "$ErrMessage\n";
+      return 0;
     }
-    close($fh);
-  }
-  else
-  {
-    LogMsg "Could not open 'wine/dlls/appwiz.cpl/addons.c': $!\n";
-    return 0;
-  }
-
-  return UpdateAddOn($AddOns{gecko}, "gecko", "x86") &&
-         UpdateAddOn($AddOns{gecko}, "gecko", "x86_64") &&
-         UpdateAddOn($AddOns{mono},  "mono",  "");
-}
-
-# See also WineTest.pl
-sub SetupWineEnvironment($)
-{
-  my ($Build) = @_;
-
-  $ENV{WINEPREFIX} = "$DataDir/wineprefix-$Build";
-  $ENV{DISPLAY} ||= ":0.0";
-}
-
-# See also WineTest.pl
-sub RunWine($$$)
-{
-  my ($Build, $Cmd, $CmdArgs) = @_;
-
-  my $Magic = `cd '$DataDir/build-$Build' && file $Cmd`;
-  my $Wine = ($Magic =~ /ELF 64/ ? "./wine64" : "./wine");
-  return system("cd '$DataDir/build-$Build' && set -x && ".
-                "time $Wine $Cmd $CmdArgs");
-}
-
-# Setup a brand new WinePrefix ready for use for testing.
-# This way we do it once instead of doing it for every test, thus saving
-# time. Note that this requires using a different wineprefix for each build.
-sub NewWinePrefix($$)
-{
-  my ($Targets, $Build) = @_;
-
-  return 1 if (!$Targets->{$Build});
-
-  InfoMsg "\nRecreating the $Build wineprefix\n";
-  SetupWineEnvironment($Build);
-  rmtree($ENV{WINEPREFIX});
-
-  # Crash dialogs cause delays so disable them
-  if (RunWine($Build, "./programs/reg/reg.exe.so", "ADD HKCU\\\\Software\\\\Wine\\\\WineDbg /v ShowCrashDialog /t REG_DWORD /d 0"))
-  {
-    LogMsg "Failed to disable the $Build build crash dialogs: $!\n";
-    return 0;
   }
-
-  # Ensure the WinePrefix has been fully created before updating the snapshot
-  system("cd '$DataDir/build-$Build' && ./server/wineserver -w");
-
   return 1;
 }
 
-sub UpdateWinePrefixes($)
-{
-  my ($Targets) = @_;
-
-  return NewWinePrefix($Targets, "win32") &&
-         # The wow32 and wow64 wineprefixes:
-         # - Are essentially identical.
-         # - Must be created after both WoW builds have been updated.
-         # - Make it possible to run the wow32 and wow64 tests in separate
-         #   prefixes, thus ensuring they don't interfere with each other.
-         NewWinePrefix($Targets, "wow64") &&
-         NewWinePrefix($Targets, "wow32");
-}
-
 
 #
 # Setup and command line processing
@@ -393,6 +187,7 @@ if (!defined $Usage)
 }
 if (defined $Usage)
 {
+  my $Name0 = GetToolName();
   if ($Usage)
   {
     Error "try '$Name0 --help' for more information\n";
@@ -436,10 +231,8 @@ if ($DataDir =~ /'/)
 # Run the builds and/or tests
 #
 
-CountCPUs();
-
-exit(1) if (!BuildTestAgentd());
-exit(1) if ($OptUpdate and !GitPull());
+exit(1) if (!BuildNativeTestAgentd());
+exit(1) if ($OptUpdate and !GitPull("wine"));
 exit(1) if ($OptAddOns and !UpdateAddOns());
 exit(1) if ($OptBuild and !UpdateWineBuilds($Targets, $OptNoRm));
 exit(1) if ($OptWinePrefix and !UpdateWinePrefixes($Targets));
diff --git a/testbot/bin/build/WineTest.pl b/testbot/bin/build/WineTest.pl
index b29440e21..9c264b485 100755
--- a/testbot/bin/build/WineTest.pl
+++ b/testbot/bin/build/WineTest.pl
@@ -40,93 +40,16 @@ sub BEGIN
   }
   $::BuildEnv = 1;
 }
-my $Name0 = $0;
-$Name0 =~ s+^.*/++;
-
 
+use Build::Utils;
 use WineTestBot::Config;
-use WineTestBot::PatchUtils;
 use WineTestBot::Utils;
 
 
-#
-# Logging and error handling helpers
-#
-
-sub InfoMsg(@)
-{
-  print @_;
-}
-
-sub LogMsg(@)
-{
-  print "Task: ", @_;
-}
-
-sub Error(@)
-{
-  print STDERR "$Name0:error: ", @_;
-}
-
-
 #
 # Build helpers
 #
 
-my $ncpus;
-sub CountCPUs()
-{
-  if (open(my $fh, "<", "/proc/cpuinfo"))
-  {
-    # Linux
-    map { $ncpus++ if (/^processor/); } <$fh>;
-    close($fh);
-  }
-  $ncpus ||= 1;
-}
-
-sub ApplyPatch($)
-{
-  my ($PatchFile) = @_;
-
-  InfoMsg "Applying patch\n";
-  system("cd '$DataDir/wine' && ".
-         "echo wine:HEAD=`git rev-parse HEAD` && ".
-         "set -x && ".
-         "git apply --verbose ". ShQuote($PatchFile) ." && ".
-         "git add -A");
-  if ($? != 0)
-  {
-    LogMsg "Patch failed to apply\n";
-    return undef;
-  }
-
-  my $Impacts = GetPatchImpact($PatchFile, "nounits");
-  if ($Impacts->{MakeMakefiles})
-  {
-    InfoMsg "\nRunning make_makefiles\n";
-    system("cd '$DataDir/wine' && set -x && ./tools/make_makefiles");
-    if ($? != 0)
-    {
-      LogMsg "make_makefiles failed\n";
-      return undef;
-    }
-  }
-
-  if ($Impacts->{Autoconf} && !$Impacts->{HasConfigure})
-  {
-    InfoMsg "\nRunning autoconf\n";
-    system("cd '$DataDir/wine' && set -x && autoconf");
-    if ($? != 0)
-    {
-      LogMsg "Autoconf failed\n";
-      return undef;
-    }
-  }
-
-  return $Impacts;
-}
-
 sub BuildWine($$)
 {
   my ($Targets, $Build) = @_;
@@ -134,8 +57,9 @@ sub BuildWine($$)
   return 1 if (!$Targets->{$Build});
 
   InfoMsg "\nRebuilding the $Build Wine\n";
+  my $CPUCount = GetCPUCount();
   system("cd '$DataDir/build-$Build' && set -x && ".
-         "time make -j$ncpus");
+         "time make -j$CPUCount");
   if ($? != 0)
   {
     LogMsg "The $Build build failed\n";
@@ -150,25 +74,6 @@ sub BuildWine($$)
 # Test helpers
 #
 
-# See also WineReconfig.pl
-sub SetupWineEnvironment($)
-{
-  my ($Build) = @_;
-
-  $ENV{WINEPREFIX} = "$DataDir/wineprefix-$Build";
-  $ENV{DISPLAY} ||= ":0.0";
-}
-
-# See also WineReconfig.pl
-sub RunWine($$$)
-{
-  my ($Build, $Cmd, $CmdArgs) = @_;
-
-  my $Magic = `cd '$DataDir/build-$Build' && file $Cmd`;
-  my $Wine = ($Magic =~ /ELF 64/ ? "./wine64" : "./wine");
-  return system("cd '$DataDir/build-$Build' && set -x && ".
-                "time $Wine $Cmd $CmdArgs");
-}
 
 sub DailyWineTest($$$$$)
 {
@@ -330,6 +235,12 @@ if (!defined $Usage)
 }
 if (defined $Usage)
 {
+  my $Name0 = GetToolName();
+  if ($Usage)
+  {
+    Error "try '$Name0 --help' for more information\n";
+    exit $Usage;
+  }
   print "Usage: $Name0 [--help] --testpatch TARGETS PATCH\n";
   print "or     $Name0 [--help] --winetest [--no-submit] TARGETS BASETAG ARGS\n";
   print "\n";
@@ -365,11 +276,9 @@ if ($DataDir =~ /'/)
 # Clean up old reports
 map { unlink("$_.report") } keys %AllTargets;
 
-CountCPUs();
-
 if ($Action eq "testpatch")
 {
-  my $Impacts = ApplyPatch($FileName);
+  my $Impacts = ApplyPatch("wine", $FileName);
   exit(1) if (!$Impacts or
               !BuildWine($Targets, "win32") or
               !BuildWine($Targets, "wow64") or
diff --git a/testbot/lib/Build/Utils.pm b/testbot/lib/Build/Utils.pm
new file mode 100644
index 000000000..038c188f2
--- /dev/null
+++ b/testbot/lib/Build/Utils.pm
@@ -0,0 +1,363 @@
+# -*- Mode: Perl; perl-indent-level: 2; indent-tabs-mode: nil -*-
+# Copyright 2018 Francois Gouget
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
+use strict;
+
+package Build::Utils;
+
+=head1 NAME
+
+Build::Utils - Utility functions for the build scripts
+
+=cut
+
+use Exporter 'import';
+our @EXPORT = qw(GetToolName InfoMsg LogMsg Error
+                 GitPull ApplyPatch
+                 GetCPUCount BuildNativeTestAgentd BuildWindowsTestAgentd
+                 BuildTestLauncher UpdateAddOns
+                 SetupWineEnvironment RunWine CreateWinePrefix);
+
+use Digest::SHA;
+use File::Path;
+
+use WineTestBot::Config;
+use WineTestBot::PatchUtils;
+use WineTestBot::Utils;
+
+
+#
+# Logging and error handling
+#
+
+my $Name0 = $0;
+$Name0 =~ s+^.*/++;
+
+sub GetToolName()
+{
+  return $Name0;
+}
+
+sub InfoMsg(@)
+{
+  print @_;
+}
+
+sub LogMsg(@)
+{
+  print "Task: ", @_;
+}
+
+sub Error(@)
+{
+  print STDERR "$Name0:error: ", @_;
+}
+
+
+#
+# Repository updates
+#
+
+sub GitPull($)
+{
+  my ($Dir) = @_;
+
+  InfoMsg "\nUpdating the $Dir source\n";
+  system("cd '$DataDir/$Dir' && git pull");
+  if ($? != 0)
+  {
+    LogMsg "Git pull failed\n";
+    return !1;
+  }
+
+  if ($Dir eq "wine")
+  {
+    my $ErrMessage = UpdateWineData("$DataDir/$Dir");
+    if ($ErrMessage)
+    {
+      LogMsg "$ErrMessage\n";
+      return !1;
+    }
+  }
+
+  return 1;
+}
+
+sub ApplyPatch($$)
+{
+  my ($Dir, $PatchFile) = @_;
+
+  InfoMsg "Applying patch\n";
+  system("cd '$DataDir/$Dir' && ".
+         "echo $Dir:HEAD=`git rev-parse HEAD` && ".
+         "set -x && ".
+         "git apply --verbose ". ShQuote($PatchFile) ." && ".
+         "git add -A");
+  if ($? != 0)
+  {
+    LogMsg "Patch failed to apply\n";
+    return undef;
+  }
+
+  my $Impacts = GetPatchImpact($PatchFile, "nounits");
+  if ($Impacts->{MakeMakefiles})
+  {
+    InfoMsg "\nRunning make_makefiles\n";
+    system("cd '$DataDir/$Dir' && set -x && ./tools/make_makefiles");
+    if ($? != 0)
+    {
+      LogMsg "make_makefiles failed\n";
+      return undef;
+    }
+  }
+
+  if ($Impacts->{Autoconf} && !$Impacts->{HasConfigure})
+  {
+    InfoMsg "\nRunning autoconf\n";
+    system("cd '$DataDir/$Dir' && set -x && autoconf");
+    if ($? != 0)
+    {
+      LogMsg "Autoconf failed\n";
+      return undef;
+    }
+  }
+
+  return $Impacts;
+}
+
+
+#
+# Build helpers
+#
+
+my $_CPUCount;
+
+sub GetCPUCount()
+{
+  if (!defined $_CPUCount)
+  {
+    if (open(my $Fh, "<", "/proc/cpuinfo"))
+    {
+      # Linux
+      map { $_CPUCount++ if (/^processor/); } <$Fh>;
+      close($Fh);
+    }
+    $_CPUCount ||= 1;
+  }
+  return $_CPUCount;
+}
+
+sub BuildNativeTestAgentd()
+{
+  # If testagentd already exists it's likely already running
+  # so don't rebuild it.
+  return 1 if (-x "$BinDir/build/testagentd");
+
+  InfoMsg "\nBuilding the native testagentd\n";
+  my $CPUCount = GetCPUCount();
+  system("cd '$::RootDir/src/testagentd' && set -x && ".
+         "time make -j$CPUCount build");
+  if ($? != 0)
+  {
+    LogMsg "Build testagentd failed\n";
+    return !1;
+  }
+
+  return 1;
+}
+
+sub BuildWindowsTestAgentd()
+{
+  InfoMsg "\nRebuilding the Windows TestAgentd\n";
+  my $CPUCount = GetCPUCount();
+  system("cd '$::RootDir/src/testagentd' && set -x && ".
+         "time make -j$CPUCount iso");
+  if ($? != 0)
+  {
+    LogMsg "Build winetestbot.iso failed\n";
+    return !1;
+  }
+
+  return 1;
+}
+
+sub BuildTestLauncher()
+{
+  InfoMsg "\nRebuilding TestLauncher\n";
+  my $CPUCount = GetCPUCount();
+  system("cd '$::RootDir/src/TestLauncher' && set -x && ".
+         "time make -j$CPUCount");
+  if ($? != 0)
+  {
+    LogMsg "Build TestLauncher failed\n";
+    return !1;
+  }
+
+  return 1;
+}
+
+
+#
+# Wine addons updates
+#
+
+sub _VerifyAddOn($$)
+{
+  my ($AddOn, $Arch) = @_;
+
+  my $Sha256 = Digest::SHA->new(256);
+  eval { $Sha256->addfile("$DataDir/$AddOn->{name}/$AddOn->{filename}") };
+  return "$@" if ($@);
+
+  my $Checksum = $Sha256->hexdigest();
+  return undef if ($Checksum eq $AddOn->{$Arch});
+  return "Bad checksum for '$AddOn->{filename}'";
+}
+
+sub _UpdateAddOn($$$)
+{
+  my ($AddOn, $Name, $Arch) = @_;
+
+  if (!defined $AddOn)
+  {
+    LogMsg "Could not get information on the $Name addon\n";
+    return 0;
+  }
+  if (!$AddOn->{version})
+  {
+    LogMsg "Could not get the $Name version\n";
+    return 0;
+  }
+  if (!$AddOn->{$Arch})
+  {
+    LogMsg "Could not get the $Name $Arch checksum\n";
+    return 0;
+  }
+
+  $AddOn->{filename} = "wine". ($Name eq "gecko" ? "_" : "-") .
+                       "$Name-$AddOn->{version}".
+                       ($Arch eq "" ? "" : "-$Arch") .".msi";
+  return 1 if (!_VerifyAddOn($AddOn, $Arch));
+
+  InfoMsg "Downloading $AddOn->{filename}\n";
+  mkdir "$DataDir/$Name";
+
+  my $Url="http://dl.winehq.org/wine/wine-$Name/$AddOn->{version}/$AddOn->{filename}";
+  for (1..3)
+  {
+    system("cd '$DataDir/$Name' && set -x && ".
+           "wget --no-verbose -O- '$Url' >'$AddOn->{filename}'");
+    last if ($? == 0);
+  }
+  my $ErrMessage = _VerifyAddOn($AddOn, $Arch);
+  return 1 if (!defined $ErrMessage);
+  LogMsg "$ErrMessage\n";
+  return 0;
+}
+
+sub UpdateAddOns()
+{
+  my %AddOns;
+  if (open(my $fh, "<", "$DataDir/wine/dlls/appwiz.cpl/addons.c"))
+  {
+    my $Arch = "";
+    while (my $Line= <$fh>)
+    {
+      if ($Line =~ /^\s*#\s*define\s+ARCH_STRING\s+"([^"]+)"/)
+      {
+        $Arch = $1;
+      }
+      elsif ($Line =~ /^\s*#\s*define\s*(GECKO|MONO)_VERSION\s*"([^"]+)"/)
+      {
+        my ($AddOn, $Version) = ($1, $2);
+        $AddOn =~ tr/A-Z/a-z/;
+        $AddOns{$AddOn}->{name} = $AddOn;
+        $AddOns{$AddOn}->{version} = $Version;
+      }
+      elsif ($Line =~ /^\s*#\s*define\s*(GECKO|MONO)_SHA\s*"([^"]+)"/)
+      {
+        my ($AddOn, $Checksum) = ($1, $2);
+        $AddOn =~ tr/A-Z/a-z/;
+        $AddOns{$AddOn}->{$Arch} = $Checksum;
+        $Arch = "";
+      }
+    }
+    close($fh);
+  }
+  else
+  {
+    LogMsg "Could not open 'wine/dlls/appwiz.cpl/addons.c': $!\n";
+    return 0;
+  }
+
+  return _UpdateAddOn($AddOns{gecko}, "gecko", "x86") &&
+         _UpdateAddOn($AddOns{gecko}, "gecko", "x86_64") &&
+         _UpdateAddOn($AddOns{mono},  "mono",  "");
+}
+
+
+#
+# Wine helpers
+#
+
+sub SetupWineEnvironment($)
+{
+  my ($Build) = @_;
+
+  $ENV{WINEPREFIX} = "$DataDir/wineprefix-$Build";
+  $ENV{DISPLAY} ||= ":0.0";
+}
+
+sub RunWine($$$)
+{
+  my ($Build, $Cmd, $CmdArgs) = @_;
+
+  my $Magic = `cd '$DataDir/build-$Build' && file $Cmd`;
+  my $Wine = ($Magic =~ /ELF 64/ ? "./wine64" : "./wine");
+  return system("cd '$DataDir/build-$Build' && set -x && ".
+                "time $Wine $Cmd $CmdArgs");
+}
+
+
+#
+# WinePrefix helpers
+#
+
+sub CreateWinePrefix($$)
+{
+  my ($Build, $Wait) = @_;
+
+  return "\$WINEPREFIX is not set!" if (!$ENV{WINEPREFIX});
+  rmtree($ENV{WINEPREFIX});
+
+  # Crash dialogs cause delays so disable them
+  if (RunWine($Build, "./programs/reg/reg.exe.so", "ADD HKCU\\\\Software\\\\Wine\\\\WineDbg /v ShowCrashDialog /t REG_DWORD /d 0"))
+  {
+    return "Failed to disable the $Build build crash dialogs: $!";
+  }
+
+  if ($Wait)
+  {
+    # Ensure the WinePrefix has been fully created and the registry files
+    # saved before returning.
+    system("cd '$DataDir/build-$Build' && ./server/wineserver -w");
+  }
+
+  return undef;
+}
+
+1;
-- 
2.18.0



More information about the wine-devel mailing list