diff options
Diffstat (limited to 'src/light/LightCommandLine.cs')
-rw-r--r-- | src/light/LightCommandLine.cs | 485 |
1 files changed, 485 insertions, 0 deletions
diff --git a/src/light/LightCommandLine.cs b/src/light/LightCommandLine.cs new file mode 100644 index 00000000..9a90b9ce --- /dev/null +++ b/src/light/LightCommandLine.cs | |||
@@ -0,0 +1,485 @@ | |||
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.Tools | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Globalization; | ||
8 | using System.IO; | ||
9 | using WixToolset.Core.CommandLine; | ||
10 | using WixToolset.Data; | ||
11 | using WixToolset.Extensibility.Services; | ||
12 | |||
13 | public class LightCommandLine | ||
14 | { | ||
15 | public LightCommandLine(IMessaging messaging) | ||
16 | { | ||
17 | this.Messaging = messaging; | ||
18 | this.ShowLogo = true; | ||
19 | this.Tidy = true; | ||
20 | |||
21 | this.CubeFiles = new List<string>(); | ||
22 | this.SuppressIces = new List<string>(); | ||
23 | this.Ices = new List<string>(); | ||
24 | this.BindPaths = new List<BindPath>(); | ||
25 | this.Extensions = new List<string>(); | ||
26 | this.Files = new List<string>(); | ||
27 | this.LocalizationFiles = new List<string>(); | ||
28 | this.Variables = new Dictionary<string, string>(); | ||
29 | } | ||
30 | |||
31 | public IMessaging Messaging { get; } | ||
32 | |||
33 | public string PdbFile { get; private set; } | ||
34 | |||
35 | public CompressionLevel? DefaultCompressionLevel { get; set; } | ||
36 | |||
37 | public bool SuppressAclReset { get; private set; } | ||
38 | |||
39 | public bool SuppressLayout { get; private set; } | ||
40 | |||
41 | public bool SuppressWixPdb { get; private set; } | ||
42 | |||
43 | public bool SuppressValidation { get; private set; } | ||
44 | |||
45 | public string IntermediateFolder { get; private set; } | ||
46 | |||
47 | public string OutputsFile { get; private set; } | ||
48 | |||
49 | public string BuiltOutputsFile { get; private set; } | ||
50 | |||
51 | public string WixprojectFile { get; private set; } | ||
52 | |||
53 | public string ContentsFile { get; private set; } | ||
54 | |||
55 | public List<string> Ices { get; private set; } | ||
56 | |||
57 | public string CabCachePath { get; private set; } | ||
58 | |||
59 | public int CabbingThreadCount { get; private set; } | ||
60 | |||
61 | public List<string> CubeFiles { get; private set; } | ||
62 | |||
63 | public List<string> SuppressIces { get; private set; } | ||
64 | |||
65 | public bool ShowLogo { get; private set; } | ||
66 | |||
67 | public bool ShowHelp { get; private set; } | ||
68 | |||
69 | public bool ShowPedanticMessages { get; private set; } | ||
70 | |||
71 | public bool SuppressLocalization { get; private set; } | ||
72 | |||
73 | public bool SuppressVersionCheck { get; private set; } | ||
74 | |||
75 | public string[] Cultures { get; private set; } | ||
76 | |||
77 | public string OutputFile { get; private set; } | ||
78 | |||
79 | public bool OutputXml { get; private set; } | ||
80 | |||
81 | public List<BindPath> BindPaths { get; private set; } | ||
82 | |||
83 | public List<string> Extensions { get; private set; } | ||
84 | |||
85 | public List<string> Files { get; private set; } | ||
86 | |||
87 | public List<string> LocalizationFiles { get; private set; } | ||
88 | |||
89 | public bool Tidy { get; private set; } | ||
90 | |||
91 | public string UnreferencedSymbolsFile { get; private set; } | ||
92 | |||
93 | public IDictionary<string, string> Variables { get; private set; } | ||
94 | |||
95 | /// <summary> | ||
96 | /// Parse the commandline arguments. | ||
97 | /// </summary> | ||
98 | /// <param name="args">Commandline arguments.</param> | ||
99 | public string[] Parse(string[] args) | ||
100 | { | ||
101 | List<string> unprocessed = new List<string>(); | ||
102 | |||
103 | for (int i = 0; i < args.Length; ++i) | ||
104 | { | ||
105 | string arg = args[i]; | ||
106 | if (String.IsNullOrEmpty(arg)) // skip blank arguments | ||
107 | { | ||
108 | continue; | ||
109 | } | ||
110 | |||
111 | if (1 == arg.Length) // treat '-' and '@' as filenames when by themselves. | ||
112 | { | ||
113 | unprocessed.Add(arg); | ||
114 | } | ||
115 | else if ('-' == arg[0] || '/' == arg[0]) | ||
116 | { | ||
117 | string parameter = arg.Substring(1); | ||
118 | if (parameter.Equals("b", StringComparison.Ordinal)) | ||
119 | { | ||
120 | if (!CommandLineHelper.IsValidArg(args, ++i)) | ||
121 | { | ||
122 | break; | ||
123 | } | ||
124 | |||
125 | var bindPath = BindPath.Parse(args[i]); | ||
126 | |||
127 | this.BindPaths.Add(bindPath); | ||
128 | } | ||
129 | else if (parameter.StartsWith("cultures:", StringComparison.Ordinal)) | ||
130 | { | ||
131 | string culturesString = arg.Substring(10).ToLower(CultureInfo.InvariantCulture); | ||
132 | |||
133 | // When null is used treat it as if cultures wasn't specified. | ||
134 | // This is needed for batching over the light task when using MSBuild which doesn't | ||
135 | // support empty items | ||
136 | if (culturesString.Equals("null", StringComparison.OrdinalIgnoreCase)) | ||
137 | { | ||
138 | this.Cultures = null; | ||
139 | } | ||
140 | else | ||
141 | { | ||
142 | this.Cultures = culturesString.Split(';', ','); | ||
143 | |||
144 | for (int c = 0; c < this.Cultures.Length; ++c) | ||
145 | { | ||
146 | // Neutral is different from null. For neutral we still want to do WXL filtering. | ||
147 | // Set the culture to the empty string = identifier for the invariant culture | ||
148 | if (this.Cultures[c].Equals("neutral", StringComparison.OrdinalIgnoreCase)) | ||
149 | { | ||
150 | this.Cultures[c] = String.Empty; | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | else if (parameter.StartsWith("dcl:", StringComparison.Ordinal)) | ||
156 | { | ||
157 | string defaultCompressionLevel = arg.Substring(5); | ||
158 | |||
159 | if (String.IsNullOrEmpty(defaultCompressionLevel)) | ||
160 | { | ||
161 | break; | ||
162 | } | ||
163 | else if (Enum.TryParse(defaultCompressionLevel, true, out CompressionLevel compressionLevel)) | ||
164 | { | ||
165 | this.DefaultCompressionLevel = compressionLevel; | ||
166 | } | ||
167 | } | ||
168 | else if (parameter.StartsWith("d", StringComparison.Ordinal)) | ||
169 | { | ||
170 | parameter = arg.Substring(2); | ||
171 | string[] value = parameter.Split("=".ToCharArray(), 2); | ||
172 | |||
173 | string preexisting; | ||
174 | if (1 == value.Length) | ||
175 | { | ||
176 | this.Messaging.Write(ErrorMessages.ExpectedWixVariableValue(value[0])); | ||
177 | } | ||
178 | else if (this.Variables.TryGetValue(value[0], out preexisting)) | ||
179 | { | ||
180 | this.Messaging.Write(ErrorMessages.WixVariableCollision(null, value[0])); | ||
181 | } | ||
182 | else | ||
183 | { | ||
184 | this.Variables.Add(value[0], value[1]); | ||
185 | } | ||
186 | } | ||
187 | else if (parameter.Equals("ext", StringComparison.Ordinal)) | ||
188 | { | ||
189 | if (!CommandLineHelper.IsValidArg(args, ++i)) | ||
190 | { | ||
191 | this.Messaging.Write(ErrorMessages.TypeSpecificationForExtensionRequired("-ext")); | ||
192 | break; | ||
193 | } | ||
194 | |||
195 | this.Extensions.Add(args[i]); | ||
196 | } | ||
197 | else if (parameter.Equals("loc", StringComparison.Ordinal)) | ||
198 | { | ||
199 | string locFile = CommandLineHelper.GetFile(parameter, this.Messaging, args, ++i); | ||
200 | if (String.IsNullOrEmpty(locFile)) | ||
201 | { | ||
202 | break; | ||
203 | } | ||
204 | |||
205 | this.LocalizationFiles.Add(locFile); | ||
206 | } | ||
207 | else if (parameter.Equals("nologo", StringComparison.Ordinal)) | ||
208 | { | ||
209 | this.ShowLogo = false; | ||
210 | } | ||
211 | else if (parameter.Equals("notidy", StringComparison.Ordinal)) | ||
212 | { | ||
213 | this.Tidy = false; | ||
214 | } | ||
215 | else if ("o" == parameter || "out" == parameter) | ||
216 | { | ||
217 | this.OutputFile = CommandLineHelper.GetFile(parameter, this.Messaging, args, ++i); | ||
218 | if (String.IsNullOrEmpty(this.OutputFile)) | ||
219 | { | ||
220 | break; | ||
221 | } | ||
222 | } | ||
223 | else if (parameter.Equals("pedantic", StringComparison.Ordinal)) | ||
224 | { | ||
225 | this.ShowPedanticMessages = true; | ||
226 | } | ||
227 | else if (parameter.Equals("sloc", StringComparison.Ordinal)) | ||
228 | { | ||
229 | this.SuppressLocalization = true; | ||
230 | } | ||
231 | else if (parameter.Equals("usf", StringComparison.Ordinal)) | ||
232 | { | ||
233 | this.UnreferencedSymbolsFile = CommandLineHelper.GetFile(parameter, this.Messaging, args, ++i); | ||
234 | |||
235 | if (String.IsNullOrEmpty(this.UnreferencedSymbolsFile)) | ||
236 | { | ||
237 | break; | ||
238 | } | ||
239 | } | ||
240 | else if (parameter.Equals("xo", StringComparison.Ordinal)) | ||
241 | { | ||
242 | this.OutputXml = true; | ||
243 | } | ||
244 | else if (parameter.Equals("cc", StringComparison.Ordinal)) | ||
245 | { | ||
246 | this.CabCachePath = CommandLineHelper.GetDirectory(parameter, this.Messaging, args, ++i); | ||
247 | |||
248 | if (String.IsNullOrEmpty(this.CabCachePath)) | ||
249 | { | ||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | else if (parameter.Equals("ct", StringComparison.Ordinal)) | ||
254 | { | ||
255 | if (!CommandLineHelper.IsValidArg(args, ++i)) | ||
256 | { | ||
257 | this.Messaging.Write(ErrorMessages.IllegalCabbingThreadCount(String.Empty)); | ||
258 | break; | ||
259 | } | ||
260 | |||
261 | int ct = 0; | ||
262 | if (!Int32.TryParse(args[i], out ct) || 0 >= ct) | ||
263 | { | ||
264 | this.Messaging.Write(ErrorMessages.IllegalCabbingThreadCount(args[i])); | ||
265 | break; | ||
266 | } | ||
267 | |||
268 | this.CabbingThreadCount = ct; | ||
269 | this.Messaging.Write(VerboseMessages.SetCabbingThreadCount(this.CabbingThreadCount.ToString())); | ||
270 | } | ||
271 | else if (parameter.Equals("cub", StringComparison.Ordinal)) | ||
272 | { | ||
273 | string cubeFile = CommandLineHelper.GetFile(parameter, this.Messaging, args, ++i); | ||
274 | |||
275 | if (String.IsNullOrEmpty(cubeFile)) | ||
276 | { | ||
277 | break; | ||
278 | } | ||
279 | |||
280 | this.CubeFiles.Add(cubeFile); | ||
281 | } | ||
282 | else if (parameter.StartsWith("ice:", StringComparison.Ordinal)) | ||
283 | { | ||
284 | this.Ices.Add(parameter.Substring(4)); | ||
285 | } | ||
286 | else if (parameter.Equals("intermediatefolder", StringComparison.OrdinalIgnoreCase)) | ||
287 | { | ||
288 | this.IntermediateFolder = CommandLineHelper.GetDirectory(parameter, this.Messaging, args, ++i); | ||
289 | |||
290 | if (String.IsNullOrEmpty(this.IntermediateFolder)) | ||
291 | { | ||
292 | break; | ||
293 | } | ||
294 | } | ||
295 | else if (parameter.Equals("contentsfile", StringComparison.Ordinal)) | ||
296 | { | ||
297 | this.ContentsFile = CommandLineHelper.GetFile(parameter, this.Messaging, args, ++i); | ||
298 | |||
299 | if (String.IsNullOrEmpty(this.ContentsFile)) | ||
300 | { | ||
301 | break; | ||
302 | } | ||
303 | } | ||
304 | else if (parameter.Equals("outputsfile", StringComparison.Ordinal)) | ||
305 | { | ||
306 | this.OutputsFile = CommandLineHelper.GetFile(parameter, this.Messaging, args, ++i); | ||
307 | |||
308 | if (String.IsNullOrEmpty(this.OutputsFile)) | ||
309 | { | ||
310 | break; | ||
311 | } | ||
312 | } | ||
313 | else if (parameter.Equals("builtoutputsfile", StringComparison.Ordinal)) | ||
314 | { | ||
315 | this.BuiltOutputsFile = CommandLineHelper.GetFile(parameter, this.Messaging, args, ++i); | ||
316 | |||
317 | if (String.IsNullOrEmpty(this.BuiltOutputsFile)) | ||
318 | { | ||
319 | break; | ||
320 | } | ||
321 | } | ||
322 | else if (parameter.Equals("wixprojectfile", StringComparison.Ordinal)) | ||
323 | { | ||
324 | this.WixprojectFile = CommandLineHelper.GetFile(parameter, this.Messaging, args, ++i); | ||
325 | |||
326 | if (String.IsNullOrEmpty(this.WixprojectFile)) | ||
327 | { | ||
328 | break; | ||
329 | } | ||
330 | } | ||
331 | else if (parameter.Equals("pdbout", StringComparison.Ordinal)) | ||
332 | { | ||
333 | this.PdbFile = CommandLineHelper.GetFile(parameter, this.Messaging, args, ++i); | ||
334 | |||
335 | if (String.IsNullOrEmpty(this.PdbFile)) | ||
336 | { | ||
337 | break; | ||
338 | } | ||
339 | } | ||
340 | else if (parameter.StartsWith("sice:", StringComparison.Ordinal)) | ||
341 | { | ||
342 | this.SuppressIces.Add(parameter.Substring(5)); | ||
343 | } | ||
344 | else if (parameter.Equals("sl", StringComparison.Ordinal)) | ||
345 | { | ||
346 | this.SuppressLayout = true; | ||
347 | } | ||
348 | else if (parameter.Equals("spdb", StringComparison.Ordinal)) | ||
349 | { | ||
350 | this.SuppressWixPdb = true; | ||
351 | } | ||
352 | else if (parameter.Equals("sacl", StringComparison.Ordinal)) | ||
353 | { | ||
354 | this.SuppressAclReset = true; | ||
355 | } | ||
356 | else if (parameter.Equals("sval", StringComparison.Ordinal)) | ||
357 | { | ||
358 | this.SuppressValidation = true; | ||
359 | } | ||
360 | else if ("sv" == parameter) | ||
361 | { | ||
362 | this.SuppressVersionCheck = true; | ||
363 | } | ||
364 | else if (parameter.StartsWith("sw", StringComparison.Ordinal)) | ||
365 | { | ||
366 | string paramArg = parameter.Substring(2); | ||
367 | if (0 == paramArg.Length) | ||
368 | { | ||
369 | this.Messaging.SuppressAllWarnings = true; | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | int suppressWarning = 0; | ||
374 | if (!Int32.TryParse(paramArg, out suppressWarning) || 0 >= suppressWarning) | ||
375 | { | ||
376 | this.Messaging.Write(ErrorMessages.IllegalSuppressWarningId(paramArg)); | ||
377 | } | ||
378 | else | ||
379 | { | ||
380 | this.Messaging.SuppressWarningMessage(suppressWarning); | ||
381 | } | ||
382 | } | ||
383 | } | ||
384 | else if (parameter.StartsWith("wx", StringComparison.Ordinal)) | ||
385 | { | ||
386 | string paramArg = parameter.Substring(2); | ||
387 | if (0 == paramArg.Length) | ||
388 | { | ||
389 | this.Messaging.WarningsAsError = true; | ||
390 | } | ||
391 | else | ||
392 | { | ||
393 | int elevateWarning = 0; | ||
394 | if (!Int32.TryParse(paramArg, out elevateWarning) || 0 >= elevateWarning) | ||
395 | { | ||
396 | this.Messaging.Write(ErrorMessages.IllegalWarningIdAsError(paramArg)); | ||
397 | } | ||
398 | else | ||
399 | { | ||
400 | this.Messaging.ElevateWarningMessage(elevateWarning); | ||
401 | } | ||
402 | } | ||
403 | } | ||
404 | else if ("v" == parameter) | ||
405 | { | ||
406 | this.Messaging.ShowVerboseMessages = true; | ||
407 | } | ||
408 | else if ("?" == parameter || "help" == parameter) | ||
409 | { | ||
410 | this.ShowHelp = true; | ||
411 | break; | ||
412 | } | ||
413 | else | ||
414 | { | ||
415 | unprocessed.Add(arg); | ||
416 | } | ||
417 | } | ||
418 | else if ('@' == arg[0]) | ||
419 | { | ||
420 | string[] parsedArgs = CommandLineResponseFile.Parse(arg.Substring(1)); | ||
421 | string[] unparsedArgs = this.Parse(parsedArgs); | ||
422 | unprocessed.AddRange(unparsedArgs); | ||
423 | } | ||
424 | else | ||
425 | { | ||
426 | unprocessed.Add(arg); | ||
427 | } | ||
428 | } | ||
429 | |||
430 | return unprocessed.ToArray(); | ||
431 | } | ||
432 | |||
433 | public string[] ParsePostExtensions(string[] remaining) | ||
434 | { | ||
435 | List<string> unprocessed = new List<string>(); | ||
436 | |||
437 | for (int i = 0; i < remaining.Length; ++i) | ||
438 | { | ||
439 | string arg = remaining[i]; | ||
440 | if (String.IsNullOrEmpty(arg)) // skip blank arguments | ||
441 | { | ||
442 | continue; | ||
443 | } | ||
444 | |||
445 | if (1 < arg.Length && ('-' == arg[0] || '/' == arg[0])) | ||
446 | { | ||
447 | unprocessed.Add(arg); | ||
448 | } | ||
449 | else | ||
450 | { | ||
451 | this.Files.AddRange(CommandLineHelper.GetFiles(arg, "Source")); | ||
452 | } | ||
453 | } | ||
454 | |||
455 | if (0 == this.Files.Count) | ||
456 | { | ||
457 | this.ShowHelp = true; | ||
458 | } | ||
459 | else if (String.IsNullOrEmpty(this.OutputFile)) | ||
460 | { | ||
461 | if (1 < this.Files.Count) | ||
462 | { | ||
463 | this.Messaging.Write(ErrorMessages.MustSpecifyOutputWithMoreThanOneInput()); | ||
464 | } | ||
465 | |||
466 | // After the linker tells us what the output type actually is, we'll change the ".wix" to the correct extension. | ||
467 | this.OutputFile = Path.ChangeExtension(Path.GetFileName(this.Files[0]), ".wix"); | ||
468 | |||
469 | // Add the directories of the input files as unnamed bind paths. | ||
470 | foreach (string file in this.Files) | ||
471 | { | ||
472 | BindPath bindPath = new BindPath(Path.GetDirectoryName(Path.GetFullPath(file))); | ||
473 | this.BindPaths.Add(bindPath); | ||
474 | } | ||
475 | } | ||
476 | |||
477 | if (!this.SuppressWixPdb && String.IsNullOrEmpty(this.PdbFile) && !String.IsNullOrEmpty(this.OutputFile)) | ||
478 | { | ||
479 | this.PdbFile = Path.ChangeExtension(this.OutputFile, ".wixpdb"); | ||
480 | } | ||
481 | |||
482 | return unprocessed.ToArray(); | ||
483 | } | ||
484 | } | ||
485 | } | ||