From 9aa2910e79ce52144c5296077aa2444876419643 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Tue, 15 Mar 2022 14:01:07 -0700 Subject: Rework build command line for combining wixlibs and default output Changes the command line handling for the "build" command to allow creation of a .wixlib to accept compiled (but not linked) intermediates. This will allow .wixlibs to combine separate build commands (potentially with different "-arch" switches) into a single .wixlib. This change also fixes the issue where by default output was being written to the intermediate folder instead of the current directory. Fixes 6464 Fixes 6473 --- .../WixToolset.Core/CommandLine/BuildCommand.cs | 263 ++++++++++++--------- .../BadInputFixture.cs | 15 -- .../CommandLineFixture.cs | 59 +++++ .../TestData/SimplePackage/SimplePackage.wxs | 11 + .../TestData/WixlibMultiarch/MultiarchFile.wxs | 11 + .../WixlibFixture.cs | 43 ++++ 6 files changed, 277 insertions(+), 125 deletions(-) create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/CommandLineFixture.cs create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimplePackage/SimplePackage.wxs create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/WixlibMultiarch/MultiarchFile.wxs (limited to 'src') diff --git a/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs b/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs index 67d2876d..f291fa8c 100644 --- a/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs +++ b/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs @@ -49,18 +49,8 @@ namespace WixToolset.Core.CommandLine private string IntermediateFolder { get; set; } - private OutputType OutputType { get; set; } - - private List IncludeSearchPaths { get; set; } - - public string PdbFile { get; set; } - - public PdbType PdbType { get; set; } - private Platform Platform { get; set; } - private string OutputFile { get; set; } - private CompressionLevel? DefaultCompressionLevel { get; set; } private string TrackingFile { get; set; } @@ -75,93 +65,70 @@ namespace WixToolset.Core.CommandLine this.IntermediateFolder = this.commandLine.CalculateIntermedateFolder(); - this.OutputType = this.commandLine.CalculateOutputType(); - - this.IncludeSearchPaths = this.commandLine.IncludeSearchPaths; - - this.PdbFile = this.commandLine.PdbFile; - - this.PdbType = this.commandLine.PdbType; - this.Platform = this.commandLine.Platform; this.TrackingFile = this.commandLine.TrackingFile; this.DefaultCompressionLevel = this.commandLine.DefaultCompressionLevel; - var preprocessorVariables = this.commandLine.GatherPreprocessorVariables(); - - var sourceFiles = this.commandLine.GatherSourceFiles(this.IntermediateFolder); + var preprocessorVariables = this.commandLine.CalculatePreprocessorVariables(); var filterCultures = this.commandLine.CalculateFilterCultures(); var creator = this.ServiceProvider.GetService(); - this.EvaluateSourceFiles(sourceFiles, creator, out var codeFiles, out var wixipl); - - this.OutputFile = this.commandLine.OutputFile; - - if (String.IsNullOrEmpty(this.OutputFile)) - { - if (codeFiles.Count == 1) - { - // If output type is unknown, the extension will be replaced with the right default based on output type. - this.OutputFile = Path.ChangeExtension(codeFiles[0].OutputPath, DefaultExtensionForOutputType(this.OutputType)); - } - else - { - this.Messaging.Write(ErrorMessages.MustSpecifyOutputWithMoreThanOneInput()); - } - } + var inputsOutputs = this.commandLine.CalculateInputsAndOutputs(creator); if (this.Messaging.EncounteredError) { return Task.FromResult(this.Messaging.LastErrorNumber); } - var wixobjs = this.CompilePhase(preprocessorVariables, codeFiles, cancellationToken); + var wixobjs = this.CompilePhase(preprocessorVariables, inputsOutputs.SourcePaths, this.commandLine.IncludeSearchPaths, cancellationToken); - var wxls = this.LoadLocalizationFiles(this.commandLine.LocalizationFilePaths, preprocessorVariables, cancellationToken); + var wxls = this.LoadLocalizationFiles(inputsOutputs.LocalizationPaths, preprocessorVariables, this.commandLine.IncludeSearchPaths, cancellationToken); if (this.Messaging.EncounteredError) { return Task.FromResult(this.Messaging.LastErrorNumber); } - if (this.OutputType == OutputType.Library) + if (inputsOutputs.OutputType == OutputType.Library) { using (new IntermediateFieldContext("wix.lib")) { - this.LibraryPhase(wixobjs, wxls, this.commandLine.BindFiles, this.commandLine.BindPaths, cancellationToken); + this.LibraryPhase(wixobjs, wxls, inputsOutputs.LibraryPaths, creator, this.commandLine.BindFiles, this.commandLine.BindPaths, inputsOutputs.OutputPath, cancellationToken); } } else { using (new IntermediateFieldContext("wix.link")) { + var wixipl = inputsOutputs.Wixipls.SingleOrDefault(); + if (wixipl == null) { - wixipl = this.LinkPhase(wixobjs, this.commandLine.LibraryFilePaths, creator, cancellationToken); + wixipl = this.LinkPhase(wixobjs, inputsOutputs, creator, cancellationToken); } if (!this.Messaging.EncounteredError) { - var outputExtension = Path.GetExtension(this.OutputFile); + var outputExtension = Path.GetExtension(inputsOutputs.OutputPath); if (String.IsNullOrEmpty(outputExtension) || ".wix" == outputExtension) { var entrySectionType = wixipl.Sections.Single().Type; - this.OutputFile = Path.ChangeExtension(this.OutputFile, DefaultExtensionForSectionType(entrySectionType)); + inputsOutputs.OutputPath = Path.ChangeExtension(inputsOutputs.OutputPath, DefaultExtensionForSectionType(entrySectionType)); } - if (this.OutputType == OutputType.IntermediatePostLink) + if (inputsOutputs.OutputType == OutputType.IntermediatePostLink) { - wixipl.Save(this.OutputFile); + wixipl.Save(inputsOutputs.OutputPath); } else { using (new IntermediateFieldContext("wix.bind")) { - this.BindPhase(wixipl, wxls, filterCultures, this.commandLine.CabCachePath, this.commandLine.BindPaths, cancellationToken); + this.BindPhase(wixipl, wxls, filterCultures, this.commandLine.CabCachePath, this.commandLine.BindPaths, inputsOutputs, cancellationToken); } } } @@ -176,51 +143,13 @@ namespace WixToolset.Core.CommandLine return this.commandLine.TryParseArgument(argument, parser); } - private void EvaluateSourceFiles(IEnumerable sourceFiles, ISymbolDefinitionCreator creator, out List codeFiles, out Intermediate wixipl) - { - codeFiles = new List(); - - wixipl = null; - - foreach (var sourceFile in sourceFiles) - { - var extension = Path.GetExtension(sourceFile.SourcePath); - - if (wixipl != null || ".wxs".Equals(extension, StringComparison.OrdinalIgnoreCase)) - { - codeFiles.Add(sourceFile); - } - else - { - try - { - wixipl = Intermediate.Load(sourceFile.SourcePath, creator); - } - catch (WixException) - { - // We'll assume anything that isn't a valid intermediate is source code to compile. - codeFiles.Add(sourceFile); - } - } - } - - if (wixipl == null && codeFiles.Count == 0) - { - this.Messaging.Write(ErrorMessages.NoSourceFiles()); - } - else if (wixipl != null && codeFiles.Count != 0) - { - this.Messaging.Write(ErrorMessages.WixiplSourceFileIsExclusive()); - } - } - - private IReadOnlyList CompilePhase(IDictionary preprocessorVariables, IEnumerable sourceFiles, CancellationToken cancellationToken) + private IReadOnlyList CompilePhase(IDictionary preprocessorVariables, IEnumerable sourceFiles, IReadOnlyCollection includeSearchPaths, CancellationToken cancellationToken) { var intermediates = new List(); foreach (var sourceFile in sourceFiles) { - var document = this.Preprocess(preprocessorVariables, sourceFile.SourcePath, cancellationToken); + var document = this.Preprocess(preprocessorVariables, sourceFile, includeSearchPaths, cancellationToken); if (this.Messaging.EncounteredError) { @@ -255,14 +184,21 @@ namespace WixToolset.Core.CommandLine return intermediates; } - private void LibraryPhase(IReadOnlyCollection intermediates, IReadOnlyCollection localizations, bool bindFiles, IReadOnlyCollection bindPaths, CancellationToken cancellationToken) + private void LibraryPhase(IReadOnlyCollection intermediates, IReadOnlyCollection localizations, IEnumerable libraryFiles, ISymbolDefinitionCreator creator, bool bindFiles, IReadOnlyCollection bindPaths, string outputPath, CancellationToken cancellationToken) { + var libraries = this.LoadLibraries(libraryFiles, creator); + + if (this.Messaging.EncounteredError) + { + return; + } + var context = this.ServiceProvider.GetService(); context.BindFiles = bindFiles; context.BindPaths = bindPaths; context.Extensions = this.ExtensionManager.GetServices(); context.Localizations = localizations; - context.Intermediates = intermediates; + context.Intermediates = intermediates.Concat(libraries).ToList(); context.CancellationToken = cancellationToken; try @@ -272,7 +208,7 @@ namespace WixToolset.Core.CommandLine if (!this.Messaging.EncounteredError) { - result.Library.Save(this.OutputFile); + result.Library.Save(outputPath); this.LayoutFiles(this.IntermediateFolder, result.TrackedFiles, null, cancellationToken); } @@ -283,9 +219,9 @@ namespace WixToolset.Core.CommandLine } } - private Intermediate LinkPhase(IEnumerable intermediates, IEnumerable libraryFiles, ISymbolDefinitionCreator creator, CancellationToken cancellationToken) + private Intermediate LinkPhase(IEnumerable intermediates, InputsAndOutputs inputsOutputs, ISymbolDefinitionCreator creator, CancellationToken cancellationToken) { - var libraries = this.LoadLibraries(libraryFiles, creator); + var libraries = this.LoadLibraries(inputsOutputs.LibraryPaths, creator); if (this.Messaging.EncounteredError) { @@ -295,7 +231,7 @@ namespace WixToolset.Core.CommandLine var context = this.ServiceProvider.GetService(); context.Extensions = this.ExtensionManager.GetServices(); context.ExtensionData = this.ExtensionManager.GetServices(); - context.ExpectedOutputType = this.OutputType; + context.ExpectedOutputType = inputsOutputs.OutputType; context.Intermediates = intermediates.Concat(libraries).ToList(); context.SymbolDefinitionCreator = creator; context.CancellationToken = cancellationToken; @@ -304,7 +240,7 @@ namespace WixToolset.Core.CommandLine return linker.Link(context); } - private void BindPhase(Intermediate output, IReadOnlyCollection localizations, IReadOnlyCollection filterCultures, string cabCachePath, IReadOnlyCollection bindPaths, CancellationToken cancellationToken) + private void BindPhase(Intermediate output, IReadOnlyCollection localizations, IReadOnlyCollection filterCultures, string cabCachePath, IReadOnlyCollection bindPaths, InputsAndOutputs inputsOutputs, CancellationToken cancellationToken) { var intermediateFolder = this.IntermediateFolder; if (String.IsNullOrEmpty(intermediateFolder)) @@ -350,9 +286,9 @@ namespace WixToolset.Core.CommandLine context.FileSystemExtensions = this.ExtensionManager.GetServices(); context.IntermediateFolder = intermediateFolder; context.IntermediateRepresentation = resolveResult.IntermediateRepresentation; - context.OutputPath = this.OutputFile; - context.PdbType = this.PdbType; - context.PdbPath = this.PdbType == PdbType.None ? null : this.PdbFile ?? Path.ChangeExtension(this.OutputFile, ".wixpdb"); + context.OutputPath = inputsOutputs.OutputPath; + context.PdbType = inputsOutputs.PdbType; + context.PdbPath = inputsOutputs.PdbPath; context.CancellationToken = cancellationToken; var binder = this.ServiceProvider.GetService(); @@ -405,14 +341,14 @@ namespace WixToolset.Core.CommandLine return Array.Empty(); } - private IReadOnlyList LoadLocalizationFiles(IEnumerable locFiles, IDictionary preprocessorVariables, CancellationToken cancellationToken) + private IReadOnlyList LoadLocalizationFiles(IEnumerable locFiles, IDictionary preprocessorVariables, IReadOnlyCollection includeSearchPaths, CancellationToken cancellationToken) { var localizations = new List(); var parser = this.ServiceProvider.GetService(); foreach (var loc in locFiles) { - var document = this.Preprocess(preprocessorVariables, loc, cancellationToken); + var document = this.Preprocess(preprocessorVariables, loc, includeSearchPaths, cancellationToken); if (this.Messaging.EncounteredError) { @@ -426,12 +362,12 @@ namespace WixToolset.Core.CommandLine return localizations; } - private XDocument Preprocess(IDictionary preprocessorVariables, string sourcePath, CancellationToken cancellationToken) + private XDocument Preprocess(IDictionary preprocessorVariables, string sourcePath, IReadOnlyCollection includeSearchPaths, CancellationToken cancellationToken) { var context = this.ServiceProvider.GetService(); context.Extensions = this.ExtensionManager.GetServices(); context.Platform = this.Platform; - context.IncludeSearchPaths = this.IncludeSearchPaths; + context.IncludeSearchPaths = includeSearchPaths; context.SourcePath = sourcePath; context.Variables = preprocessorVariables; context.CancellationToken = cancellationToken; @@ -519,6 +455,8 @@ namespace WixToolset.Core.CommandLine public List SourceFilePaths { get; } = new List(); + public List UnevaluatedInputFilePaths { get; } = new List(); + public Platform Platform { get; private set; } public string PdbFile { get; private set; } @@ -632,6 +570,10 @@ namespace WixToolset.Core.CommandLine parser.GetNextArgumentAsFilePathOrError(arg, "library files", this.LibraryFilePaths); return true; + case "src": + parser.GetNextArgumentAsFilePathOrError(arg, "source code", this.SourceFilePaths); + return true; + case "o": case "out": this.OutputFile = parser.GetNextArgumentAsFilePathOrError(arg); @@ -665,7 +607,7 @@ namespace WixToolset.Core.CommandLine } else { - parser.GetArgumentAsFilePathOrError(arg, "source code", this.SourceFilePaths); + parser.GetArgumentAsFilePathOrError(arg, "input file", this.UnevaluatedInputFilePaths); return true; } } @@ -747,7 +689,7 @@ namespace WixToolset.Core.CommandLine return result; } - public IDictionary GatherPreprocessorVariables() + public IDictionary CalculatePreprocessorVariables() { var variables = new Dictionary(); @@ -767,19 +709,89 @@ namespace WixToolset.Core.CommandLine return variables; } - public IEnumerable GatherSourceFiles(string intermediateDirectory) + public InputsAndOutputs CalculateInputsAndOutputs(ISymbolDefinitionCreator creator) { - var files = new List(); + var codePaths = new List(this.SourceFilePaths); + var localizationPaths = new List(this.LocalizationFilePaths); + var libraryPaths = new List(this.LibraryFilePaths); + var wixipls = new List(); + string lastWixiplPath = null; - foreach (var item in this.SourceFilePaths) + var outputPath = this.OutputFile; + var outputType = this.CalculateOutputType(); + + foreach (var path in this.UnevaluatedInputFilePaths) { - var sourcePath = item; - var outputPath = Path.Combine(intermediateDirectory, Path.GetFileNameWithoutExtension(sourcePath) + ".wir"); + var extension = Path.GetExtension(path); + + if (".wxs".Equals(extension, StringComparison.OrdinalIgnoreCase)) + { + codePaths.Add(path); + } + else if (".wxl".Equals(extension, StringComparison.OrdinalIgnoreCase)) + { + localizationPaths.Add(path); + } + else if (".wixlib".Equals(extension, StringComparison.OrdinalIgnoreCase)) + { + libraryPaths.Add(path); + } + else + { + try + { + // Try to load the file as an intermediate to determine whether it is a + // .wixipl or a .wixlib. + var intermediate = Intermediate.Load(path, creator); - files.Add(new SourceFile(sourcePath, outputPath)); + if (intermediate.HasLevel(IntermediateLevels.Linked)) + { + wixipls.Add(intermediate); + lastWixiplPath = path; + } + else + { + libraryPaths.Add(path); + } + } + catch (WixException) + { + // We'll assume anything that isn't a valid intermediate is source code to compile. + codePaths.Add(path); + } + } } - return files; + if (wixipls.Count > 0) + { + if (wixipls.Count > 1 || codePaths.Count > 0 || libraryPaths.Count > 0) + { + this.Messaging.Write(ErrorMessages.WixiplSourceFileIsExclusive()); + } + } + else if (codePaths.Count == 0 && libraryPaths.Count == 0) + { + this.Messaging.Write(ErrorMessages.NoSourceFiles()); + } + + if (!this.Messaging.EncounteredError && String.IsNullOrEmpty(outputPath)) + { + var singleInputPath = codePaths.Count == 1 ? codePaths[0] : lastWixiplPath; + + if (String.IsNullOrEmpty(singleInputPath)) + { + this.Messaging.Write(ErrorMessages.MustSpecifyOutputWithMoreThanOneInput()); + } + else + { + // If output type is unknown, the extension will be replaced with the right default based on output type. + outputPath = Path.ChangeExtension(singleInputPath, DefaultExtensionForOutputType(outputType)); + } + } + + var pdbPath = this.PdbType == PdbType.None ? null : this.PdbFile ?? Path.ChangeExtension(outputPath ?? "error.above", ".wixpdb"); + + return new InputsAndOutputs(codePaths, localizationPaths, libraryPaths, wixipls, outputPath, outputType, pdbPath, this.PdbType); } private bool TryParseBindPath(string bindPath, out IBindPath bp) @@ -807,5 +819,36 @@ namespace WixToolset.Core.CommandLine return true; } } + + private class InputsAndOutputs + { + public InputsAndOutputs(IReadOnlyCollection sourcePaths, IReadOnlyCollection localizationPaths, IReadOnlyCollection libraryPaths, IReadOnlyCollection wixipls, string outputPath, OutputType outputType, string pdbPath, PdbType pdbType) + { + this.SourcePaths = sourcePaths; + this.LocalizationPaths = localizationPaths; + this.LibraryPaths = libraryPaths; + this.Wixipls = wixipls; + this.OutputPath = outputPath; + this.OutputType = outputType; + this.PdbPath = pdbPath; + this.PdbType = pdbType; + } + + public IReadOnlyCollection SourcePaths { get; } + + public IReadOnlyCollection LocalizationPaths { get; } + + public IReadOnlyCollection LibraryPaths { get; } + + public IReadOnlyCollection Wixipls { get; } + + public string OutputPath { get; set; } + + public OutputType OutputType { get; } + + public string PdbPath { get; } + + public PdbType PdbType { get; } + } } } diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BadInputFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BadInputFixture.cs index 62ffe1eb..f91c0ab0 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/BadInputFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/BadInputFixture.cs @@ -6,25 +6,10 @@ namespace WixToolsetTest.CoreIntegration using System.IO; using WixBuildTools.TestSupport; using WixToolset.Core.TestPackage; - using WixToolset.Data; using Xunit; public class BadInputFixture { - [Fact] - public void SwitchIsNotConsideredAnArgument() - { - var result = WixRunner.Execute(new[] - { - "build", - "-bindpath", "-thisisaswitchnotanarg", - }); - - Assert.Single(result.Messages, m => m.Id == (int)ErrorMessages.Ids.ExpectedArgument); - // TODO: when CantBuildSingleExeBundleWithInvalidArgument is fixed, uncomment: - //Assert.Equal((int)ErrorMessages.Ids.ExpectedArgument, result.ExitCode); - } - [Fact] public void HandleInvalidIds() { diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/CommandLineFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/CommandLineFixture.cs new file mode 100644 index 00000000..1b0f9633 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/CommandLineFixture.cs @@ -0,0 +1,59 @@ +// 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 WixToolsetTest.CoreIntegration +{ + using System.IO; + using System.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Core.TestPackage; + using Xunit; + + public class CommandLineFixture + { + [Fact] + public void SwitchIsNotConsideredAnArgument() + { + var result = WixRunner.Execute(new[] + { + "build", + "-bindpath", "-thisisaswitchnotanarg", + }); + + WixAssert.CompareLineByLine(new[] + { + "-bindpath is expected to be followed by a value. See -? for additional detail.", + "Additional argument '-bindpath' was unexpected. Remove the argument and add the '-?' switch for more information.", + "No source files specified." + }, result.Messages.Select(m => m.ToString()).ToArray()); + Assert.Equal(391, result.ExitCode); + } + + [Fact] + public void CanBuildWithNoOutputSpecified() + { + var folder = TestData.Get(@"TestData", "SimplePackage"); + var bindFolder = TestData.Get(@"TestData", "SingleFile", "data"); + + using (var fs = new DisposableFileSystem()) + { + var testFolder = fs.GetFolder(create: true); + var srcFile = Path.Combine(testFolder, "SimplePackage.wxs"); + var intermediateFolder = Path.Combine(testFolder, "obj"); + var expectedPath = Path.Combine(testFolder, "SimplePackage.msi"); + + // Copy the source folder into the test working folder so the output can be written to the same folder. + File.Copy(Path.Combine(folder, "SimplePackage.wxs"), srcFile); + + var result = WixRunner.Execute(new[] + { + "build", srcFile, + "-bindpath", bindFolder, + "-intermediateFolder", intermediateFolder + }); + + result.AssertSuccess(); + Assert.True(File.Exists(expectedPath), $"Expected to build MSI to: {expectedPath}"); + } + } + } +} diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimplePackage/SimplePackage.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimplePackage/SimplePackage.wxs new file mode 100644 index 00000000..0325867c --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimplePackage/SimplePackage.wxs @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/WixlibMultiarch/MultiarchFile.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/WixlibMultiarch/MultiarchFile.wxs new file mode 100644 index 00000000..c74bf370 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/WixlibMultiarch/MultiarchFile.wxs @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/WixlibFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/WixlibFixture.cs index 00b83de8..01b82eb3 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/WixlibFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/WixlibFixture.cs @@ -52,6 +52,49 @@ namespace WixToolsetTest.CoreIntegration } } + [Fact] + public void CanBuildMultiarchWixlib() + { + var folder = TestData.Get(@"TestData", "WixlibMultiarch"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var wixlibPath = Path.Combine(intermediateFolder, @"test.wixlib"); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "MultiarchFile.wxs"), + "-intermediateFolder", intermediateFolder, + "-o", wixlibPath + }); + + result.AssertSuccess(); + + result = WixRunner.Execute(new[] + { + "build", + "-arch", "x64", + Path.Combine(folder, "MultiarchFile.wxs"), + wixlibPath, + "-intermediateFolder", intermediateFolder, + "-o", wixlibPath + }); + + result.AssertSuccess(); + + var wixlib = Intermediate.Load(wixlibPath); + var componentSymbols = wixlib.Sections.SelectMany(s => s.Symbols).OfType().ToList(); + WixAssert.CompareLineByLine(new[] + { + "x64 filcV1yrx0x8wJWj4qMzcH21jwkPko", + "x86 filcV1yrx0x8wJWj4qMzcH21jwkPko", + }, componentSymbols.Select(c => (c.Win64 ? "x64 " : "x86 ") + c.Id.Id).OrderBy(s => s).ToArray()); + } + } + [Fact] public void CanBuildWixlibWithBinariesFromNamedBindPaths() { -- cgit v1.2.3-55-g6feb