aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/CommandLine
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2017-10-01 14:25:33 -0700
committerRob Mensching <rob@firegiant.com>2017-10-01 14:25:33 -0700
commit39c7e2bb0399802e65a3025c4a73db211e730479 (patch)
treecf53a931796c67b89cb48fb3a7a0cc4f30cb2c22 /src/WixToolset.Core/CommandLine
parente576d34c3f88b5da033d2516d1c16b0df9491523 (diff)
downloadwix-39c7e2bb0399802e65a3025c4a73db211e730479.tar.gz
wix-39c7e2bb0399802e65a3025c4a73db211e730479.tar.bz2
wix-39c7e2bb0399802e65a3025c4a73db211e730479.zip
Add support for BindPaths and building .wixlibs
Diffstat (limited to 'src/WixToolset.Core/CommandLine')
-rw-r--r--src/WixToolset.Core/CommandLine/BuildCommand.cs196
-rw-r--r--src/WixToolset.Core/CommandLine/CommandLine.cs115
2 files changed, 266 insertions, 45 deletions
diff --git a/src/WixToolset.Core/CommandLine/BuildCommand.cs b/src/WixToolset.Core/CommandLine/BuildCommand.cs
index ffb48305..d8954cb7 100644
--- a/src/WixToolset.Core/CommandLine/BuildCommand.cs
+++ b/src/WixToolset.Core/CommandLine/BuildCommand.cs
@@ -7,17 +7,24 @@ namespace WixToolset.Core
7 using System.IO; 7 using System.IO;
8 using System.Linq; 8 using System.Linq;
9 using WixToolset.Data; 9 using WixToolset.Data;
10 using WixToolset.Extensibility;
10 11
11 internal class BuildCommand : ICommand 12 internal class BuildCommand : ICommand
12 { 13 {
13 public BuildCommand(IEnumerable<SourceFile> sources, IDictionary<string, string> preprocessorVariables, IEnumerable<string> locFiles, string outputPath, IEnumerable<string> cultures, string contentsFile, string outputsFile, string builtOutputsFile, string wixProjectFile) 14 public BuildCommand(IEnumerable<SourceFile> sources, IDictionary<string, string> preprocessorVariables, IEnumerable<string> locFiles, IEnumerable<string> libraryFiles, string outputPath, OutputType outputType, IEnumerable<string> cultures, bool bindFiles, IEnumerable<BindPath> bindPaths, string intermediateFolder, string contentsFile, string outputsFile, string builtOutputsFile, string wixProjectFile)
14 { 15 {
15 this.LocFiles = locFiles; 16 this.LocFiles = locFiles;
17 this.LibraryFiles = libraryFiles;
16 this.PreprocessorVariables = preprocessorVariables; 18 this.PreprocessorVariables = preprocessorVariables;
17 this.SourceFiles = sources; 19 this.SourceFiles = sources;
18 this.OutputPath = outputPath; 20 this.OutputPath = outputPath;
21 this.OutputType = outputType;
19 22
20 this.Cultures = cultures; 23 this.Cultures = cultures;
24 this.BindFiles = bindFiles;
25 this.BindPaths = bindPaths;
26
27 this.IntermediateFolder = intermediateFolder ?? Path.GetTempPath();
21 this.ContentsFile = contentsFile; 28 this.ContentsFile = contentsFile;
22 this.OutputsFile = outputsFile; 29 this.OutputsFile = outputsFile;
23 this.BuiltOutputsFile = builtOutputsFile; 30 this.BuiltOutputsFile = builtOutputsFile;
@@ -26,14 +33,24 @@ namespace WixToolset.Core
26 33
27 public IEnumerable<string> LocFiles { get; } 34 public IEnumerable<string> LocFiles { get; }
28 35
36 public IEnumerable<string> LibraryFiles { get; }
37
29 private IEnumerable<SourceFile> SourceFiles { get; } 38 private IEnumerable<SourceFile> SourceFiles { get; }
30 39
31 private IDictionary<string, string> PreprocessorVariables { get; } 40 private IDictionary<string, string> PreprocessorVariables { get; }
32 41
33 private string OutputPath { get; } 42 private string OutputPath { get; }
34 43
44 private OutputType OutputType { get; }
45
35 public IEnumerable<string> Cultures { get; } 46 public IEnumerable<string> Cultures { get; }
36 47
48 public bool BindFiles { get; }
49
50 public IEnumerable<BindPath> BindPaths { get; }
51
52 public string IntermediateFolder { get; }
53
37 public string ContentsFile { get; } 54 public string ContentsFile { get; }
38 55
39 public string OutputsFile { get; } 56 public string OutputsFile { get; }
@@ -44,21 +61,135 @@ namespace WixToolset.Core
44 61
45 public int Execute() 62 public int Execute()
46 { 63 {
47 var intermediates = CompilePhase(); 64 var intermediates = this.CompilePhase();
65
66 var tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions());
67
68 if (this.OutputType == OutputType.Library)
69 {
70 this.LibraryPhase(intermediates, tableDefinitions);
71 }
72 else
73 {
74 var output = this.LinkPhase(intermediates, tableDefinitions);
75
76 if (!Messaging.Instance.EncounteredError)
77 {
78 this.BindPhase(output, tableDefinitions);
79 }
80 }
81
82 return Messaging.Instance.LastErrorNumber;
83 }
84
85 private IEnumerable<Intermediate> CompilePhase()
86 {
87 var intermediates = new List<Intermediate>();
88
89 var preprocessor = new Preprocessor();
90
91 var compiler = new Compiler();
92
93 foreach (var sourceFile in this.SourceFiles)
94 {
95 var document = preprocessor.Process(sourceFile.SourcePath, this.PreprocessorVariables);
96
97 var intermediate = compiler.Compile(document);
98
99 intermediates.Add(intermediate);
100 }
101
102 return intermediates;
103 }
104
105 private void LibraryPhase(IEnumerable<Intermediate> intermediates, TableDefinitionCollection tableDefinitions)
106 {
107 var localizations = this.LoadLocalizationFiles(tableDefinitions).ToList();
108
109 // If there was an error adding localization files, then bail.
110 if (Messaging.Instance.EncounteredError)
111 {
112 return;
113 }
48 114
49 var sections = intermediates.SelectMany(i => i.Sections).ToList(); 115 var sections = intermediates.SelectMany(i => i.Sections).ToList();
50 116
117 LibraryBinaryFileResolver resolver = null;
118
119 if (this.BindFiles)
120 {
121 resolver = new LibraryBinaryFileResolver();
122 resolver.FileManagers = new List<IBinderFileManager> { new BinderFileManager() }; ;
123 resolver.VariableResolver = new WixVariableResolver();
124
125 BinderFileManagerCore core = new BinderFileManagerCore();
126 core.AddBindPaths(this.BindPaths, BindStage.Normal);
127
128 foreach (var fileManager in resolver.FileManagers)
129 {
130 fileManager.Core = core;
131 }
132 }
133
134 var librarian = new Librarian();
135
136 var library = librarian.Combine(sections, localizations, resolver);
137
138 library?.Save(this.OutputPath);
139 }
140
141 private Output LinkPhase(IEnumerable<Intermediate> intermediates, TableDefinitionCollection tableDefinitions)
142 {
143 var sections = intermediates.SelectMany(i => i.Sections).ToList();
144
145 sections.AddRange(SectionsFromLibraries(tableDefinitions));
146
51 var linker = new Linker(); 147 var linker = new Linker();
52 148
53 var output = linker.Link(sections, OutputType.Product); 149 var output = linker.Link(sections, this.OutputType);
150
151 return output;
152 }
153
154 private IEnumerable<Section> SectionsFromLibraries(TableDefinitionCollection tableDefinitions)
155 {
156 var sections = new List<Section>();
157
158 if (this.LibraryFiles != null)
159 {
160 foreach (var libraryFile in this.LibraryFiles)
161 {
162 try
163 {
164 var library = Library.Load(libraryFile, tableDefinitions, false);
165
166 sections.AddRange(library.Sections);
167 }
168 catch (WixCorruptFileException e)
169 {
170 Messaging.Instance.OnMessage(e.Error);
171 }
172 catch (WixUnexpectedFileFormatException e)
173 {
174 Messaging.Instance.OnMessage(e.Error);
175 }
176 }
177 }
54 178
55 var localizer = new Localizer(); 179 return sections;
180 }
181
182 private void BindPhase(Output output, TableDefinitionCollection tableDefinitions)
183 {
184 var localizations = this.LoadLocalizationFiles(tableDefinitions).ToList();
185
186 var localizer = new Localizer(localizations);
187
188 var resolver = new WixVariableResolver(localizer);
56 189
57 var binder = new Binder(); 190 var binder = new Binder();
58 binder.TempFilesLocation = Path.GetTempPath(); 191 binder.TempFilesLocation = this.IntermediateFolder;
59 binder.WixVariableResolver = new WixVariableResolver(); 192 binder.WixVariableResolver = resolver;
60 binder.WixVariableResolver.Localizer = localizer;
61 binder.AddExtension(new BinderFileManager());
62 binder.SuppressValidation = true; 193 binder.SuppressValidation = true;
63 194
64 binder.ContentsFile = this.ContentsFile; 195 binder.ContentsFile = this.ContentsFile;
@@ -66,35 +197,50 @@ namespace WixToolset.Core
66 binder.BuiltOutputsFile = this.BuiltOutputsFile; 197 binder.BuiltOutputsFile = this.BuiltOutputsFile;
67 binder.WixprojectFile = this.WixProjectFile; 198 binder.WixprojectFile = this.WixProjectFile;
68 199
69 foreach (var loc in this.LocFiles) 200 if (this.BindPaths != null)
70 { 201 {
71 var localization = Localizer.ParseLocalizationFile(loc, linker.TableDefinitions); 202 binder.BindPaths.AddRange(this.BindPaths);
72 binder.WixVariableResolver.Localizer.AddLocalization(localization);
73 } 203 }
74 204
75 binder.Bind(output, this.OutputPath); 205 binder.AddExtension(new BinderFileManager());
76 206
77 return 0; 207 binder.Bind(output, this.OutputPath);
78 } 208 }
79 209
80 private IEnumerable<Intermediate> CompilePhase() 210 private IEnumerable<Localization> LoadLocalizationFiles(TableDefinitionCollection tableDefinitions)
81 { 211 {
82 var intermediates = new List<Intermediate>(); 212 foreach (var loc in this.LocFiles)
83 213 {
84 var preprocessor = new Preprocessor(); 214 var localization = Localizer.ParseLocalizationFile(loc, tableDefinitions);
85 215
86 var compiler = new Compiler(); 216 yield return localization;
217 }
218 }
87 219
88 foreach (var sourceFile in this.SourceFiles) 220 /// <summary>
89 { 221 /// File resolution mechanism to create binary library.
90 var document = preprocessor.Process(sourceFile.SourcePath, this.PreprocessorVariables); 222 /// </summary>
223 private class LibraryBinaryFileResolver : ILibraryBinaryFileResolver
224 {
225 public IEnumerable<IBinderFileManager> FileManagers { get; set; }
91 226
92 var intermediate = compiler.Compile(document); 227 public WixVariableResolver VariableResolver { get; set; }
93 228
94 intermediates.Add(intermediate); 229 public string Resolve(SourceLineNumber sourceLineNumber, string table, string path)
230 {
231 string resolvedPath = this.VariableResolver.ResolveVariables(sourceLineNumber, path, false);
232
233 foreach (IBinderFileManager fileManager in this.FileManagers)
234 {
235 string finalPath = fileManager.ResolveFile(resolvedPath, table, sourceLineNumber, BindStage.Normal);
236 if (!String.IsNullOrEmpty(finalPath))
237 {
238 return finalPath;
239 }
240 }
241
242 return null;
95 } 243 }
96
97 return intermediates;
98 } 244 }
99 } 245 }
100} 246}
diff --git a/src/WixToolset.Core/CommandLine/CommandLine.cs b/src/WixToolset.Core/CommandLine/CommandLine.cs
index 440ae9ef..cac54091 100644
--- a/src/WixToolset.Core/CommandLine/CommandLine.cs
+++ b/src/WixToolset.Core/CommandLine/CommandLine.cs
@@ -57,14 +57,20 @@ namespace WixToolset.Core
57 var showVersion = false; 57 var showVersion = false;
58 var outputFolder = String.Empty; 58 var outputFolder = String.Empty;
59 var outputFile = String.Empty; 59 var outputFile = String.Empty;
60 var sourceFile = String.Empty; 60 var outputType = String.Empty;
61 var verbose = false; 61 var verbose = false;
62 var files = new List<string>(); 62 var files = new List<string>();
63 var defines = new List<string>(); 63 var defines = new List<string>();
64 var includePaths = new List<string>(); 64 var includePaths = new List<string>();
65 var locFiles = new List<string>(); 65 var locFiles = new List<string>();
66 var libraryFiles = new List<string>();
66 var suppressedWarnings = new List<int>(); 67 var suppressedWarnings = new List<int>();
67 68
69 var bindFiles = false;
70 var bindPaths = new List<string>();
71
72 var intermediateFolder = String.Empty;
73
68 var cultures = new List<string>(); 74 var cultures = new List<string>();
69 var contentsFile = String.Empty; 75 var contentsFile = String.Empty;
70 var outputsFile = String.Empty; 76 var outputsFile = String.Empty;
@@ -84,6 +90,14 @@ namespace WixToolset.Core
84 cmdline.ShowHelp = true; 90 cmdline.ShowHelp = true;
85 return true; 91 return true;
86 92
93 case "bindfiles":
94 bindFiles = true;
95 return true;
96
97 case "bindpath":
98 cmdline.GetNextArgumentOrError(bindPaths);
99 return true;
100
87 case "cultures": 101 case "cultures":
88 cmdline.GetNextArgumentOrError(cultures); 102 cmdline.GetNextArgumentOrError(cultures);
89 return true; 103 return true;
@@ -110,15 +124,27 @@ namespace WixToolset.Core
110 cmdline.GetNextArgumentOrError(includePaths); 124 cmdline.GetNextArgumentOrError(includePaths);
111 return true; 125 return true;
112 126
127 case "intermediatefolder":
128 cmdline.GetNextArgumentOrError(ref intermediateFolder);
129 return true;
130
113 case "loc": 131 case "loc":
114 cmdline.GetNextArgumentAsFilePathOrError(locFiles, "localization files"); 132 cmdline.GetNextArgumentAsFilePathOrError(locFiles, "localization files");
115 return true; 133 return true;
116 134
135 case "lib":
136 cmdline.GetNextArgumentAsFilePathOrError(libraryFiles, "library files");
137 return true;
138
117 case "o": 139 case "o":
118 case "out": 140 case "out":
119 cmdline.GetNextArgumentOrError(ref outputFile); 141 cmdline.GetNextArgumentOrError(ref outputFile);
120 return true; 142 return true;
121 143
144 case "outputtype":
145 cmdline.GetNextArgumentOrError(ref outputType);
146 return true;
147
122 case "nologo": 148 case "nologo":
123 showLogo = false; 149 showLogo = false;
124 return true; 150 return true;
@@ -143,6 +169,8 @@ namespace WixToolset.Core
143 } 169 }
144 }); 170 });
145 171
172 Messaging.Instance.ShowVerboseMessages = verbose;
173
146 if (showVersion) 174 if (showVersion)
147 { 175 {
148 return new VersionCommand(); 176 return new VersionCommand();
@@ -164,8 +192,10 @@ namespace WixToolset.Core
164 { 192 {
165 var sourceFiles = GatherSourceFiles(files, outputFolder); 193 var sourceFiles = GatherSourceFiles(files, outputFolder);
166 var variables = GatherPreprocessorVariables(defines); 194 var variables = GatherPreprocessorVariables(defines);
195 var bindPathList = GatherBindPaths(bindPaths);
167 var extensions = cli.ExtensionManager; 196 var extensions = cli.ExtensionManager;
168 return new BuildCommand(sourceFiles, variables, locFiles, outputFile, cultures, contentsFile, outputsFile, builtOutputsFile, wixProjectFile); 197 var type = CalculateOutputType(outputType, outputFile);
198 return new BuildCommand(sourceFiles, variables, locFiles, libraryFiles, outputFile, type, cultures, bindFiles, bindPathList, intermediateFolder, contentsFile, outputsFile, builtOutputsFile, wixProjectFile);
169 } 199 }
170 200
171 case Commands.Compile: 201 case Commands.Compile:
@@ -179,6 +209,46 @@ namespace WixToolset.Core
179 return null; 209 return null;
180 } 210 }
181 211
212 private static OutputType CalculateOutputType(string outputType, string outputFile)
213 {
214 if (String.IsNullOrEmpty(outputType))
215 {
216 outputType = Path.GetExtension(outputFile);
217 }
218
219 switch (outputType.ToLowerInvariant())
220 {
221 case "bundle":
222 case ".exe":
223 return OutputType.Bundle;
224
225 case "library":
226 case ".wixlib":
227 return OutputType.Library;
228
229 case "module":
230 case ".msm":
231 return OutputType.Module;
232
233 case "patch":
234 case ".msp":
235 return OutputType.Patch;
236
237 case ".pcp":
238 return OutputType.PatchCreation;
239
240 case "product":
241 case ".msi":
242 return OutputType.Product;
243
244 case "transform":
245 case ".mst":
246 return OutputType.Transform;
247 }
248
249 return OutputType.Unknown;
250 }
251
182 private static CommandLine Parse(string commandLineString, Func<CommandLine, string, bool> parseArgument) 252 private static CommandLine Parse(string commandLineString, Func<CommandLine, string, bool> parseArgument)
183 { 253 {
184 var arguments = CommandLine.ParseArgumentsToArray(commandLineString).ToArray(); 254 var arguments = CommandLine.ParseArgumentsToArray(commandLineString).ToArray();
@@ -239,6 +309,26 @@ namespace WixToolset.Core
239 return variables; 309 return variables;
240 } 310 }
241 311
312 private static IEnumerable<BindPath> GatherBindPaths(IEnumerable<string> bindPaths)
313 {
314 var result = new List<BindPath>();
315
316 foreach (var bindPath in bindPaths)
317 {
318 BindPath bp = BindPath.Parse(bindPath);
319
320 if (Directory.Exists(bp.Path))
321 {
322 result.Add(bp);
323 }
324 else if (File.Exists(bp.Path))
325 {
326 Messaging.Instance.OnMessage(WixErrors.ExpectedDirectoryGotFile("-bindpath", bp.Path));
327 }
328 }
329
330 return result;
331 }
242 332
243 /// <summary> 333 /// <summary>
244 /// Get a set of files that possibly have a search pattern in the path (such as '*'). 334 /// Get a set of files that possibly have a search pattern in the path (such as '*').
@@ -361,7 +451,7 @@ namespace WixToolset.Core
361 451
362 private static bool TryDequeue(Queue<string> q, out string arg) 452 private static bool TryDequeue(Queue<string> q, out string arg)
363 { 453 {
364 if (q.Count> 0) 454 if (q.Count > 0)
365 { 455 {
366 arg = q.Dequeue(); 456 arg = q.Dequeue();
367 return true; 457 return true;
@@ -469,11 +559,6 @@ namespace WixToolset.Core
469 return false; 559 return false;
470 } 560 }
471 561
472 /// <summary>
473 /// Parses a response file.
474 /// </summary>
475 /// <param name="responseFile">The file to parse.</param>
476 /// <returns>The array of arguments.</returns>
477 private static List<string> ParseResponseFile(string responseFile) 562 private static List<string> ParseResponseFile(string responseFile)
478 { 563 {
479 string arguments; 564 string arguments;
@@ -486,11 +571,6 @@ namespace WixToolset.Core
486 return CommandLine.ParseArgumentsToArray(arguments); 571 return CommandLine.ParseArgumentsToArray(arguments);
487 } 572 }
488 573
489 /// <summary>
490 /// Parses an argument string into an argument array based on whitespace and quoting.
491 /// </summary>
492 /// <param name="arguments">Argument string.</param>
493 /// <returns>Argument array.</returns>
494 private static List<string> ParseArgumentsToArray(string arguments) 574 private static List<string> ParseArgumentsToArray(string arguments)
495 { 575 {
496 // Scan and parse the arguments string, dividing up the arguments based on whitespace. 576 // Scan and parse the arguments string, dividing up the arguments based on whitespace.
@@ -526,7 +606,7 @@ namespace WixToolset.Core
526 // Add the argument to the list if it's not empty. 606 // Add the argument to the list if it's not empty.
527 if (arg.Length > 0) 607 if (arg.Length > 0)
528 { 608 {
529 argsList.Add(CommandLine.ExpandEnvVars(arg.ToString())); 609 argsList.Add(CommandLine.ExpandEnvironmentVariables(arg.ToString()));
530 arg.Length = 0; 610 arg.Length = 0;
531 } 611 }
532 } 612 }
@@ -557,12 +637,7 @@ namespace WixToolset.Core
557 return argsList; 637 return argsList;
558 } 638 }
559 639
560 /// <summary> 640 private static string ExpandEnvironmentVariables(string arguments)
561 /// Expand enxironment variables contained in the passed string
562 /// </summary>
563 /// <param name="arguments"></param>
564 /// <returns></returns>
565 private static string ExpandEnvVars(string arguments)
566 { 641 {
567 var id = Environment.GetEnvironmentVariables(); 642 var id = Environment.GetEnvironmentVariables();
568 643