From 5063385d16deae5f63e7f1c062e4d31f9a6d8502 Mon Sep 17 00:00:00 2001 From: stil Date: Sun, 5 Feb 2017 07:07:05 +0100 Subject: [PATCH] AppVeyor integration (#25) * Fix minor bugs and improve code formatting of Python build tool * Prepend $PATH to give it higher priority * Invoke WiX tools through variable to ensure correct path * Make build script ensure pacman dependencies are installed * pacman -Sy causes dependency break on AppVeyor * Skip deps version check and don't show progress bar --- NuGet/build.py | 38 +++++++------ NuGet/pybuild/Helper.py | 71 +++++++++++++++++-------- NuGet/pybuild/ProfileBase.py | 15 +++--- NuGet/pybuild/profiles/Glue_Win32.py | 17 +++--- NuGet/pybuild/profiles/Glue_Win64.py | 3 +- NuGet/pybuild/profiles/GtkSharp.py | 13 ++--- NuGet/pybuild/profiles/GtkSharp_Core.py | 26 ++++----- NuGet/pybuild/profiles/Gtk_Win32.py | 19 +++---- NuGet/pybuild/profiles/Gtk_Win64.py | 7 ++- NuGet/pybuild/vsgenext/CoreVSProject.py | 28 +++++----- configure.ac | 5 +- msi/Makefile.am | 4 +- msi/unmanaged/Makefile.am | 4 +- 13 files changed, 145 insertions(+), 105 deletions(-) diff --git a/NuGet/build.py b/NuGet/build.py index 3ba9363bb..99b2f7055 100644 --- a/NuGet/build.py +++ b/NuGet/build.py @@ -1,12 +1,14 @@ #!/usr/bin/python3 """Script to build out the .Net dll's and package them into a Nuget Package for gtksharp3""" -import os, sys +import sys from pybuild.profiles.GtkSharp import GtkSharp from pybuild.profiles.GtkSharp_Core import GtkSharp_Core from pybuild.profiles.Glue_Win32 import Glue_Win32 from pybuild.profiles.Glue_Win64 import Glue_Win64 from pybuild.profiles.Gtk_Win32 import Gtk_Win32 from pybuild.profiles.Gtk_Win64 import Gtk_Win64 +from pybuild.Helper import Helper + # Ideally I'd like to see the GtkSharp Build system redone via the build system of .Net core (dotnet cli tool) # and using Scons / Cuppa for the glue libraries @@ -14,24 +16,25 @@ from pybuild.profiles.Gtk_Win64 import Gtk_Win64 # under linux we run this natively, under windows we can use MSYS2 class Build(object): - # Clean the Build directory - def clean(self): + @staticmethod + def clean(): """Clean the build dir""" - helpers.emptydir('./build') - print ("Clean finished") + Helper.emptydir('./build') + print("Clean finished") # Print Usage - def usage(self): - print ("Please use GtkSharp3_Build.py where is one of") - print (" clean to clean the output directory: ./build") + @staticmethod + def usage(): + print("Please use GtkSharp3_Build.py where is one of") + print(" clean to clean the output directory: ./build") - print (" gtksharp to build .Net libs for GtkSharp, via .Net 4.5") - print (" gtksharp_core to build .Net libs for GtkSharp, via .Net 4.5 using the dotnet cli tool") + print(" gtksharp to build .Net libs for GtkSharp, via .Net 4.5") + print(" gtksharp_core to build .Net libs for GtkSharp, via .Net 4.5 using the dotnet cli tool") - print (" gtk_win32 to build the Nuget package for GtkSharp.Win32") - print (" gtk_win64 to build the Nuget package for GtkSharp.Win64") - print (" all to make all") + print(" gtk_win32 to build the Nuget package for GtkSharp.Win32") + print(" gtk_win64 to build the Nuget package for GtkSharp.Win64") + print(" all to make all") def main(self): if len(sys.argv) != 2: @@ -46,13 +49,15 @@ class Build(object): self.runbuild(sys.argv[1]) - def runbuild(self, build_type): - + if build_type == 'clean': self.clean() + return - elif build_type == 'gtksharp': + Helper.install_pacman_deps() + + if build_type == 'gtksharp': profile = GtkSharp() profile.clean() profile.build() @@ -82,5 +87,6 @@ class Build(object): profile.build() profile.build_nuget() + if __name__ == "__main__": Build().main() diff --git a/NuGet/pybuild/Helper.py b/NuGet/pybuild/Helper.py index f54e51e85..fa4d69203 100644 --- a/NuGet/pybuild/Helper.py +++ b/NuGet/pybuild/Helper.py @@ -1,17 +1,18 @@ #!/usr/bin/python3 """Helper Functions""" -import os, subprocess, shutil, sys +import os from os.path import join -from glob import iglob + from executor import ExternalCommand -import ntpath + class Helper(object): - + @staticmethod def emptydir(top): """Empty a Directory""" - if(top == '/' or top == "\\"): return + if top == '/' or top == "\\": + return else: for root, dirs, files in os.walk(top, topdown=False): for name in files: @@ -19,44 +20,70 @@ class Helper(object): for name in dirs: os.rmdir(os.path.join(root, name)) - def run_cmd(cmdarray, workdir, comms = None): - """Run a command on the shell""" + @staticmethod + def run_cmd(cmdarray, workdir): + """Run a command on the shell""" cmd = ExternalCommand(*cmdarray, capture=True, capture_stderr=True, async=True, shell=False, directory=workdir) cmd.start() last_out = '' last_err = '' while cmd.is_running: - new_out = cmd.decoded_stdout.replace(last_out, '') - new_err = cmd.decoded_stderr.replace(last_err, '') + new_out = cmd.stdout.decode(cmd.encoding, 'ignore').replace(last_out, '') + new_err = cmd.stderr.decode(cmd.encoding, 'ignore').replace(last_err, '') + last_out += new_out last_err += new_err new_out = new_out.replace(u"\u2018", "'").replace(u"\u2019", "'") new_err = new_err.replace(u"\u2018", "'").replace(u"\u2019", "'") - if new_out != '': print(new_out, end='') - if new_err != '': print(new_err, end='') + if new_out != '': + print(new_out, end='') + if new_err != '': + print(new_err, end='') if cmd.returncode != 0: raise RuntimeError('Failure to run command') return cmd + @staticmethod def winpath_to_msyspath(winpath): """Convert a Windows path to a Msys type path""" winpath = '/' + winpath[0] + winpath[2:].replace('\\', '/') return winpath + @staticmethod def get_gtksharp_version(srcdir): - """Get the Version of GTK Sharp in use from the source directory""" - ret = None - with open(join(srcdir, 'configure.ac')) as f: - for line in f: - if line.startswith('AC_INIT'): - ret = line - ret = ret.replace('AC_INIT(gtk-sharp,', '') - ret = ret.replace(' ', '') - ret = ret.replace(')\n', '') - break - return ret + """Get the Version of GTK Sharp in use from the source directory""" + ret = None + with open(join(srcdir, 'configure.ac')) as f: + for line in f: + if line.startswith('AC_INIT'): + ret = line + ret = ret.replace('AC_INIT(gtk-sharp,', '') + ret = ret.replace(' ', '') + ret = ret.replace(')\n', '') + break + return ret + @staticmethod + def install_pacman_deps(): + Helper.run_pacman_cmd(['-Sy']) + + args = ['--needed', '--nodeps', '--noprogressbar', '--noconfirm', '-S'] + args += 'unzip autoconf automake libtool pkg-config make'.split(' ') + + deps_arch = 'gcc glib2 pango atk gtk3 zlib libiconv' + args += ['mingw-w64-i686-{0}'.format(i) for i in deps_arch.split(' ')] + args += ['mingw-w64-x86_64-{0}'.format(i) for i in deps_arch.split(' ')] + + Helper.run_pacman_cmd(args) + + @staticmethod + def run_pacman_cmd(pacman_args): + msyspath = 'C:\\msys64' + pacman_path = join(msyspath, 'usr\\bin\\pacman.exe') + return Helper.run_cmd([pacman_path] + pacman_args, msyspath) + + @staticmethod def get_gtk_version_msys(msyspath): ret = '' pacman_path = join(msyspath, 'usr\\bin\\pacman.exe') diff --git a/NuGet/pybuild/ProfileBase.py b/NuGet/pybuild/ProfileBase.py index 317f3c062..cb64d8cb5 100644 --- a/NuGet/pybuild/ProfileBase.py +++ b/NuGet/pybuild/ProfileBase.py @@ -1,13 +1,15 @@ #!/usr/bin/python3 """Base class for Settings profiles""" -import os, shutil +import os +import shutil from os.path import abspath, join from xml.etree import ElementTree as et + from pybuild.Helper import Helper -class ProfileBase(object): +class ProfileBase(object): def __init__(self): """Class Init""" self._NuGetPath = 'nuget.exe' @@ -55,12 +57,11 @@ class ProfileBase(object): def Version(self): return self._Version - - def clean(self): + @staticmethod + def clean(): """Clean the build dir""" Helper.emptydir('./build') - print ("Clean finished") - + print("Clean finished") def build_nuget(self): """Package up a nuget file based on the default build""" @@ -84,4 +85,4 @@ class ProfileBase(object): nugetfile = join(self.Build_NugetDir, self.NuGet_PackageName + '.' + self.Version + '.nupkg') os.makedirs(self.PackageDestination, exist_ok=True) shutil.copy(nugetfile, self.PackageDestination) - print ('Generation of Nuget package complete - ' + self.NuGet_PackageName) + print('Generation of Nuget package complete - ' + self.NuGet_PackageName) diff --git a/NuGet/pybuild/profiles/Glue_Win32.py b/NuGet/pybuild/profiles/Glue_Win32.py index 5fa72f141..86117a4d3 100644 --- a/NuGet/pybuild/profiles/Glue_Win32.py +++ b/NuGet/pybuild/profiles/Glue_Win32.py @@ -1,14 +1,17 @@ #!/usr/bin/python3 -import os, shutil, ntpath -from pybuild.ProfileBase import ProfileBase -from os.path import abspath, join +import ntpath +import os +import shutil from glob import glob +from os.path import abspath, join + from pybuild.Helper import Helper +from pybuild.ProfileBase import ProfileBase from pybuild.profiles.GtkSharp import GtkSharp -class Glue_Win32(ProfileBase): +class Glue_Win32(ProfileBase): def __init__(self): """Class Init""" super().__init__() @@ -30,8 +33,8 @@ class Glue_Win32(ProfileBase): """Package up a nuget file based on the default build""" if os.name != 'nt': - print("Skipping Native Nuget package build, as this needs to be run on Windows") - return + print("Skipping Native Nuget package build, as this needs to be run on Windows") + return # Trigger build of gtksharp with specific bash for Mingw32 builder = GtkSharp() @@ -41,7 +44,7 @@ class Glue_Win32(ProfileBase): net45_build_dir = join(self.Build_NugetDir, 'build', 'net45') os.makedirs(net45_build_dir, exist_ok=True) - print ('Copying Files') + print('Copying Files') dll_list = self.Get_Dlls_GtkSharp_Glue() for item in dll_list: diff --git a/NuGet/pybuild/profiles/Glue_Win64.py b/NuGet/pybuild/profiles/Glue_Win64.py index 74938ac9f..60f741fa9 100644 --- a/NuGet/pybuild/profiles/Glue_Win64.py +++ b/NuGet/pybuild/profiles/Glue_Win64.py @@ -1,11 +1,10 @@ #!/usr/bin/python3 -from pybuild.ProfileBase import ProfileBase from pybuild.Helper import Helper from pybuild.profiles.Glue_Win32 import Glue_Win32 -class Glue_Win64(Glue_Win32): +class Glue_Win64(Glue_Win32): def __init__(self): """Class Init""" super().__init__() diff --git a/NuGet/pybuild/profiles/GtkSharp.py b/NuGet/pybuild/profiles/GtkSharp.py index f1a193e75..87c121afb 100644 --- a/NuGet/pybuild/profiles/GtkSharp.py +++ b/NuGet/pybuild/profiles/GtkSharp.py @@ -1,11 +1,13 @@ #!/usr/bin/python3 -import os, shutil -from pybuild.ProfileBase import ProfileBase +import os +import shutil from os.path import abspath, join + from pybuild.Helper import Helper +from pybuild.ProfileBase import ProfileBase + class GtkSharp(ProfileBase): - def __init__(self): """Class Init""" super().__init__() @@ -27,8 +29,8 @@ class GtkSharp(ProfileBase): if os.name == 'nt': print("Building .Net GtkSharp using MSYS2") with open(buildfile, 'w') as f: - f.write('PATH=$PATH:/c/Program\ Files\ \(x86\)/Microsoft\ SDKs/Windows/v10.0A/bin/NETFX\ 4.6\ Tools/\n') - f.write('PATH=$PATH:/c/Windows/Microsoft.NET/Framework/v4.0.30319/\n') + f.write('PATH=/c/Program\ Files\ \(x86\)/Microsoft\ SDKs/Windows/v10.0A/bin/NETFX\ 4.6\ Tools/:$PATH\n') + f.write('PATH=/c/Windows/Microsoft.NET/Framework/v4.0.30319/:$PATH\n') f.write('cd ' + Helper.winpath_to_msyspath(self.SrcDir + '\n')) f.write('./autogen.sh --prefix=/tmp/install\n') f.write('make clean\n') @@ -53,7 +55,6 @@ class GtkSharp(ProfileBase): cmds = [self.LinuxBashPath, buildfile] cmd = Helper.run_cmd(cmds, self.SrcDir) - def copy(self): """Copy the .Net 4.5 dll's to the build dir""" diff --git a/NuGet/pybuild/profiles/GtkSharp_Core.py b/NuGet/pybuild/profiles/GtkSharp_Core.py index 078f376e1..18640ecf7 100644 --- a/NuGet/pybuild/profiles/GtkSharp_Core.py +++ b/NuGet/pybuild/profiles/GtkSharp_Core.py @@ -1,11 +1,15 @@ #!/usr/bin/python3 -import os, shutil +import os +import shutil +from glob import glob +from os.path import abspath, join + +import vsgen + +from pybuild.Helper import Helper from pybuild.ProfileBase import ProfileBase from pybuild.vsgenext.CoreVSProject import CoreVSProject -from os.path import abspath, join -from pybuild.Helper import Helper -from glob import glob -import vsgen + # Note at this stage we can't complile GtkSharp using the .Net Core platform libraries, such as netstandard1.6 # https://docs.microsoft.com/en-us/dotnet/articles/standard/library @@ -19,7 +23,6 @@ import vsgen # TODO look into package for symbols, via NuGet -symbols class GtkSharp_Core(ProfileBase): - def __init__(self): """Class Init""" super().__init__() @@ -36,7 +39,6 @@ class GtkSharp_Core(ProfileBase): def Dotnet_BuildExe(self): return 'dotnet.exe' - def Copy_CS_Files(self, csfiles): srclist = glob(join(self.SrcDir, csfiles[0])) destdir = join(self.Build_CoreDir, csfiles[1]) @@ -47,11 +49,11 @@ class GtkSharp_Core(ProfileBase): def SetupProject(self, projname): proj = CoreVSProject() proj.Name = projname - proj.RootNamespace=projname + proj.RootNamespace = projname proj.FileName = join(self.Build_CoreDir, projname, projname + '.xproj') proj.Frameworks = {'net461': {}} proj.Depends = {} - proj.BuildOptions = { "allowUnsafe": True , "outputName": projname + "-sharp"} + proj.BuildOptions = {"allowUnsafe": True, "outputName": projname + "-sharp"} proj.Version = self._Version self.Solution.Projects.append(proj) self.Solution.write() @@ -64,8 +66,7 @@ class GtkSharp_Core(ProfileBase): '--configuration', self.BuildConfig, '--framework', 'net461', '--output', join(self.Build_CoreDir, 'build')] - , projdir) - + , projdir) def build(self): """Build the gtksharp binaries for .Net 4.5""" @@ -133,7 +134,6 @@ class GtkSharp_Core(ProfileBase): proj.write() self.Build_Project(proj) - def copy_dll(self): """Copy the .Net 4.5 dll's to the build dir""" @@ -152,4 +152,4 @@ class GtkSharp_Core(ProfileBase): dll_list = ['atk', 'cairo', 'gdk', 'gio', 'glib', 'gtk', 'pango'] for item in dll_list: if item != 'cairo': - shutil.copy(join(self.SrcDir, item, item + '-sharp.dll.config'), net45_build_dir) \ No newline at end of file + shutil.copy(join(self.SrcDir, item, item + '-sharp.dll.config'), net45_build_dir) diff --git a/NuGet/pybuild/profiles/Gtk_Win32.py b/NuGet/pybuild/profiles/Gtk_Win32.py index 0c4fb1fad..311fb87a2 100644 --- a/NuGet/pybuild/profiles/Gtk_Win32.py +++ b/NuGet/pybuild/profiles/Gtk_Win32.py @@ -1,14 +1,17 @@ #!/usr/bin/python3 """Build of GTK3 into a NuGet package - Windows 32bit""" -import os, shutil, ntpath -from pybuild.ProfileBase import ProfileBase -from os.path import abspath, join +import ntpath +import os +import shutil from glob import iglob +from os.path import abspath, join + from pybuild.Helper import Helper +from pybuild.ProfileBase import ProfileBase + class Gtk_Win32(ProfileBase): - def __init__(self): """Class Init""" super().__init__() @@ -21,7 +24,6 @@ class Gtk_Win32(ProfileBase): def MingwBinPath(self): return abspath(self._MingwBinPath) - def Get_Dlls_Native_GTK(self): ret = [] @@ -74,18 +76,17 @@ class Gtk_Win32(ProfileBase): ret.append('libbz2-1.dll') return ret - def build(self): """Package up a nuget file based on the default build""" if os.name != 'nt': - print("Skipping Native Nuget package build, as this needs to be run on Windows") - return + print("Skipping Native Nuget package build, as this needs to be run on Windows") + return net45_build_dir = join(self.Build_NugetDir, 'build', 'net45') os.makedirs(net45_build_dir, exist_ok=True) - print ('Copying Files') + print('Copying Files') shutil.copy('./misc/GtkSharp.Native.targets', join(net45_build_dir, 'GtkSharp.' + self.arch + '.targets')) # Copy dlls diff --git a/NuGet/pybuild/profiles/Gtk_Win64.py b/NuGet/pybuild/profiles/Gtk_Win64.py index 998fc8252..97e8fe839 100644 --- a/NuGet/pybuild/profiles/Gtk_Win64.py +++ b/NuGet/pybuild/profiles/Gtk_Win64.py @@ -1,14 +1,13 @@ #!/usr/bin/python3 """Build of GTK3 into a NuGet package - Windows 64bit""" -import os, shutil -from pybuild.ProfileBase import ProfileBase -from os.path import abspath, join +from os.path import join + from pybuild.Helper import Helper from pybuild.profiles.Gtk_Win32 import Gtk_Win32 -class Gtk_Win64(Gtk_Win32): +class Gtk_Win64(Gtk_Win32): def __init__(self): """Class Init""" super().__init__() diff --git a/NuGet/pybuild/vsgenext/CoreVSProject.py b/NuGet/pybuild/vsgenext/CoreVSProject.py index 520c0f763..79dcca987 100644 --- a/NuGet/pybuild/vsgenext/CoreVSProject.py +++ b/NuGet/pybuild/vsgenext/CoreVSProject.py @@ -1,11 +1,14 @@ #!/usr/bin/python3 -import os, json -from vsgen.project import VSGProject -from xml.etree import ElementTree as et -from yattag import indent -from os.path import abspath, join +import json +import os from collections import OrderedDict +from os.path import join +from xml.etree import ElementTree as et + +from vsgen.project import VSGProject +from yattag import indent + class CoreVSProject(VSGProject): """ @@ -51,18 +54,18 @@ class CoreVSProject(VSGProject): data = OrderedDict() ver = {'version': self.Version} data.update(ver) - + depends = self.Depends depends2 = {'dependencies': depends} data.update(depends2) - - if self.Frameworks != None: + + if self.Frameworks is not None: frameworks = {'frameworks': self.Frameworks} else: frameworks = {'frameworks': {'netstandard1.6': {'imports': 'dnxcore50'}}} data.update(frameworks) - if self.BuildOptions != None: + if self.BuildOptions is not None: buildopts = {'buildOptions': self.BuildOptions} data.update(buildopts) @@ -112,8 +115,7 @@ class CoreVSProject(VSGProject): etstr = et.tostring(xml_projroot, encoding='utf-8', method='xml').decode('utf-8') outtxt = indent(etstr) - return outtxt - + return outtxt def write(self): """ @@ -125,7 +127,7 @@ class CoreVSProject(VSGProject): projectFileName = os.path.normpath(self.FileName) projxml = '' - if self.ProjectXml == None: + if self.ProjectXml is None: projxml = self.get_project_xml() else: projxml = self.ProjectXml @@ -134,7 +136,7 @@ class CoreVSProject(VSGProject): jsonFileName = join(filepath, 'project.json') - if self.ProjectJson == None: + if self.ProjectJson is None: projjson = self.get_project_json() else: projjson = self.ProjectJson diff --git a/configure.ac b/configure.ac index d58243133..eb8162efd 100644 --- a/configure.ac +++ b/configure.ac @@ -89,8 +89,9 @@ fi enable_msi="no" if test "x$platform_win32" = "xyes"; then - AC_PATH_PROG(WIX, candle, no) - if test "x$WIX" != "xno" ; then + AC_PATH_PROG(WIX_CANDLE, candle, no) + AC_PATH_PROG(WIX_LIGHT, light, no) + if test "x$WIX_CANDLE" != "xno" -a "x$WIX_LIGHT" != "xno" ; then enable_msi="yes" fi fi diff --git a/msi/Makefile.am b/msi/Makefile.am index bceda3229..11e80b622 100644 --- a/msi/Makefile.am +++ b/msi/Makefile.am @@ -26,5 +26,5 @@ gtk-sharp-3.0.msi: gtk-sharp-3.0.wxs mv binaries/libpangosharpglue-3.dll binaries/pangosharpglue-3.dll cp $(top_builddir)/sample/GtkDemo/GtkDemo.exe binaries - candle -ext WixUIExtension gtk-sharp-3.0.wxs - light -cultures:en-us -ext WixUIExtension -ext WixNetFxExtension -out gtk-sharp-$(VERSION).msi gtk-sharp-3.0.wixobj + $(WIX_CANDLE) -ext WixUIExtension gtk-sharp-3.0.wxs + $(WIX_LIGHT) -cultures:en-us -ext WixUIExtension -ext WixNetFxExtension -out gtk-sharp-$(VERSION).msi gtk-sharp-3.0.wixobj diff --git a/msi/unmanaged/Makefile.am b/msi/unmanaged/Makefile.am index 6afe677d9..433a97e5e 100644 --- a/msi/unmanaged/Makefile.am +++ b/msi/unmanaged/Makefile.am @@ -15,10 +15,10 @@ download-stamp: $(DOWNLOADS) touch download-stamp unmanaged.wixobj: unmanaged.wxs redirector.exe download-stamp - candle unmanaged.wxs + $(WIX_CANDLE) unmanaged.wxs unmanaged.msm: unmanaged.wixobj - light unmanaged.wixobj + $(WIX_LIGHT) unmanaged.wixobj bundle-scanner.exe: bundle-scanner.cs $(CSC) bundle-scanner.cs