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
This commit is contained in:
stil 2017-02-05 07:07:05 +01:00 committed by MIkkel Kruse Johnsen
parent af3956b2dd
commit 5063385d16
13 changed files with 145 additions and 105 deletions

View file

@ -1,12 +1,14 @@
#!/usr/bin/python3 #!/usr/bin/python3
"""Script to build out the .Net dll's and package them into a Nuget Package for gtksharp3""" """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 import GtkSharp
from pybuild.profiles.GtkSharp_Core import GtkSharp_Core from pybuild.profiles.GtkSharp_Core import GtkSharp_Core
from pybuild.profiles.Glue_Win32 import Glue_Win32 from pybuild.profiles.Glue_Win32 import Glue_Win32
from pybuild.profiles.Glue_Win64 import Glue_Win64 from pybuild.profiles.Glue_Win64 import Glue_Win64
from pybuild.profiles.Gtk_Win32 import Gtk_Win32 from pybuild.profiles.Gtk_Win32 import Gtk_Win32
from pybuild.profiles.Gtk_Win64 import Gtk_Win64 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) # 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 # 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 # under linux we run this natively, under windows we can use MSYS2
class Build(object): class Build(object):
# Clean the Build directory # Clean the Build directory
def clean(self): @staticmethod
def clean():
"""Clean the build dir""" """Clean the build dir"""
helpers.emptydir('./build') Helper.emptydir('./build')
print ("Clean finished") print("Clean finished")
# Print Usage # Print Usage
def usage(self): @staticmethod
print ("Please use GtkSharp3_Build.py <target> where <target> is one of") def usage():
print (" clean to clean the output directory: ./build") print("Please use GtkSharp3_Build.py <target> where <target> 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 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_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_win32 to build the Nuget package for GtkSharp.Win32")
print (" gtk_win64 to build the Nuget package for GtkSharp.Win64") print(" gtk_win64 to build the Nuget package for GtkSharp.Win64")
print (" all to make all") print(" all to make all")
def main(self): def main(self):
if len(sys.argv) != 2: if len(sys.argv) != 2:
@ -46,13 +49,15 @@ class Build(object):
self.runbuild(sys.argv[1]) self.runbuild(sys.argv[1])
def runbuild(self, build_type): def runbuild(self, build_type):
if build_type == 'clean': if build_type == 'clean':
self.clean() self.clean()
return
elif build_type == 'gtksharp': Helper.install_pacman_deps()
if build_type == 'gtksharp':
profile = GtkSharp() profile = GtkSharp()
profile.clean() profile.clean()
profile.build() profile.build()
@ -82,5 +87,6 @@ class Build(object):
profile.build() profile.build()
profile.build_nuget() profile.build_nuget()
if __name__ == "__main__": if __name__ == "__main__":
Build().main() Build().main()

View file

@ -1,17 +1,18 @@
#!/usr/bin/python3 #!/usr/bin/python3
"""Helper Functions""" """Helper Functions"""
import os, subprocess, shutil, sys import os
from os.path import join from os.path import join
from glob import iglob
from executor import ExternalCommand from executor import ExternalCommand
import ntpath
class Helper(object): class Helper(object):
@staticmethod
def emptydir(top): def emptydir(top):
"""Empty a Directory""" """Empty a Directory"""
if(top == '/' or top == "\\"): return if top == '/' or top == "\\":
return
else: else:
for root, dirs, files in os.walk(top, topdown=False): for root, dirs, files in os.walk(top, topdown=False):
for name in files: for name in files:
@ -19,31 +20,37 @@ class Helper(object):
for name in dirs: for name in dirs:
os.rmdir(os.path.join(root, name)) os.rmdir(os.path.join(root, name))
def run_cmd(cmdarray, workdir, comms = None): @staticmethod
def run_cmd(cmdarray, workdir):
"""Run a command on the shell""" """Run a command on the shell"""
cmd = ExternalCommand(*cmdarray, capture=True, capture_stderr=True, async=True, shell=False, directory=workdir) cmd = ExternalCommand(*cmdarray, capture=True, capture_stderr=True, async=True, shell=False, directory=workdir)
cmd.start() cmd.start()
last_out = '' last_out = ''
last_err = '' last_err = ''
while cmd.is_running: while cmd.is_running:
new_out = cmd.decoded_stdout.replace(last_out, '') new_out = cmd.stdout.decode(cmd.encoding, 'ignore').replace(last_out, '')
new_err = cmd.decoded_stderr.replace(last_err, '') new_err = cmd.stderr.decode(cmd.encoding, 'ignore').replace(last_err, '')
last_out += new_out last_out += new_out
last_err += new_err last_err += new_err
new_out = new_out.replace(u"\u2018", "'").replace(u"\u2019", "'") new_out = new_out.replace(u"\u2018", "'").replace(u"\u2019", "'")
new_err = new_err.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_out != '':
if new_err != '': print(new_err, end='') print(new_out, end='')
if new_err != '':
print(new_err, end='')
if cmd.returncode != 0: if cmd.returncode != 0:
raise RuntimeError('Failure to run command') raise RuntimeError('Failure to run command')
return cmd return cmd
@staticmethod
def winpath_to_msyspath(winpath): def winpath_to_msyspath(winpath):
"""Convert a Windows path to a Msys type path""" """Convert a Windows path to a Msys type path"""
winpath = '/' + winpath[0] + winpath[2:].replace('\\', '/') winpath = '/' + winpath[0] + winpath[2:].replace('\\', '/')
return winpath return winpath
@staticmethod
def get_gtksharp_version(srcdir): def get_gtksharp_version(srcdir):
"""Get the Version of GTK Sharp in use from the source directory""" """Get the Version of GTK Sharp in use from the source directory"""
ret = None ret = None
@ -57,6 +64,26 @@ class Helper(object):
break break
return ret 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): def get_gtk_version_msys(msyspath):
ret = '' ret = ''
pacman_path = join(msyspath, 'usr\\bin\\pacman.exe') pacman_path = join(msyspath, 'usr\\bin\\pacman.exe')

View file

@ -1,13 +1,15 @@
#!/usr/bin/python3 #!/usr/bin/python3
"""Base class for Settings profiles""" """Base class for Settings profiles"""
import os, shutil import os
import shutil
from os.path import abspath, join from os.path import abspath, join
from xml.etree import ElementTree as et from xml.etree import ElementTree as et
from pybuild.Helper import Helper from pybuild.Helper import Helper
class ProfileBase(object):
class ProfileBase(object):
def __init__(self): def __init__(self):
"""Class Init""" """Class Init"""
self._NuGetPath = 'nuget.exe' self._NuGetPath = 'nuget.exe'
@ -55,12 +57,11 @@ class ProfileBase(object):
def Version(self): def Version(self):
return self._Version return self._Version
@staticmethod
def clean(self): def clean():
"""Clean the build dir""" """Clean the build dir"""
Helper.emptydir('./build') Helper.emptydir('./build')
print ("Clean finished") print("Clean finished")
def build_nuget(self): def build_nuget(self):
"""Package up a nuget file based on the default build""" """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') nugetfile = join(self.Build_NugetDir, self.NuGet_PackageName + '.' + self.Version + '.nupkg')
os.makedirs(self.PackageDestination, exist_ok=True) os.makedirs(self.PackageDestination, exist_ok=True)
shutil.copy(nugetfile, self.PackageDestination) shutil.copy(nugetfile, self.PackageDestination)
print ('Generation of Nuget package complete - ' + self.NuGet_PackageName) print('Generation of Nuget package complete - ' + self.NuGet_PackageName)

View file

@ -1,14 +1,17 @@
#!/usr/bin/python3 #!/usr/bin/python3
import os, shutil, ntpath import ntpath
from pybuild.ProfileBase import ProfileBase import os
from os.path import abspath, join import shutil
from glob import glob from glob import glob
from os.path import abspath, join
from pybuild.Helper import Helper from pybuild.Helper import Helper
from pybuild.ProfileBase import ProfileBase
from pybuild.profiles.GtkSharp import GtkSharp from pybuild.profiles.GtkSharp import GtkSharp
class Glue_Win32(ProfileBase):
class Glue_Win32(ProfileBase):
def __init__(self): def __init__(self):
"""Class Init""" """Class Init"""
super().__init__() super().__init__()
@ -41,7 +44,7 @@ class Glue_Win32(ProfileBase):
net45_build_dir = join(self.Build_NugetDir, 'build', 'net45') net45_build_dir = join(self.Build_NugetDir, 'build', 'net45')
os.makedirs(net45_build_dir, exist_ok=True) os.makedirs(net45_build_dir, exist_ok=True)
print ('Copying Files') print('Copying Files')
dll_list = self.Get_Dlls_GtkSharp_Glue() dll_list = self.Get_Dlls_GtkSharp_Glue()
for item in dll_list: for item in dll_list:

View file

@ -1,11 +1,10 @@
#!/usr/bin/python3 #!/usr/bin/python3
from pybuild.ProfileBase import ProfileBase
from pybuild.Helper import Helper from pybuild.Helper import Helper
from pybuild.profiles.Glue_Win32 import Glue_Win32 from pybuild.profiles.Glue_Win32 import Glue_Win32
class Glue_Win64(Glue_Win32):
class Glue_Win64(Glue_Win32):
def __init__(self): def __init__(self):
"""Class Init""" """Class Init"""
super().__init__() super().__init__()

View file

@ -1,11 +1,13 @@
#!/usr/bin/python3 #!/usr/bin/python3
import os, shutil import os
from pybuild.ProfileBase import ProfileBase import shutil
from os.path import abspath, join from os.path import abspath, join
from pybuild.Helper import Helper from pybuild.Helper import Helper
from pybuild.ProfileBase import ProfileBase
class GtkSharp(ProfileBase): class GtkSharp(ProfileBase):
def __init__(self): def __init__(self):
"""Class Init""" """Class Init"""
super().__init__() super().__init__()
@ -27,8 +29,8 @@ class GtkSharp(ProfileBase):
if os.name == 'nt': if os.name == 'nt':
print("Building .Net GtkSharp using MSYS2") print("Building .Net GtkSharp using MSYS2")
with open(buildfile, 'w') as f: 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=/c/Program\ Files\ \(x86\)/Microsoft\ SDKs/Windows/v10.0A/bin/NETFX\ 4.6\ Tools/:$PATH\n')
f.write('PATH=$PATH:/c/Windows/Microsoft.NET/Framework/v4.0.30319/\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('cd ' + Helper.winpath_to_msyspath(self.SrcDir + '\n'))
f.write('./autogen.sh --prefix=/tmp/install\n') f.write('./autogen.sh --prefix=/tmp/install\n')
f.write('make clean\n') f.write('make clean\n')
@ -53,7 +55,6 @@ class GtkSharp(ProfileBase):
cmds = [self.LinuxBashPath, buildfile] cmds = [self.LinuxBashPath, buildfile]
cmd = Helper.run_cmd(cmds, self.SrcDir) cmd = Helper.run_cmd(cmds, self.SrcDir)
def copy(self): def copy(self):
"""Copy the .Net 4.5 dll's to the build dir""" """Copy the .Net 4.5 dll's to the build dir"""

View file

@ -1,11 +1,15 @@
#!/usr/bin/python3 #!/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.ProfileBase import ProfileBase
from pybuild.vsgenext.CoreVSProject import CoreVSProject 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 # 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 # 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 # TODO look into package for symbols, via NuGet -symbols
class GtkSharp_Core(ProfileBase): class GtkSharp_Core(ProfileBase):
def __init__(self): def __init__(self):
"""Class Init""" """Class Init"""
super().__init__() super().__init__()
@ -36,7 +39,6 @@ class GtkSharp_Core(ProfileBase):
def Dotnet_BuildExe(self): def Dotnet_BuildExe(self):
return 'dotnet.exe' return 'dotnet.exe'
def Copy_CS_Files(self, csfiles): def Copy_CS_Files(self, csfiles):
srclist = glob(join(self.SrcDir, csfiles[0])) srclist = glob(join(self.SrcDir, csfiles[0]))
destdir = join(self.Build_CoreDir, csfiles[1]) destdir = join(self.Build_CoreDir, csfiles[1])
@ -47,11 +49,11 @@ class GtkSharp_Core(ProfileBase):
def SetupProject(self, projname): def SetupProject(self, projname):
proj = CoreVSProject() proj = CoreVSProject()
proj.Name = projname proj.Name = projname
proj.RootNamespace=projname proj.RootNamespace = projname
proj.FileName = join(self.Build_CoreDir, projname, projname + '.xproj') proj.FileName = join(self.Build_CoreDir, projname, projname + '.xproj')
proj.Frameworks = {'net461': {}} proj.Frameworks = {'net461': {}}
proj.Depends = {} proj.Depends = {}
proj.BuildOptions = { "allowUnsafe": True , "outputName": projname + "-sharp"} proj.BuildOptions = {"allowUnsafe": True, "outputName": projname + "-sharp"}
proj.Version = self._Version proj.Version = self._Version
self.Solution.Projects.append(proj) self.Solution.Projects.append(proj)
self.Solution.write() self.Solution.write()
@ -66,7 +68,6 @@ class GtkSharp_Core(ProfileBase):
'--output', join(self.Build_CoreDir, 'build')] '--output', join(self.Build_CoreDir, 'build')]
, projdir) , projdir)
def build(self): def build(self):
"""Build the gtksharp binaries for .Net 4.5""" """Build the gtksharp binaries for .Net 4.5"""
os.makedirs(self.Build_CoreDir, exist_ok=True) os.makedirs(self.Build_CoreDir, exist_ok=True)
@ -133,7 +134,6 @@ class GtkSharp_Core(ProfileBase):
proj.write() proj.write()
self.Build_Project(proj) self.Build_Project(proj)
def copy_dll(self): def copy_dll(self):
"""Copy the .Net 4.5 dll's to the build dir""" """Copy the .Net 4.5 dll's to the build dir"""

View file

@ -1,14 +1,17 @@
#!/usr/bin/python3 #!/usr/bin/python3
"""Build of GTK3 into a NuGet package - Windows 32bit""" """Build of GTK3 into a NuGet package - Windows 32bit"""
import os, shutil, ntpath import ntpath
from pybuild.ProfileBase import ProfileBase import os
from os.path import abspath, join import shutil
from glob import iglob from glob import iglob
from os.path import abspath, join
from pybuild.Helper import Helper from pybuild.Helper import Helper
from pybuild.ProfileBase import ProfileBase
class Gtk_Win32(ProfileBase): class Gtk_Win32(ProfileBase):
def __init__(self): def __init__(self):
"""Class Init""" """Class Init"""
super().__init__() super().__init__()
@ -21,7 +24,6 @@ class Gtk_Win32(ProfileBase):
def MingwBinPath(self): def MingwBinPath(self):
return abspath(self._MingwBinPath) return abspath(self._MingwBinPath)
def Get_Dlls_Native_GTK(self): def Get_Dlls_Native_GTK(self):
ret = [] ret = []
@ -74,7 +76,6 @@ class Gtk_Win32(ProfileBase):
ret.append('libbz2-1.dll') ret.append('libbz2-1.dll')
return ret return ret
def build(self): def build(self):
"""Package up a nuget file based on the default build""" """Package up a nuget file based on the default build"""
@ -85,7 +86,7 @@ class Gtk_Win32(ProfileBase):
net45_build_dir = join(self.Build_NugetDir, 'build', 'net45') net45_build_dir = join(self.Build_NugetDir, 'build', 'net45')
os.makedirs(net45_build_dir, exist_ok=True) 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')) shutil.copy('./misc/GtkSharp.Native.targets', join(net45_build_dir, 'GtkSharp.' + self.arch + '.targets'))
# Copy dlls # Copy dlls

View file

@ -1,14 +1,13 @@
#!/usr/bin/python3 #!/usr/bin/python3
"""Build of GTK3 into a NuGet package - Windows 64bit""" """Build of GTK3 into a NuGet package - Windows 64bit"""
import os, shutil from os.path import join
from pybuild.ProfileBase import ProfileBase
from os.path import abspath, join
from pybuild.Helper import Helper from pybuild.Helper import Helper
from pybuild.profiles.Gtk_Win32 import Gtk_Win32 from pybuild.profiles.Gtk_Win32 import Gtk_Win32
class Gtk_Win64(Gtk_Win32):
class Gtk_Win64(Gtk_Win32):
def __init__(self): def __init__(self):
"""Class Init""" """Class Init"""
super().__init__() super().__init__()

View file

@ -1,11 +1,14 @@
#!/usr/bin/python3 #!/usr/bin/python3
import os, json import json
from vsgen.project import VSGProject import os
from xml.etree import ElementTree as et
from yattag import indent
from os.path import abspath, join
from collections import OrderedDict 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): class CoreVSProject(VSGProject):
""" """
@ -56,13 +59,13 @@ class CoreVSProject(VSGProject):
depends2 = {'dependencies': depends} depends2 = {'dependencies': depends}
data.update(depends2) data.update(depends2)
if self.Frameworks != None: if self.Frameworks is not None:
frameworks = {'frameworks': self.Frameworks} frameworks = {'frameworks': self.Frameworks}
else: else:
frameworks = {'frameworks': {'netstandard1.6': {'imports': 'dnxcore50'}}} frameworks = {'frameworks': {'netstandard1.6': {'imports': 'dnxcore50'}}}
data.update(frameworks) data.update(frameworks)
if self.BuildOptions != None: if self.BuildOptions is not None:
buildopts = {'buildOptions': self.BuildOptions} buildopts = {'buildOptions': self.BuildOptions}
data.update(buildopts) data.update(buildopts)
@ -114,7 +117,6 @@ class CoreVSProject(VSGProject):
outtxt = indent(etstr) outtxt = indent(etstr)
return outtxt return outtxt
def write(self): def write(self):
""" """
Creates the project files. Creates the project files.
@ -125,7 +127,7 @@ class CoreVSProject(VSGProject):
projectFileName = os.path.normpath(self.FileName) projectFileName = os.path.normpath(self.FileName)
projxml = '' projxml = ''
if self.ProjectXml == None: if self.ProjectXml is None:
projxml = self.get_project_xml() projxml = self.get_project_xml()
else: else:
projxml = self.ProjectXml projxml = self.ProjectXml
@ -134,7 +136,7 @@ class CoreVSProject(VSGProject):
jsonFileName = join(filepath, 'project.json') jsonFileName = join(filepath, 'project.json')
if self.ProjectJson == None: if self.ProjectJson is None:
projjson = self.get_project_json() projjson = self.get_project_json()
else: else:
projjson = self.ProjectJson projjson = self.ProjectJson

View file

@ -89,8 +89,9 @@ fi
enable_msi="no" enable_msi="no"
if test "x$platform_win32" = "xyes"; then if test "x$platform_win32" = "xyes"; then
AC_PATH_PROG(WIX, candle, no) AC_PATH_PROG(WIX_CANDLE, candle, no)
if test "x$WIX" != "xno" ; then AC_PATH_PROG(WIX_LIGHT, light, no)
if test "x$WIX_CANDLE" != "xno" -a "x$WIX_LIGHT" != "xno" ; then
enable_msi="yes" enable_msi="yes"
fi fi
fi fi

View file

@ -26,5 +26,5 @@ gtk-sharp-3.0.msi: gtk-sharp-3.0.wxs
mv binaries/libpangosharpglue-3.dll binaries/pangosharpglue-3.dll mv binaries/libpangosharpglue-3.dll binaries/pangosharpglue-3.dll
cp $(top_builddir)/sample/GtkDemo/GtkDemo.exe binaries cp $(top_builddir)/sample/GtkDemo/GtkDemo.exe binaries
candle -ext WixUIExtension gtk-sharp-3.0.wxs $(WIX_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_LIGHT) -cultures:en-us -ext WixUIExtension -ext WixNetFxExtension -out gtk-sharp-$(VERSION).msi gtk-sharp-3.0.wixobj

View file

@ -15,10 +15,10 @@ download-stamp: $(DOWNLOADS)
touch download-stamp touch download-stamp
unmanaged.wixobj: unmanaged.wxs redirector.exe download-stamp unmanaged.wixobj: unmanaged.wxs redirector.exe download-stamp
candle unmanaged.wxs $(WIX_CANDLE) unmanaged.wxs
unmanaged.msm: unmanaged.wixobj unmanaged.msm: unmanaged.wixobj
light unmanaged.wixobj $(WIX_LIGHT) unmanaged.wixobj
bundle-scanner.exe: bundle-scanner.cs bundle-scanner.exe: bundle-scanner.cs
$(CSC) bundle-scanner.cs $(CSC) bundle-scanner.cs