Move Directory code generation to the linker
Adding all referenced standard directories requires access to the references. However, references do no survive the linker. Which means the binder is too late to add standard directories. Fixes 6977
Rob Mensching committed
Nov 4, 2022 at 12:26 UTC
184fd7663696e52fe5386f6623b3313a41e05979
5 files changed
+63
-74
src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
-6
@@ -171,12 +171,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
171
command.Execute();
172
}
173
174
- if (section.Type == SectionType.Product || section.Type == SectionType.Module)
175
- {
176
- var command = new AddRequiredStandardDirectories(section, platform);
177
- command.Execute();
178
- }
179
-
174
{
175
var command = new CreateSpecialPropertiesCommand(section);
176
command.Execute();
src/wix/WixToolset.Core/Compiler.cs
+5
@@ -7131,6 +7131,11 @@ namespace WixToolset.Core
7131
this.Core.ParseExtensionElement(node, child);
7132
}
7133
}
7134
+
7135
+ if (!this.Core.EncounteredError)
7136
+ {
7137
+ this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Directory, id);
7138
+ }
7139
}
7140
7141
/// <summary>
src/wix/WixToolset.Core/Link/AddRequiredStandardDirectories.cs
renamed
+40
-10
@@ -1,6 +1,6 @@
1
// 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.
2
3
-namespace WixToolset.Core.WindowsInstaller.Bind
3
+namespace WixToolset.Core.Link
4
{
5
using System;
6
using System.Collections.Generic;
@@ -14,21 +14,29 @@ namespace WixToolset.Core.WindowsInstaller.Bind
14
/// </summary>
15
internal class AddRequiredStandardDirectories
16
{
17
- internal AddRequiredStandardDirectories(IntermediateSection section, Platform platform)
17
+ public AddRequiredStandardDirectories(IntermediateSection section, List<WixSimpleReferenceSymbol> references)
18
{
19
this.Section = section;
20
- this.Platform = platform;
20
+ this.References = references;
21
}
22
23
private IntermediateSection Section { get; }
24
25
- private Platform Platform { get; }
25
+ private List<WixSimpleReferenceSymbol> References { get; }
26
27
public void Execute()
28
{
29
+ var platform = this.GetPlatformFromSection();
30
+
31
var directories = this.Section.Symbols.OfType<DirectorySymbol>().ToList();
32
var directoryIds = new SortedSet<string>(directories.Select(d => d.Id.Id));
33
34
+ // Ensure any standard directory references symbols are added.
35
+ foreach (var directoryReference in this.References.Where(r => r.Table == "Directory"))
36
+ {
37
+ this.EnsureStandardDirectoryAdded(directoryIds, directoryReference.PrimaryKeys, directoryReference.SourceLineNumbers, platform);
38
+ }
39
+
40
foreach (var directory in directories)
41
{
42
var parentDirectoryId = directory.ParentDirectoryRef;
@@ -42,7 +50,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
50
}
51
else
52
{
45
- this.EnsureStandardDirectoryAdded(directoryIds, parentDirectoryId, directory.SourceLineNumbers);
53
+ this.EnsureStandardDirectoryAdded(directoryIds, parentDirectoryId, directory.SourceLineNumbers, platform);
54
}
55
}
56
@@ -53,11 +61,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
61
}
62
}
63
56
- private void EnsureStandardDirectoryAdded(ISet<string> directoryIds, string directoryId, SourceLineNumber sourceLineNumbers)
64
+ private void EnsureStandardDirectoryAdded(ISet<string> directoryIds, string directoryId, SourceLineNumber sourceLineNumbers, Platform platform)
65
{
66
if (!directoryIds.Contains(directoryId) && WindowsInstallerStandard.TryGetStandardDirectory(directoryId, out var standardDirectory))
67
{
60
- var parentDirectoryId = this.GetStandardDirectoryParent(directoryId);
68
+ var parentDirectoryId = this.GetStandardDirectoryParent(directoryId, platform);
69
70
var directory = new DirectorySymbol(sourceLineNumbers, standardDirectory.Id)
71
{
@@ -70,12 +78,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
78
79
if (!String.IsNullOrEmpty(parentDirectoryId))
80
{
73
- this.EnsureStandardDirectoryAdded(directoryIds, parentDirectoryId, sourceLineNumbers);
81
+ this.EnsureStandardDirectoryAdded(directoryIds, parentDirectoryId, sourceLineNumbers, platform);
82
}
83
}
84
}
85
78
- private string GetStandardDirectoryParent(string directoryId)
86
+ private string GetStandardDirectoryParent(string directoryId, Platform platform)
87
{
88
switch (directoryId)
89
{
@@ -85,11 +93,33 @@ namespace WixToolset.Core.WindowsInstaller.Bind
93
case "CommonFiles6432Folder":
94
case "ProgramFiles6432Folder":
95
case "System6432Folder":
88
- return WindowsInstallerStandard.GetPlatformSpecificDirectoryId(directoryId, this.Platform);
96
+ return WindowsInstallerStandard.GetPlatformSpecificDirectoryId(directoryId, platform);
97
98
default:
99
return "TARGETDIR";
100
}
101
}
102
+
103
+ private Platform GetPlatformFromSection()
104
+ {
105
+ var symbol = this.Section.Symbols.OfType<SummaryInformationSymbol>().First(p => p.PropertyId == SummaryInformationType.PlatformAndLanguage);
106
+
107
+ var value = symbol.Value;
108
+ var separatorIndex = value.IndexOf(';');
109
+ var platformValue = separatorIndex > 0 ? value.Substring(0, separatorIndex) : value;
110
+
111
+ switch (platformValue)
112
+ {
113
+ case "x64":
114
+ return Platform.X64;
115
+
116
+ case "Arm64":
117
+ return Platform.ARM64;
118
+
119
+ case "Intel":
120
+ default:
121
+ return Platform.X86;
122
+ }
123
+ }
124
}
125
}
src/wix/WixToolset.Core/Linker.cs
+8
-2
@@ -90,8 +90,6 @@ namespace WixToolset.Core
90
}
91
}
92
93
- //this.activeOutput = null;
94
-
93
var multipleFeatureComponents = new Hashtable();
94
95
var wixVariables = new Dictionary<string, WixVariableSymbol>();
@@ -178,6 +176,7 @@ namespace WixToolset.Core
176
// Create a new section to hold the linked content. Start with the entry section's
177
// metadata.
178
var resolvedSection = new IntermediateSection(find.EntrySection.Id, find.EntrySection.Type);
179
+ var references = new List<WixSimpleReferenceSymbol>();
180
181
foreach (var section in sections)
182
{
@@ -248,6 +247,7 @@ namespace WixToolset.Core
247
248
case SymbolDefinitionType.WixSimpleReference:
249
copySymbol = false;
250
+ references.Add(symbol as WixSimpleReferenceSymbol);
251
break;
252
253
case SymbolDefinitionType.WixVariable:
@@ -288,6 +288,12 @@ namespace WixToolset.Core
288
var command = new FlattenAndProcessBundleTablesCommand(resolvedSection, this.Messaging);
289
command.Execute();
290
}
291
+ else if (resolvedSection.Type == SectionType.Product || resolvedSection.Type == SectionType.Module)
292
+ {
293
+ // Packages and modules get standard directories add.
294
+ var command = new AddRequiredStandardDirectories(resolvedSection, references);
295
+ command.Execute();
296
+ }
297
298
if (this.Messaging.EncounteredError)
299
{
src/wix/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs
+10
-56
@@ -97,54 +97,8 @@ namespace WixToolsetTest.CoreIntegration
97
{
98
var baseFolder = fs.GetFolder();
99
var intermediateFolder = Path.Combine(baseFolder, "obj");
100
- var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
101
-
102
- var result = WixRunner.Execute(new[]
103
- {
104
- "build",
105
- Path.Combine(folder, "Directory", "DefaultName.wxs"),
106
- Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
107
- "-bindpath", Path.Combine(folder, "SingleFile", "data"),
108
- "-intermediateFolder", intermediateFolder,
109
- "-o", msiPath
110
- });
111
-
112
- result.AssertSuccess();
113
-
114
- var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb"));
115
- var section = intermediate.Sections.Single();
116
-
117
- var dirSymbols = section.Symbols.OfType<WixToolset.Data.Symbols.DirectorySymbol>().ToList();
118
- WixAssert.CompareLineByLine(new[]
119
- {
120
- "BinFolder\tCompanyFolder\t.",
121
- "CompanyFolder\tProgramFilesFolder\tExample Corporation",
122
- "ProgramFilesFolder\tTARGETDIR\tPFiles",
123
- "TARGETDIR\t\tSourceDir"
124
- }, dirSymbols.OrderBy(d => d.Id.Id).Select(d => String.Join('\t', d.Id.Id, d.ParentDirectoryRef, d.Name)).ToArray());
125
-
126
- var data = WindowsInstallerData.Load(Path.Combine(baseFolder, @"bin\test.wixpdb"));
127
- var directoryRows = data.Tables["Directory"].Rows;
128
- WixAssert.CompareLineByLine(new[]
129
- {
130
- "BinFolder\tCompanyFolder\t.",
131
- "CompanyFolder\tProgramFilesFolder\tu7-b4gch|Example Corporation",
132
- "ProgramFilesFolder\tTARGETDIR\tPFiles",
133
- "TARGETDIR\t\tSourceDir"
134
- }, directoryRows.Select(r => String.Join('\t', r.FieldAsString(0), r.FieldAsString(1), r.FieldAsString(2))).ToArray());
135
- }
136
- }
137
-
138
- [Fact(Skip = "https://github.com/wixtoolset/issues/issues/6977")]
139
- public void CanGetEmptyStandardDirectory()
140
- {
141
- var folder = TestData.Get(@"TestData");
142
-
143
- using (var fs = new DisposableFileSystem())
144
- {
145
- var baseFolder = fs.GetFolder();
146
- var intermediateFolder = Path.Combine(baseFolder, "obj");
147
- var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
100
+ var msiPath = Path.Combine(baseFolder, "bin", "test.msi");
101
+ var wixpdbPath = Path.Combine(baseFolder, "bin", "test.wixpdb");
102
103
var result = WixRunner.Execute(new[]
104
{
@@ -158,7 +112,7 @@ namespace WixToolsetTest.CoreIntegration
112
113
result.AssertSuccess();
114
161
- var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb"));
115
+ var intermediate = Intermediate.Load(wixpdbPath);
116
var section = intermediate.Sections.Single();
117
118
var dirSymbols = section.Symbols.OfType<WixToolset.Data.Symbols.DirectorySymbol>().ToList();
@@ -166,23 +120,23 @@ namespace WixToolsetTest.CoreIntegration
120
{
121
"BinFolder\tCompanyFolder\t.",
122
"CompanyFolder\tProgramFilesFolder\tExample Corporation",
169
- "DesktopFolder\tTARGETDIR\t.",
123
+ "DesktopFolder\tTARGETDIR\tDesktop",
124
"ProgramFilesFolder\tTARGETDIR\tPFiles",
171
- "ProgramMenuFolder\tTARGETDIR\t.",
125
+ "ProgramMenuFolder\tTARGETDIR\tPMenu",
126
"TARGETDIR\t\tSourceDir"
173
- }, dirSymbols.OrderBy(d => d.Id.Id).Select(d => String.Join('\t', d.Id.Id, d.ParentDirectoryRef, d.Name)).ToArray());
127
+ }, dirSymbols.Select(d => String.Join('\t', d.Id.Id, d.ParentDirectoryRef, d.Name)).OrderBy(s => s).ToArray());
128
175
- var data = WindowsInstallerData.Load(Path.Combine(baseFolder, @"bin\test.wixpdb"));
129
+ var data = WindowsInstallerData.Load(wixpdbPath);
130
var directoryRows = data.Tables["Directory"].Rows;
131
WixAssert.CompareLineByLine(new[]
132
{
133
"BinFolder\tCompanyFolder\t.",
134
"CompanyFolder\tProgramFilesFolder\tu7-b4gch|Example Corporation",
181
- "DesktopFolder\tTARGETDIR\t.",
135
+ "DesktopFolder\tTARGETDIR\tDesktop",
136
"ProgramFilesFolder\tTARGETDIR\tPFiles",
183
- "ProgramMenuFolder\tTARGETDIR\t.",
137
+ "ProgramMenuFolder\tTARGETDIR\tPMenu",
138
"TARGETDIR\t\tSourceDir"
185
- }, directoryRows.Select(r => String.Join('\t', r.FieldAsString(0), r.FieldAsString(1), r.FieldAsString(2))).ToArray());
139
+ }, directoryRows.Select(r => String.Join('\t', r.FieldAsString(0), r.FieldAsString(1), r.FieldAsString(2))).OrderBy(s => s).ToArray());
140
}
141
}
142