From 07b3d459ea0a45cbef29b98d283edafbab26462a Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Wed, 12 Oct 2022 22:01:55 -0700 Subject: Normalize ToolsetTask implementation to call wix.exe and heat.exe Share the ToolsetTask implementation that can find .NET Core and .NET Framework with multiple architectures. Fixes 6951 --- .../SetBuildNumber/Directory.Packages.props.pp | 1 + .../BaseToolsetTask.cs | 178 +++++++++++++++++++++ .../FileSearchHelperMethods.cs | 57 +++++++ .../WixCommandLineBuilder.cs | 177 ++++++++++++++++++++ .../WixToolset.BaseBuildTasks.Sources.csproj | 36 +++++ src/internal/internal.cmd | 2 + src/internal/internal.sln | 22 ++- src/internal/internal_t.proj | 1 + .../TestData/WixprojPackageHarvesting/Package.wxs | 12 ++ .../WixprojPackageHarvesting.wixproj | 21 +++ .../TestData/WixprojPackageHarvesting/_data/a.txt | 1 + .../TestData/WixprojPackageHarvesting/_data/b.txt | 1 + .../wix/TestData/WixprojPackageHeatDir/Package.wxs | 12 ++ .../WixprojPackageHeatDir.wixproj | 30 ++++ .../wix/TestData/WixprojPackageHeatDir/_data/a.txt | 1 + .../wix/TestData/WixprojPackageHeatDir/_data/b.txt | 1 + src/test/wix/WixE2E/WixE2EFixture.cs | 31 ++++ src/tools/WixToolset.HeatTasks/HeatDirectory.cs | 1 + src/tools/WixToolset.HeatTasks/HeatFile.cs | 1 + src/tools/WixToolset.HeatTasks/HeatProject.cs | 1 + src/tools/WixToolset.HeatTasks/HeatTask.cs | 139 +--------------- .../WixToolset.HeatTasks/WixCommandLineBuilder.cs | 56 ------- .../WixToolset.HeatTasks.csproj | 1 + .../DetachBundleEngineForSigning.cs | 1 + .../FileSearchHelperMethods.cs | 57 ------- .../InscribeMsiWithCabinetSignatures.cs | 1 + .../ReattachSignedBundleEngine.cs | 1 + src/wix/WixToolset.BuildTasks/ToolsetTask.cs | 177 -------------------- .../WindowsInstallerValidation.cs | 1 + src/wix/WixToolset.BuildTasks/WixBuild.cs | 1 + .../WixToolset.BuildTasks/WixCommandLineBuilder.cs | 177 -------------------- src/wix/WixToolset.BuildTasks/WixExeBaseTask.cs | 4 +- .../WixToolset.BuildTasks.csproj | 3 +- 33 files changed, 601 insertions(+), 605 deletions(-) create mode 100644 src/internal/WixToolset.BaseBuildTasks.Sources/BaseToolsetTask.cs create mode 100644 src/internal/WixToolset.BaseBuildTasks.Sources/FileSearchHelperMethods.cs create mode 100644 src/internal/WixToolset.BaseBuildTasks.Sources/WixCommandLineBuilder.cs create mode 100644 src/internal/WixToolset.BaseBuildTasks.Sources/WixToolset.BaseBuildTasks.Sources.csproj create mode 100644 src/test/wix/TestData/WixprojPackageHarvesting/Package.wxs create mode 100644 src/test/wix/TestData/WixprojPackageHarvesting/WixprojPackageHarvesting.wixproj create mode 100644 src/test/wix/TestData/WixprojPackageHarvesting/_data/a.txt create mode 100644 src/test/wix/TestData/WixprojPackageHarvesting/_data/b.txt create mode 100644 src/test/wix/TestData/WixprojPackageHeatDir/Package.wxs create mode 100644 src/test/wix/TestData/WixprojPackageHeatDir/WixprojPackageHeatDir.wixproj create mode 100644 src/test/wix/TestData/WixprojPackageHeatDir/_data/a.txt create mode 100644 src/test/wix/TestData/WixprojPackageHeatDir/_data/b.txt delete mode 100644 src/tools/WixToolset.HeatTasks/WixCommandLineBuilder.cs delete mode 100644 src/wix/WixToolset.BuildTasks/FileSearchHelperMethods.cs delete mode 100644 src/wix/WixToolset.BuildTasks/ToolsetTask.cs delete mode 100644 src/wix/WixToolset.BuildTasks/WixCommandLineBuilder.cs (limited to 'src') diff --git a/src/internal/SetBuildNumber/Directory.Packages.props.pp b/src/internal/SetBuildNumber/Directory.Packages.props.pp index d06990fe..e1df6f8e 100644 --- a/src/internal/SetBuildNumber/Directory.Packages.props.pp +++ b/src/internal/SetBuildNumber/Directory.Packages.props.pp @@ -8,6 +8,7 @@ + diff --git a/src/internal/WixToolset.BaseBuildTasks.Sources/BaseToolsetTask.cs b/src/internal/WixToolset.BaseBuildTasks.Sources/BaseToolsetTask.cs new file mode 100644 index 00000000..d9e3b5e8 --- /dev/null +++ b/src/internal/WixToolset.BaseBuildTasks.Sources/BaseToolsetTask.cs @@ -0,0 +1,178 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.BaseBuildTasks +{ + using System; + using System.IO; + using System.Runtime.InteropServices; + using Microsoft.Build.Utilities; + + public abstract class BaseToolsetTask : ToolTask + { + /// + /// Gets or sets additional options that are appended the the tool command-line. + /// + /// + /// This allows the task to support extended options in the tool which are not + /// explicitly implemented as properties on the task. + /// + public string AdditionalOptions { get; set; } + + /// + /// Gets or sets whether to display the logo. + /// + public bool NoLogo { get; set; } + + /// + /// Gets or sets whether all warnings should be suppressed. + /// + public bool SuppressAllWarnings { get; set; } + + /// + /// Gets or sets a list of specific warnings to be suppressed. + /// + public string[] SuppressSpecificWarnings { get; set; } + + /// + /// Gets or sets whether all warnings should be treated as errors. + /// + public bool TreatWarningsAsErrors { get; set; } + + /// + /// Gets or sets a list of specific warnings to treat as errors. + /// + public string[] TreatSpecificWarningsAsErrors { get; set; } + + /// + /// Gets or sets whether to display verbose output. + /// + public bool VerboseOutput { get; set; } + + /// + /// Get the path to the executable. + /// + /// + /// ToolTask only calls GenerateFullPathToTool when the ToolPath property is not set. + /// WiX never sets the ToolPath property, but the user can through $(WixToolDir). + /// If we return only a file name, ToolTask will search the system paths for it. + /// + protected sealed override string GenerateFullPathToTool() + { + var defaultToolFullPath = this.GetDefaultToolFullPath(); + +#if NETCOREAPP + // If we're pointing at an executable use that. + if (IsSelfExecutable(defaultToolFullPath, out var finalToolFullPath)) + { + return finalToolFullPath; + } + + // Otherwise, use "dotnet.exe" to run an assembly dll. + return Environment.GetEnvironmentVariable("DOTNET_HOST_PATH") ?? "dotnet"; +#else + return defaultToolFullPath; +#endif + } + + /// + /// Builds a command line from options in this and derivative tasks. + /// + /// + /// Derivative classes should call BuildCommandLine() on the base class to ensure that common command line options are added to the command. + /// + protected virtual void BuildCommandLine(WixCommandLineBuilder commandLineBuilder) + { + commandLineBuilder.AppendIfTrue("-nologo", this.NoLogo); + commandLineBuilder.AppendArrayIfNotNull("-sw", this.SuppressSpecificWarnings); + commandLineBuilder.AppendIfTrue("-sw", this.SuppressAllWarnings); + commandLineBuilder.AppendIfTrue("-v", this.VerboseOutput); + commandLineBuilder.AppendArrayIfNotNull("-wx", this.TreatSpecificWarningsAsErrors); + commandLineBuilder.AppendIfTrue("-wx", this.TreatWarningsAsErrors); + commandLineBuilder.AppendTextIfNotNull(this.AdditionalOptions); + } + + protected sealed override string GenerateResponseFileCommands() + { + var commandLineBuilder = new WixCommandLineBuilder(); + this.BuildCommandLine(commandLineBuilder); + return commandLineBuilder.ToString(); + } + +#if NETCOREAPP + protected override string GenerateCommandLineCommands() + { + // If the target tool path is an executable, we don't need to add anything to the command-line. + var toolFullPath = this.GetToolFullPath(); + + if (IsSelfExecutable(toolFullPath, out var finalToolFullPath)) + { + return null; + } + else // we're using "dotnet.exe" to run the assembly so add "exec" plus path to the command-line. + { + return $"exec \"{finalToolFullPath}\""; + } + } + + private static bool IsSelfExecutable(string proposedToolFullPath, out string finalToolFullPath) + { + var toolFullPathWithoutExtension = Path.Combine(Path.GetDirectoryName(proposedToolFullPath), Path.GetFileNameWithoutExtension(proposedToolFullPath)); + var exeExtension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : String.Empty; + var exeToolFullPath = $"{toolFullPathWithoutExtension}{exeExtension}"; + if (File.Exists(exeToolFullPath)) + { + finalToolFullPath = exeToolFullPath; + return true; + } + + finalToolFullPath = $"{toolFullPathWithoutExtension}.dll"; + return false; + } +#else + private static string GetArchitectureFolder(string baseFolder) + { + // First try to find a folder that matches this task's architecture. + var folder = RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(); + + if (Directory.Exists(Path.Combine(baseFolder, folder))) + { + return folder; + } + + // Try to fallback to "x86" folder. + if (folder != "x86" && Directory.Exists(Path.Combine(baseFolder, "x86"))) + { + return "x86"; + } + + // Return empty, even though this isn't likely to be useful. + return String.Empty; + } +#endif + + private string GetDefaultToolFullPath() + { +#if NETCOREAPP + var thisTaskFolder = Path.GetDirectoryName(typeof(BaseToolsetTask).Assembly.Location); + + return Path.Combine(thisTaskFolder, this.ToolExe); +#else + var thisTaskFolder = Path.GetDirectoryName(new Uri(typeof(BaseToolsetTask).Assembly.CodeBase).AbsolutePath); + + var archFolder = GetArchitectureFolder(thisTaskFolder); + + return Path.Combine(thisTaskFolder, archFolder, this.ToolExe); +#endif + } + + private string GetToolFullPath() + { + if (String.IsNullOrEmpty(this.ToolPath)) + { + return this.GetDefaultToolFullPath(); + } + + return Path.Combine(this.ToolPath, this.ToolExe); + } + } +} diff --git a/src/internal/WixToolset.BaseBuildTasks.Sources/FileSearchHelperMethods.cs b/src/internal/WixToolset.BaseBuildTasks.Sources/FileSearchHelperMethods.cs new file mode 100644 index 00000000..442fedd6 --- /dev/null +++ b/src/internal/WixToolset.BaseBuildTasks.Sources/FileSearchHelperMethods.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.BaseBuildTasks +{ + using System; + using System.IO; + + /// + /// Contains helper methods on searching for files + /// + public static class FileSearchHelperMethods + { + /// + /// Searches for the existence of a file in multiple directories. + /// Search is satisfied if default file path is valid and exists. If not, + /// file name is extracted from default path and combined with each of the directories + /// looking to see if it exists. If not found, input default path is returned. + /// + /// Array of directories to look in, without filenames in them + /// Default path - to use if not found + /// File path if file found. Empty string if not found + public static string SearchFilePaths(string[] directories, string defaultFullPath) + { + if (String.IsNullOrEmpty(defaultFullPath)) + { + return String.Empty; + } + + if (File.Exists(defaultFullPath)) + { + return defaultFullPath; + } + + if (directories == null) + { + return String.Empty; + } + + var fileName = Path.GetFileName(defaultFullPath); + foreach (var currentPath in directories) + { + if (String.IsNullOrWhiteSpace(currentPath)) + { + continue; + } + + var path = Path.Combine(currentPath, fileName); + if (File.Exists(path)) + { + return path; + } + } + + return String.Empty; + } + } +} diff --git a/src/internal/WixToolset.BaseBuildTasks.Sources/WixCommandLineBuilder.cs b/src/internal/WixToolset.BaseBuildTasks.Sources/WixCommandLineBuilder.cs new file mode 100644 index 00000000..152992dd --- /dev/null +++ b/src/internal/WixToolset.BaseBuildTasks.Sources/WixCommandLineBuilder.cs @@ -0,0 +1,177 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.BaseBuildTasks +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.IO; + + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + + /// + /// Helper class for appending the command line arguments. + /// + public class WixCommandLineBuilder : CommandLineBuilder + { + internal const int Unspecified = -1; + + /// + /// Append a switch to the command line if the value has been specified. + /// + /// Switch to append. + /// Value specified by the user. + public void AppendIfSpecified(string switchName, int value) + { + if (value != Unspecified) + { + this.AppendSwitchIfNotNull(switchName, value.ToString(CultureInfo.InvariantCulture)); + } + } + + /// + /// Append a switch to the command line if the condition is true. + /// + /// Switch to append. + /// Condition specified by the user. + public void AppendIfTrue(string switchName, bool condition) + { + if (condition) + { + this.AppendSwitch(switchName); + } + } + + /// + /// Append a switch to the command line if any values in the array have been specified. + /// + /// Switch to append. + /// Values specified by the user. + public void AppendArrayIfNotNull(string switchName, IEnumerable values) + { + if (values != null) + { + foreach (ITaskItem value in values) + { + this.AppendSwitchIfNotNull(switchName, value); + } + } + } + + /// + /// Append a switch to the command line if any values in the array have been specified. + /// + /// Switch to append. + /// Values specified by the user. + public void AppendArrayIfNotNull(string switchName, IEnumerable values) + { + if (values != null) + { + foreach (string value in values) + { + this.AppendSwitchIfNotNull(switchName, value); + } + } + } + + /// + /// Build the extensions argument. Each extension is searched in the current folder, user defined search + /// directories (ReferencePath), HintPath, and under Wix Extension Directory in that order. + /// The order of precedence is based off of that described in Microsoft.Common.Targets's SearchPaths + /// property for the ResolveAssemblyReferences task. + /// + /// The list of extensions to include. + /// Evaluated default folder for Wix Extensions + /// User defined reference directories to search in + public void AppendExtensions(ITaskItem[] extensions, string wixExtensionDirectory, string [] referencePaths) + { + if (extensions == null) + { + return; + } + + foreach (ITaskItem extension in extensions) + { + string className = extension.GetMetadata("Class"); + + string fileName = Path.GetFileName(extension.ItemSpec); + + if (String.IsNullOrEmpty(Path.GetExtension(fileName))) + { + fileName += ".dll"; + } + + // First try reference paths + var resolvedPath = FileSearchHelperMethods.SearchFilePaths(referencePaths, fileName); + + if (String.IsNullOrEmpty(resolvedPath)) + { + // Now try HintPath + resolvedPath = extension.GetMetadata("HintPath"); + + if (!File.Exists(resolvedPath)) + { + // Now try the item itself + resolvedPath = extension.ItemSpec; + + if (String.IsNullOrEmpty(Path.GetExtension(resolvedPath))) + { + resolvedPath += ".dll"; + } + + if (!File.Exists(resolvedPath)) + { + if (!String.IsNullOrEmpty(wixExtensionDirectory)) + { + // Now try the extension directory + resolvedPath = Path.Combine(wixExtensionDirectory, Path.GetFileName(resolvedPath)); + } + + if (!File.Exists(resolvedPath)) + { + // Extension wasn't found, just set it to the extension name passed in + resolvedPath = extension.ItemSpec; + } + } + } + } + + if (String.IsNullOrEmpty(className)) + { + this.AppendSwitchIfNotNull("-ext ", resolvedPath); + } + else + { + this.AppendSwitchIfNotNull("-ext ", className + ", " + resolvedPath); + } + } + } + + /// + /// Append arbitrary text to the command-line if specified. + /// + /// Text to append. + public void AppendTextIfNotNull(string textToAppend) + { + if (!String.IsNullOrEmpty(textToAppend)) + { + this.AppendSpaceIfNotEmpty(); + this.AppendTextUnquoted(textToAppend); + } + } + + /// + /// Append arbitrary text to the command-line if specified. + /// + /// Text to append. + public void AppendTextIfNotWhitespace(string textToAppend) + { + if (!String.IsNullOrWhiteSpace(textToAppend)) + { + this.AppendSpaceIfNotEmpty(); + this.AppendTextUnquoted(textToAppend); + } + } + } +} diff --git a/src/internal/WixToolset.BaseBuildTasks.Sources/WixToolset.BaseBuildTasks.Sources.csproj b/src/internal/WixToolset.BaseBuildTasks.Sources/WixToolset.BaseBuildTasks.Sources.csproj new file mode 100644 index 00000000..6ae5165e --- /dev/null +++ b/src/internal/WixToolset.BaseBuildTasks.Sources/WixToolset.BaseBuildTasks.Sources.csproj @@ -0,0 +1,36 @@ + + + + + + + + netstandard2.0 + WiX Toolset BuildTasks Foundation Sources + true + false + false + contentFiles + true + false + false + CS8021 + true + true + true + + + + + + + + + + + + + + + + diff --git a/src/internal/internal.cmd b/src/internal/internal.cmd index 9380ce4e..32df26e9 100644 --- a/src/internal/internal.cmd +++ b/src/internal/internal.cmd @@ -33,8 +33,10 @@ msbuild internal_t.proj -p:Configuration=%_C% -nologo -warnaserror -bl:%_L%\inte @rd /s/q "..\..\build\internal" 2> nul @del "..\..\build\artifacts\WixBuildTools.TestSupport.*.nupkg" 2> nul @del "..\..\build\artifacts\WixBuildTools.TestSupport.Native.*.nupkg" 2> nul +@del "..\..\build\artifacts\WixToolset.BaseBuildTasks.Sources.*.nupkg" 2> nul @rd /s/q "%USERPROFILE%\.nuget\packages\wixbuildtools.testsupport" 2> nul @rd /s/q "%USERPROFILE%\.nuget\packages\wixbuildtools.testsupport.native" 2> nul +@rd /s/q "%USERPROFILE%\.nuget\packages\wixtoolset.basebuildtasks.sources" 2> nul @exit /b :end diff --git a/src/internal/internal.sln b/src/internal/internal.sln index 9d4fe69f..fe36efbe 100644 --- a/src/internal/internal.sln +++ b/src/internal/internal.sln @@ -1,12 +1,14 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.6.30114.105 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32929.385 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixBuildTools.TestSupport", "WixBuildTools.TestSupport\WixBuildTools.TestSupport.csproj", "{8E082709-7355-41D5-AF86-6BBF9C89BDD7}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WixBuildTools.TestSupport.Native", "WixBuildTools.TestSupport.Native\WixBuildTools.TestSupport.Native.vcxproj", "{95BABD97-FBDB-453A-AF8A-FA031A07B599}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.BaseBuildTasks.Sources", "WixToolset.BaseBuildTasks.Sources\WixToolset.BaseBuildTasks.Sources.csproj", "{6B654490-AB0D-4F94-B564-DAA80044D5A3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -47,6 +49,22 @@ Global {95BABD97-FBDB-453A-AF8A-FA031A07B599}.Release|x64.ActiveCfg = Release|Win32 {95BABD97-FBDB-453A-AF8A-FA031A07B599}.Release|x86.ActiveCfg = Release|Win32 {95BABD97-FBDB-453A-AF8A-FA031A07B599}.Release|x86.Build.0 = Release|Win32 + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Debug|ARM64.Build.0 = Debug|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Debug|x64.ActiveCfg = Debug|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Debug|x64.Build.0 = Debug|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Debug|x86.ActiveCfg = Debug|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Debug|x86.Build.0 = Debug|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|Any CPU.Build.0 = Release|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|ARM64.ActiveCfg = Release|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|ARM64.Build.0 = Release|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|x64.ActiveCfg = Release|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|x64.Build.0 = Release|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|x86.ActiveCfg = Release|Any CPU + {6B654490-AB0D-4F94-B564-DAA80044D5A3}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/internal/internal_t.proj b/src/internal/internal_t.proj index fda67786..fc4956d2 100644 --- a/src/internal/internal_t.proj +++ b/src/internal/internal_t.proj @@ -1,5 +1,6 @@ + diff --git a/src/test/wix/TestData/WixprojPackageHarvesting/Package.wxs b/src/test/wix/TestData/WixprojPackageHarvesting/Package.wxs new file mode 100644 index 00000000..cea86733 --- /dev/null +++ b/src/test/wix/TestData/WixprojPackageHarvesting/Package.wxs @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/test/wix/TestData/WixprojPackageHarvesting/WixprojPackageHarvesting.wixproj b/src/test/wix/TestData/WixprojPackageHarvesting/WixprojPackageHarvesting.wixproj new file mode 100644 index 00000000..c4255246 --- /dev/null +++ b/src/test/wix/TestData/WixprojPackageHarvesting/WixprojPackageHarvesting.wixproj @@ -0,0 +1,21 @@ + + + + + true + true + + + + + HarvestedComponents + ApplicationFolder + true + + + + + + + + diff --git a/src/test/wix/TestData/WixprojPackageHarvesting/_data/a.txt b/src/test/wix/TestData/WixprojPackageHarvesting/_data/a.txt new file mode 100644 index 00000000..71b864af --- /dev/null +++ b/src/test/wix/TestData/WixprojPackageHarvesting/_data/a.txt @@ -0,0 +1 @@ +This is a.txt. diff --git a/src/test/wix/TestData/WixprojPackageHarvesting/_data/b.txt b/src/test/wix/TestData/WixprojPackageHarvesting/_data/b.txt new file mode 100644 index 00000000..78eb1cc6 --- /dev/null +++ b/src/test/wix/TestData/WixprojPackageHarvesting/_data/b.txt @@ -0,0 +1 @@ +This is b.txt. diff --git a/src/test/wix/TestData/WixprojPackageHeatDir/Package.wxs b/src/test/wix/TestData/WixprojPackageHeatDir/Package.wxs new file mode 100644 index 00000000..cea86733 --- /dev/null +++ b/src/test/wix/TestData/WixprojPackageHeatDir/Package.wxs @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/test/wix/TestData/WixprojPackageHeatDir/WixprojPackageHeatDir.wixproj b/src/test/wix/TestData/WixprojPackageHeatDir/WixprojPackageHeatDir.wixproj new file mode 100644 index 00000000..3df9c9d4 --- /dev/null +++ b/src/test/wix/TestData/WixprojPackageHeatDir/WixprojPackageHeatDir.wixproj @@ -0,0 +1,30 @@ + + + + + true + true + + + + + + + + + + + + + + + + + + diff --git a/src/test/wix/TestData/WixprojPackageHeatDir/_data/a.txt b/src/test/wix/TestData/WixprojPackageHeatDir/_data/a.txt new file mode 100644 index 00000000..71b864af --- /dev/null +++ b/src/test/wix/TestData/WixprojPackageHeatDir/_data/a.txt @@ -0,0 +1 @@ +This is a.txt. diff --git a/src/test/wix/TestData/WixprojPackageHeatDir/_data/b.txt b/src/test/wix/TestData/WixprojPackageHeatDir/_data/b.txt new file mode 100644 index 00000000..78eb1cc6 --- /dev/null +++ b/src/test/wix/TestData/WixprojPackageHeatDir/_data/b.txt @@ -0,0 +1 @@ +This is b.txt. diff --git a/src/test/wix/WixE2E/WixE2EFixture.cs b/src/test/wix/WixE2E/WixE2EFixture.cs index b1c6b2de..5574680f 100644 --- a/src/test/wix/WixE2E/WixE2EFixture.cs +++ b/src/test/wix/WixE2E/WixE2EFixture.cs @@ -115,6 +115,32 @@ namespace WixE2E Assert.NotEqual(firstHashes, secondHashes); } + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CanBuildPackageWithHarvesting(bool x64) + { + var projectPath = TestData.Get("TestData", "WixprojPackageHarvesting", "WixprojPackageHarvesting.wixproj"); + + CleanEverything(); + + var result = RestoreAndBuild(projectPath, x64); + result.AssertSuccess(); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CanBuildPackageWithHeatDir(bool x64) + { + var projectPath = TestData.Get("TestData", "WixprojPackageHeatDir", "WixprojPackageHeatDir.wixproj"); + + CleanEverything(); + + var result = RestoreAndBuild(projectPath, x64); + result.AssertSuccess(); + } + [Fact(Skip = "Investigate if .NET Core WebApplications can be incrementally built")] public void CanIncrementalBuildPackageWithNetCoreWebAppWithoutEdits() { @@ -161,6 +187,11 @@ namespace WixE2E } } } + + foreach (var logFile in Directory.GetFiles(rootFolder, "*.binlog", SearchOption.AllDirectories)) + { + File.Delete(logFile); + } } private static string GetFileHash(string path) diff --git a/src/tools/WixToolset.HeatTasks/HeatDirectory.cs b/src/tools/WixToolset.HeatTasks/HeatDirectory.cs index 8a169055..14a8acfa 100644 --- a/src/tools/WixToolset.HeatTasks/HeatDirectory.cs +++ b/src/tools/WixToolset.HeatTasks/HeatDirectory.cs @@ -3,6 +3,7 @@ namespace WixToolset.HeatTasks { using Microsoft.Build.Framework; + using WixToolset.BaseBuildTasks; public sealed class HeatDirectory : HeatTask { diff --git a/src/tools/WixToolset.HeatTasks/HeatFile.cs b/src/tools/WixToolset.HeatTasks/HeatFile.cs index 83cbc4d1..b39de7da 100644 --- a/src/tools/WixToolset.HeatTasks/HeatFile.cs +++ b/src/tools/WixToolset.HeatTasks/HeatFile.cs @@ -3,6 +3,7 @@ namespace WixToolset.HeatTasks { using Microsoft.Build.Framework; + using WixToolset.BaseBuildTasks; public sealed class HeatFile : HeatTask { diff --git a/src/tools/WixToolset.HeatTasks/HeatProject.cs b/src/tools/WixToolset.HeatTasks/HeatProject.cs index d54f6ad1..998c14ab 100644 --- a/src/tools/WixToolset.HeatTasks/HeatProject.cs +++ b/src/tools/WixToolset.HeatTasks/HeatProject.cs @@ -3,6 +3,7 @@ namespace WixToolset.HeatTasks { using Microsoft.Build.Framework; + using WixToolset.BaseBuildTasks; public sealed class HeatProject : HeatTask { diff --git a/src/tools/WixToolset.HeatTasks/HeatTask.cs b/src/tools/WixToolset.HeatTasks/HeatTask.cs index 6b7b9399..cad6635b 100644 --- a/src/tools/WixToolset.HeatTasks/HeatTask.cs +++ b/src/tools/WixToolset.HeatTasks/HeatTask.cs @@ -2,64 +2,15 @@ namespace WixToolset.HeatTasks { - using System; - using System.IO; - using System.Runtime.InteropServices; using Microsoft.Build.Framework; - using Microsoft.Build.Utilities; + using WixToolset.BaseBuildTasks; /// /// A base MSBuild task to run the WiX harvester. /// Specific harvester tasks should extend this class. /// - public abstract partial class HeatTask : ToolTask + public abstract partial class HeatTask : BaseToolsetTask { -#if NETFRAMEWORK - private static readonly string ThisDllPath = new Uri(typeof(HeatTask).Assembly.CodeBase).AbsolutePath; -#else - private static readonly string ThisDllPath = typeof(HeatTask).Assembly.Location; -#endif - - - /// - /// Gets or sets additional options that are appended the the tool command-line. - /// - /// - /// This allows the task to support extended options in the tool which are not - /// explicitly implemented as properties on the task. - /// - public string AdditionalOptions { get; set; } - - /// - /// Gets or sets whether to display the logo. - /// - public bool NoLogo { get; set; } - - /// - /// Gets or sets whether all warnings should be suppressed. - /// - public bool SuppressAllWarnings { get; set; } - - /// - /// Gets or sets a list of specific warnings to be suppressed. - /// - public string[] SuppressSpecificWarnings { get; set; } - - /// - /// Gets or sets whether all warnings should be treated as errors. - /// - public bool TreatWarningsAsErrors { get; set; } - - /// - /// Gets or sets a list of specific warnings to treat as errors. - /// - public string[] TreatSpecificWarningsAsErrors { get; set; } - - /// - /// Gets or sets whether to display verbose output. - /// - public bool VerboseOutput { get; set; } - public bool AutogenerateGuids { get; set; } public bool GenerateGuidsNow { get; set; } @@ -74,8 +25,6 @@ namespace WixToolset.HeatTasks public string[] Transforms { get; set; } - protected sealed override string ToolName => "heat.exe"; - /// /// Gets the name of the heat operation performed by the task. /// @@ -83,99 +32,21 @@ namespace WixToolset.HeatTasks /// The name of the heat operation performed by the task. protected abstract string OperationName { get; } - private string ToolFullPath - { - get - { - if (String.IsNullOrEmpty(this.ToolPath)) - { - return Path.Combine(Path.GetDirectoryName(ThisDllPath), this.ToolExe); - } - - return Path.Combine(this.ToolPath, this.ToolExe); - } - } - - /// - /// Get the path to the executable. - /// - /// - /// ToolTask only calls GenerateFullPathToTool when the ToolPath property is not set. - /// WiX never sets the ToolPath property, but the user can through $(HeatToolDir). - /// If we return only a file name, ToolTask will search the system paths for it. - /// - protected sealed override string GenerateFullPathToTool() - { -#if NETCOREAPP - // If we're not using heat.exe, use dotnet.exe to exec heat.dll. - // See this.GenerateCommandLine() where "exec heat.dll" is added. - if (!IsSelfExecutable(this.ToolFullPath, out var toolFullPath)) - { - return DotnetFullPath; - } - - return toolFullPath; -#else - return this.ToolFullPath; -#endif - } - - protected sealed override string GenerateCommandLineCommands() - { - var commandLineBuilder = new WixCommandLineBuilder(); - -#if NETCOREAPP - // If we're using dotnet.exe as the target executable, see this.GenerateFullPathToTool(), - // then add "exec heat.dll" to the beginning of the command-line. - if (!IsSelfExecutable(this.ToolFullPath, out var toolFullPath)) - { - //commandLineBuilder.AppendSwitchIfNotNull("exec ", toolFullPath); - commandLineBuilder.AppendSwitch($"exec \"{toolFullPath}\""); - } -#endif - - this.BuildCommandLine(commandLineBuilder); - return commandLineBuilder.ToString(); - } + protected sealed override string ToolName => "heat.exe"; /// /// Builds a command line from options in this task. /// - protected virtual void BuildCommandLine(WixCommandLineBuilder commandLineBuilder) + protected override void BuildCommandLine(WixCommandLineBuilder commandLineBuilder) { - commandLineBuilder.AppendIfTrue("-nologo", this.NoLogo); - commandLineBuilder.AppendArrayIfNotNull("-sw", this.SuppressSpecificWarnings); - commandLineBuilder.AppendIfTrue("-sw", this.SuppressAllWarnings); - commandLineBuilder.AppendIfTrue("-v", this.VerboseOutput); - commandLineBuilder.AppendArrayIfNotNull("-wx", this.TreatSpecificWarningsAsErrors); - commandLineBuilder.AppendIfTrue("-wx", this.TreatWarningsAsErrors); + base.BuildCommandLine(commandLineBuilder); commandLineBuilder.AppendIfTrue("-ag", this.AutogenerateGuids); commandLineBuilder.AppendIfTrue("-gg", this.GenerateGuidsNow); commandLineBuilder.AppendIfTrue("-sfrag", this.SuppressFragments); commandLineBuilder.AppendIfTrue("-suid", this.SuppressUniqueIds); commandLineBuilder.AppendArrayIfNotNull("-t ", this.Transforms); - commandLineBuilder.AppendTextIfNotNull(this.AdditionalOptions); commandLineBuilder.AppendSwitchIfNotNull("-out ", this.OutputFile); } - -#if NETCOREAPP - private static readonly string DotnetFullPath = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH") ?? "dotnet"; - - private static bool IsSelfExecutable(string proposedToolFullPath, out string toolFullPath) - { - var toolFullPathWithoutExtension = Path.Combine(Path.GetDirectoryName(proposedToolFullPath), Path.GetFileNameWithoutExtension(proposedToolFullPath)); - var exeExtension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : String.Empty; - var exeToolFullPath = $"{toolFullPathWithoutExtension}{exeExtension}"; - if (File.Exists(exeToolFullPath)) - { - toolFullPath = exeToolFullPath; - return true; - } - - toolFullPath = $"{toolFullPathWithoutExtension}.dll"; - return false; - } -#endif } } diff --git a/src/tools/WixToolset.HeatTasks/WixCommandLineBuilder.cs b/src/tools/WixToolset.HeatTasks/WixCommandLineBuilder.cs deleted file mode 100644 index c3989902..00000000 --- a/src/tools/WixToolset.HeatTasks/WixCommandLineBuilder.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -namespace WixToolset.HeatTasks -{ - using System; - using System.Collections.Generic; - using Microsoft.Build.Utilities; - - /// - /// Helper class for appending the command line arguments. - /// - public class WixCommandLineBuilder : CommandLineBuilder - { - /// - /// Append a switch to the command line if the condition is true. - /// - /// Switch to append. - /// Condition specified by the user. - public void AppendIfTrue(string switchName, bool condition) - { - if (condition) - { - this.AppendSwitch(switchName); - } - } - - /// - /// Append a switch to the command line if any values in the array have been specified. - /// - /// Switch to append. - /// Values specified by the user. - public void AppendArrayIfNotNull(string switchName, IEnumerable values) - { - if (values != null) - { - foreach (var value in values) - { - this.AppendSwitchIfNotNull(switchName, value); - } - } - } - - /// - /// Append arbitrary text to the command-line if specified. - /// - /// Text to append. - public void AppendTextIfNotNull(string textToAppend) - { - if (!String.IsNullOrWhiteSpace(textToAppend)) - { - this.AppendSpaceIfNotEmpty(); - this.AppendTextUnquoted(textToAppend); - } - } - } -} diff --git a/src/tools/WixToolset.HeatTasks/WixToolset.HeatTasks.csproj b/src/tools/WixToolset.HeatTasks/WixToolset.HeatTasks.csproj index 21fb419c..a8538d9e 100644 --- a/src/tools/WixToolset.HeatTasks/WixToolset.HeatTasks.csproj +++ b/src/tools/WixToolset.HeatTasks/WixToolset.HeatTasks.csproj @@ -12,5 +12,6 @@ + diff --git a/src/wix/WixToolset.BuildTasks/DetachBundleEngineForSigning.cs b/src/wix/WixToolset.BuildTasks/DetachBundleEngineForSigning.cs index 5fcd1def..27d4436b 100644 --- a/src/wix/WixToolset.BuildTasks/DetachBundleEngineForSigning.cs +++ b/src/wix/WixToolset.BuildTasks/DetachBundleEngineForSigning.cs @@ -3,6 +3,7 @@ namespace WixToolset.BuildTasks { using Microsoft.Build.Framework; + using WixToolset.BaseBuildTasks; /// /// An MSBuild task to run WiX to detach bundle engine to be signed. diff --git a/src/wix/WixToolset.BuildTasks/FileSearchHelperMethods.cs b/src/wix/WixToolset.BuildTasks/FileSearchHelperMethods.cs deleted file mode 100644 index 94ff8c67..00000000 --- a/src/wix/WixToolset.BuildTasks/FileSearchHelperMethods.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -namespace WixToolset.BuildTasks -{ - using System; - using System.IO; - - /// - /// Contains helper methods on searching for files - /// - public static class FileSearchHelperMethods - { - /// - /// Searches for the existence of a file in multiple directories. - /// Search is satisfied if default file path is valid and exists. If not, - /// file name is extracted from default path and combined with each of the directories - /// looking to see if it exists. If not found, input default path is returned. - /// - /// Array of directories to look in, without filenames in them - /// Default path - to use if not found - /// File path if file found. Empty string if not found - public static string SearchFilePaths(string[] directories, string defaultFullPath) - { - if (String.IsNullOrEmpty(defaultFullPath)) - { - return String.Empty; - } - - if (File.Exists(defaultFullPath)) - { - return defaultFullPath; - } - - if (directories == null) - { - return String.Empty; - } - - var fileName = Path.GetFileName(defaultFullPath); - foreach (var currentPath in directories) - { - if (String.IsNullOrWhiteSpace(currentPath)) - { - continue; - } - - var path = Path.Combine(currentPath, fileName); - if (File.Exists(path)) - { - return path; - } - } - - return String.Empty; - } - } -} diff --git a/src/wix/WixToolset.BuildTasks/InscribeMsiWithCabinetSignatures.cs b/src/wix/WixToolset.BuildTasks/InscribeMsiWithCabinetSignatures.cs index 9f78caa5..72d9e872 100644 --- a/src/wix/WixToolset.BuildTasks/InscribeMsiWithCabinetSignatures.cs +++ b/src/wix/WixToolset.BuildTasks/InscribeMsiWithCabinetSignatures.cs @@ -3,6 +3,7 @@ namespace WixToolset.BuildTasks { using Microsoft.Build.Framework; + using WixToolset.BaseBuildTasks; /// /// An MSBuild task to run WiX to update cabinet signatures in a MSI. diff --git a/src/wix/WixToolset.BuildTasks/ReattachSignedBundleEngine.cs b/src/wix/WixToolset.BuildTasks/ReattachSignedBundleEngine.cs index c07c12b9..d131402d 100644 --- a/src/wix/WixToolset.BuildTasks/ReattachSignedBundleEngine.cs +++ b/src/wix/WixToolset.BuildTasks/ReattachSignedBundleEngine.cs @@ -3,6 +3,7 @@ namespace WixToolset.BuildTasks { using Microsoft.Build.Framework; + using WixToolset.BaseBuildTasks; /// /// An MSBuild task to run WiX to reattach a (signed) bundle engine to its bundle. diff --git a/src/wix/WixToolset.BuildTasks/ToolsetTask.cs b/src/wix/WixToolset.BuildTasks/ToolsetTask.cs deleted file mode 100644 index 3eee7625..00000000 --- a/src/wix/WixToolset.BuildTasks/ToolsetTask.cs +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -namespace WixToolset.BuildTasks -{ - using System; - using System.IO; - using System.Runtime.InteropServices; - using Microsoft.Build.Utilities; - - public abstract class ToolsetTask : ToolTask - { - /// - /// Gets or sets additional options that are appended the the tool command-line. - /// - /// - /// This allows the task to support extended options in the tool which are not - /// explicitly implemented as properties on the task. - /// - public string AdditionalOptions { get; set; } - - /// - /// Gets or sets whether to display the logo. - /// - public bool NoLogo { get; set; } - - /// - /// Gets or sets whether all warnings should be suppressed. - /// - public bool SuppressAllWarnings { get; set; } - - /// - /// Gets or sets a list of specific warnings to be suppressed. - /// - public string[] SuppressSpecificWarnings { get; set; } - - /// - /// Gets or sets whether all warnings should be treated as errors. - /// - public bool TreatWarningsAsErrors { get; set; } - - /// - /// Gets or sets a list of specific warnings to treat as errors. - /// - public string[] TreatSpecificWarningsAsErrors { get; set; } - - /// - /// Gets or sets whether to display verbose output. - /// - public bool VerboseOutput { get; set; } - - /// - /// Get the path to the executable. - /// - /// - /// ToolTask only calls GenerateFullPathToTool when the ToolPath property is not set. - /// WiX never sets the ToolPath property, but the user can through $(WixToolDir). - /// If we return only a file name, ToolTask will search the system paths for it. - /// - protected sealed override string GenerateFullPathToTool() - { - var defaultToolFullPath = this.GetDefaultToolFullPath(); - -#if NETCOREAPP - // If we're pointing at an executable use that. - if (IsSelfExecutable(defaultToolFullPath, out var finalToolFullPath)) - { - return finalToolFullPath; - } - - // Otherwise, use "dotnet.exe" to run an assembly dll. - return Environment.GetEnvironmentVariable("DOTNET_HOST_PATH") ?? "dotnet"; -#else - return defaultToolFullPath; -#endif - } - - /// - /// Builds a command line from options in this and derivative tasks. - /// - /// - /// Derivative classes should call BuildCommandLine() on the base class to ensure that common command line options are added to the command. - /// - protected virtual void BuildCommandLine(WixCommandLineBuilder commandLineBuilder) - { - commandLineBuilder.AppendIfTrue("-nologo", this.NoLogo); - commandLineBuilder.AppendArrayIfNotNull("-sw", this.SuppressSpecificWarnings); - commandLineBuilder.AppendIfTrue("-sw", this.SuppressAllWarnings); - commandLineBuilder.AppendIfTrue("-v", this.VerboseOutput); - commandLineBuilder.AppendArrayIfNotNull("-wx", this.TreatSpecificWarningsAsErrors); - commandLineBuilder.AppendIfTrue("-wx", this.TreatWarningsAsErrors); - } - - protected sealed override string GenerateResponseFileCommands() - { - var commandLineBuilder = new WixCommandLineBuilder(); - this.BuildCommandLine(commandLineBuilder); - return commandLineBuilder.ToString(); - } - -#if NETCOREAPP - protected override string GenerateCommandLineCommands() - { - // If the target tool path is an executable, we don't need to add anything to the command-line. - var toolFullPath = this.GetToolFullPath(); - - if (IsSelfExecutable(toolFullPath, out var finalToolFullPath)) - { - return null; - } - else // we're using "dotnet.exe" to run the assembly so add "exec" plus path to the command-line. - { - return $"exec \"{finalToolFullPath}\""; - } - } - - private static bool IsSelfExecutable(string proposedToolFullPath, out string finalToolFullPath) - { - var toolFullPathWithoutExtension = Path.Combine(Path.GetDirectoryName(proposedToolFullPath), Path.GetFileNameWithoutExtension(proposedToolFullPath)); - var exeExtension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : String.Empty; - var exeToolFullPath = $"{toolFullPathWithoutExtension}{exeExtension}"; - if (File.Exists(exeToolFullPath)) - { - finalToolFullPath = exeToolFullPath; - return true; - } - - finalToolFullPath = $"{toolFullPathWithoutExtension}.dll"; - return false; - } -#else - private static string GetArchitectureFolder(string baseFolder) - { - // First try to find a folder that matches this task's architecture. - var folder = RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(); - - if (Directory.Exists(Path.Combine(baseFolder, folder))) - { - return folder; - } - - // Try to fallback to "x86" folder. - if (folder != "x86" && Directory.Exists(Path.Combine(baseFolder, "x86"))) - { - return "x86"; - } - - // Return empty, even though this isn't likely to be useful. - return String.Empty; - } -#endif - - private string GetDefaultToolFullPath() - { -#if NETCOREAPP - var thisTaskFolder = Path.GetDirectoryName(typeof(ToolsetTask).Assembly.Location); - - return Path.Combine(thisTaskFolder, this.ToolExe); -#else - var thisTaskFolder = Path.GetDirectoryName(new Uri(typeof(ToolsetTask).Assembly.CodeBase).AbsolutePath); - - var archFolder = GetArchitectureFolder(thisTaskFolder); - - return Path.Combine(thisTaskFolder, archFolder, this.ToolExe); -#endif - } - - private string GetToolFullPath() - { - if (String.IsNullOrEmpty(this.ToolPath)) - { - return this.GetDefaultToolFullPath(); - } - - return Path.Combine(this.ToolPath, this.ToolExe); - } - } -} diff --git a/src/wix/WixToolset.BuildTasks/WindowsInstallerValidation.cs b/src/wix/WixToolset.BuildTasks/WindowsInstallerValidation.cs index ae708c0e..cfa6ed85 100644 --- a/src/wix/WixToolset.BuildTasks/WindowsInstallerValidation.cs +++ b/src/wix/WixToolset.BuildTasks/WindowsInstallerValidation.cs @@ -3,6 +3,7 @@ namespace WixToolset.BuildTasks { using Microsoft.Build.Framework; + using WixToolset.BaseBuildTasks; /// /// An MSBuild task to run WiX to detach bundle engine to be signed. diff --git a/src/wix/WixToolset.BuildTasks/WixBuild.cs b/src/wix/WixToolset.BuildTasks/WixBuild.cs index 5c3b9a48..8990d0b7 100644 --- a/src/wix/WixToolset.BuildTasks/WixBuild.cs +++ b/src/wix/WixToolset.BuildTasks/WixBuild.cs @@ -5,6 +5,7 @@ namespace WixToolset.BuildTasks using System; using System.Collections.Generic; using Microsoft.Build.Framework; + using WixToolset.BaseBuildTasks; /// /// An MSBuild task to run the WiX compiler. diff --git a/src/wix/WixToolset.BuildTasks/WixCommandLineBuilder.cs b/src/wix/WixToolset.BuildTasks/WixCommandLineBuilder.cs deleted file mode 100644 index a979dbb0..00000000 --- a/src/wix/WixToolset.BuildTasks/WixCommandLineBuilder.cs +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -namespace WixToolset.BuildTasks -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.IO; - - using Microsoft.Build.Framework; - using Microsoft.Build.Utilities; - - /// - /// Helper class for appending the command line arguments. - /// - public class WixCommandLineBuilder : CommandLineBuilder - { - internal const int Unspecified = -1; - - /// - /// Append a switch to the command line if the value has been specified. - /// - /// Switch to append. - /// Value specified by the user. - public void AppendIfSpecified(string switchName, int value) - { - if (value != Unspecified) - { - this.AppendSwitchIfNotNull(switchName, value.ToString(CultureInfo.InvariantCulture)); - } - } - - /// - /// Append a switch to the command line if the condition is true. - /// - /// Switch to append. - /// Condition specified by the user. - public void AppendIfTrue(string switchName, bool condition) - { - if (condition) - { - this.AppendSwitch(switchName); - } - } - - /// - /// Append a switch to the command line if any values in the array have been specified. - /// - /// Switch to append. - /// Values specified by the user. - public void AppendArrayIfNotNull(string switchName, IEnumerable values) - { - if (values != null) - { - foreach (ITaskItem value in values) - { - this.AppendSwitchIfNotNull(switchName, value); - } - } - } - - /// - /// Append a switch to the command line if any values in the array have been specified. - /// - /// Switch to append. - /// Values specified by the user. - public void AppendArrayIfNotNull(string switchName, IEnumerable values) - { - if (values != null) - { - foreach (string value in values) - { - this.AppendSwitchIfNotNull(switchName, value); - } - } - } - - /// - /// Build the extensions argument. Each extension is searched in the current folder, user defined search - /// directories (ReferencePath), HintPath, and under Wix Extension Directory in that order. - /// The order of precedence is based off of that described in Microsoft.Common.Targets's SearchPaths - /// property for the ResolveAssemblyReferences task. - /// - /// The list of extensions to include. - /// Evaluated default folder for Wix Extensions - /// User defined reference directories to search in - public void AppendExtensions(ITaskItem[] extensions, string wixExtensionDirectory, string [] referencePaths) - { - if (extensions == null) - { - return; - } - - foreach (ITaskItem extension in extensions) - { - string className = extension.GetMetadata("Class"); - - string fileName = Path.GetFileName(extension.ItemSpec); - - if (String.IsNullOrEmpty(Path.GetExtension(fileName))) - { - fileName += ".dll"; - } - - // First try reference paths - var resolvedPath = FileSearchHelperMethods.SearchFilePaths(referencePaths, fileName); - - if (String.IsNullOrEmpty(resolvedPath)) - { - // Now try HintPath - resolvedPath = extension.GetMetadata("HintPath"); - - if (!File.Exists(resolvedPath)) - { - // Now try the item itself - resolvedPath = extension.ItemSpec; - - if (String.IsNullOrEmpty(Path.GetExtension(resolvedPath))) - { - resolvedPath += ".dll"; - } - - if (!File.Exists(resolvedPath)) - { - if (!String.IsNullOrEmpty(wixExtensionDirectory)) - { - // Now try the extension directory - resolvedPath = Path.Combine(wixExtensionDirectory, Path.GetFileName(resolvedPath)); - } - - if (!File.Exists(resolvedPath)) - { - // Extension wasn't found, just set it to the extension name passed in - resolvedPath = extension.ItemSpec; - } - } - } - } - - if (String.IsNullOrEmpty(className)) - { - this.AppendSwitchIfNotNull("-ext ", resolvedPath); - } - else - { - this.AppendSwitchIfNotNull("-ext ", className + ", " + resolvedPath); - } - } - } - - /// - /// Append arbitrary text to the command-line if specified. - /// - /// Text to append. - public void AppendTextIfNotNull(string textToAppend) - { - if (!String.IsNullOrEmpty(textToAppend)) - { - this.AppendSpaceIfNotEmpty(); - this.AppendTextUnquoted(textToAppend); - } - } - - /// - /// Append arbitrary text to the command-line if specified. - /// - /// Text to append. - public void AppendTextIfNotWhitespace(string textToAppend) - { - if (!String.IsNullOrWhiteSpace(textToAppend)) - { - this.AppendSpaceIfNotEmpty(); - this.AppendTextUnquoted(textToAppend); - } - } - } -} diff --git a/src/wix/WixToolset.BuildTasks/WixExeBaseTask.cs b/src/wix/WixToolset.BuildTasks/WixExeBaseTask.cs index 5583f64e..72be2fe6 100644 --- a/src/wix/WixToolset.BuildTasks/WixExeBaseTask.cs +++ b/src/wix/WixToolset.BuildTasks/WixExeBaseTask.cs @@ -2,10 +2,12 @@ namespace WixToolset.BuildTasks { + using WixToolset.BaseBuildTasks; + /// /// An MSBuild task to run WiX to update cabinet signatures in a MSI. /// - public abstract class WixExeBaseTask : ToolsetTask + public abstract class WixExeBaseTask : BaseToolsetTask { protected override string ToolName => "wix.exe"; } diff --git a/src/wix/WixToolset.BuildTasks/WixToolset.BuildTasks.csproj b/src/wix/WixToolset.BuildTasks/WixToolset.BuildTasks.csproj index 92651ed2..8088462f 100644 --- a/src/wix/WixToolset.BuildTasks/WixToolset.BuildTasks.csproj +++ b/src/wix/WixToolset.BuildTasks/WixToolset.BuildTasks.csproj @@ -12,7 +12,8 @@ - + + -- cgit v1.2.3-55-g6feb