// 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.Tools { using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Xml.Linq; using WixToolset.Data; using WixToolset.Extensibility; /// /// The main entry point for candle. /// public sealed class Candle { private CandleCommandLine commandLine; private IEnumerable preprocessorExtensions; private IEnumerable compilerExtensions; private IEnumerable extensionData; /// /// The main entry point for candle. /// /// Commandline arguments for the application. /// Returns the application error code. [MTAThread] public static int Main(string[] args) { AppCommon.PrepareConsoleForLocalization(); Messaging.Instance.InitializeAppName("CNDL", "candle.exe").Display += AppCommon.ConsoleDisplayMessage; Candle candle = new Candle(); return candle.Execute(args); } private int Execute(string[] args) { try { string[] unparsed = this.ParseCommandLineAndLoadExtensions(args); if (!Messaging.Instance.EncounteredError) { if (this.commandLine.ShowLogo) { AppCommon.DisplayToolHeader(); } if (this.commandLine.ShowHelp) { Console.WriteLine(CandleStrings.HelpMessage); AppCommon.DisplayToolFooter(); } else { foreach (string arg in unparsed) { Messaging.Instance.OnMessage(WixWarnings.UnsupportedCommandLineArgument(arg)); } this.Run(); } } } catch (WixException we) { Messaging.Instance.OnMessage(we.Error); } catch (Exception e) { Messaging.Instance.OnMessage(WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace)); if (e is NullReferenceException || e is SEHException) { throw; } } return Messaging.Instance.LastErrorNumber; } private string[] ParseCommandLineAndLoadExtensions(string[] args) { this.commandLine = new CandleCommandLine(); string[] unprocessed = commandLine.Parse(args); if (Messaging.Instance.EncounteredError) { return unprocessed; } // Load extensions. ExtensionManager extensionManager = new ExtensionManager(); foreach (string extension in this.commandLine.Extensions) { extensionManager.Load(extension); } // Preprocessor extension command line processing. this.preprocessorExtensions = extensionManager.Create(); foreach (IExtensionCommandLine pce in this.preprocessorExtensions.Where(e => e is IExtensionCommandLine).Cast()) { pce.MessageHandler = Messaging.Instance; unprocessed = pce.ParseCommandLine(unprocessed); } // Compiler extension command line processing. this.compilerExtensions = extensionManager.Create(); foreach (IExtensionCommandLine cce in this.compilerExtensions.Where(e => e is IExtensionCommandLine).Cast()) { cce.MessageHandler = Messaging.Instance; unprocessed = cce.ParseCommandLine(unprocessed); } // Extension data command line processing. this.extensionData = extensionManager.Create(); foreach (IExtensionCommandLine dce in this.extensionData.Where(e => e is IExtensionCommandLine).Cast()) { dce.MessageHandler = Messaging.Instance; unprocessed = dce.ParseCommandLine(unprocessed); } return commandLine.ParsePostExtensions(unprocessed); } private void Run() { // Create the preprocessor and compiler Preprocessor preprocessor = new Preprocessor(); preprocessor.CurrentPlatform = this.commandLine.Platform; foreach (string includePath in this.commandLine.IncludeSearchPaths) { preprocessor.IncludeSearchPaths.Add(includePath); } foreach (IPreprocessorExtension pe in this.preprocessorExtensions) { preprocessor.AddExtension(pe); } Compiler compiler = new Compiler(); compiler.ShowPedanticMessages = this.commandLine.ShowPedanticMessages; compiler.CurrentPlatform = this.commandLine.Platform; foreach (IExtensionData ed in this.extensionData) { compiler.AddExtensionData(ed); } foreach (ICompilerExtension ce in this.compilerExtensions) { compiler.AddExtension(ce); } // Preprocess then compile each source file. foreach (CompileFile file in this.commandLine.Files) { // print friendly message saying what file is being compiled Console.WriteLine(file.SourcePath); // preprocess the source XDocument sourceDocument; try { if (!String.IsNullOrEmpty(this.commandLine.PreprocessFile)) { preprocessor.PreprocessOut = this.commandLine.PreprocessFile.Equals("con:", StringComparison.OrdinalIgnoreCase) ? Console.Out : new StreamWriter(this.commandLine.PreprocessFile); } sourceDocument = preprocessor.Process(file.SourcePath, this.commandLine.PreprocessorVariables); } finally { if (null != preprocessor.PreprocessOut && Console.Out != preprocessor.PreprocessOut) { preprocessor.PreprocessOut.Close(); } } // If we're not actually going to compile anything, move on to the next file. if (null == sourceDocument || !String.IsNullOrEmpty(this.commandLine.PreprocessFile)) { continue; } // and now we do what we came here to do... Intermediate intermediate = compiler.Compile(sourceDocument); // save the intermediate to disk if no errors were found for this source file if (null != intermediate) { intermediate.Save(file.OutputPath); } } } } }