diff options
| author | Rob Mensching <rob@firegiant.com> | 2017-08-15 01:31:51 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2017-08-15 01:31:51 -0700 |
| commit | 4418bd52f1fca52a0d8d5f5b60abd2fdfc7146bd (patch) | |
| tree | 02338abc93fb2e065c8717a84520d5ea8c7ea06c | |
| parent | 0358780c77469974dd8bc87840364e790ccecc29 (diff) | |
| download | wix-4418bd52f1fca52a0d8d5f5b60abd2fdfc7146bd.tar.gz wix-4418bd52f1fca52a0d8d5f5b60abd2fdfc7146bd.tar.bz2 wix-4418bd52f1fca52a0d8d5f5b60abd2fdfc7146bd.zip | |
Migrate MsgGen
| -rw-r--r-- | WixBuildTools.sln | 15 | ||||
| -rw-r--r-- | src/WixBuildTools.MsgGen/AssemblyInfo.cs | 8 | ||||
| -rw-r--r-- | src/WixBuildTools.MsgGen/GenerateMessageFiles.cs | 250 | ||||
| -rw-r--r-- | src/WixBuildTools.MsgGen/MsgGen.cs | 261 | ||||
| -rw-r--r-- | src/WixBuildTools.MsgGen/WixBuildTools.MsgGen.csproj | 22 | ||||
| -rw-r--r-- | src/WixBuildTools.MsgGen/Xsd/messages.xsd | 101 | ||||
| -rw-r--r-- | src/WixBuildTools.MsgGen/build/WixBuildTools.MsgGen.targets | 102 | ||||
| -rw-r--r-- | src/WixBuildTools.MsgGen/buildCrossTargeting/WixBuildTools.MsgGen.targets | 6 |
8 files changed, 765 insertions, 0 deletions
diff --git a/WixBuildTools.sln b/WixBuildTools.sln index 251fed6d..d7f21621 100644 --- a/WixBuildTools.sln +++ b/WixBuildTools.sln | |||
| @@ -6,6 +6,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{00E50075-E89 | |||
| 6 | EndProject | 6 | EndProject |
| 7 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixBuildTools.XsdGen", "src\WixBuildTools.XsdGen\WixBuildTools.XsdGen.csproj", "{E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}" | 7 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixBuildTools.XsdGen", "src\WixBuildTools.XsdGen\WixBuildTools.XsdGen.csproj", "{E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}" |
| 8 | EndProject | 8 | EndProject |
| 9 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixBuildTools.MsgGen", "src\WixBuildTools.MsgGen\WixBuildTools.MsgGen.csproj", "{DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}" | ||
| 10 | EndProject | ||
| 9 | Global | 11 | Global |
| 10 | GlobalSection(SolutionConfigurationPlatforms) = preSolution | 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution |
| 11 | Debug|Any CPU = Debug|Any CPU | 13 | Debug|Any CPU = Debug|Any CPU |
| @@ -28,12 +30,25 @@ Global | |||
| 28 | {E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}.Release|x64.Build.0 = Release|Any CPU | 30 | {E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}.Release|x64.Build.0 = Release|Any CPU |
| 29 | {E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}.Release|x86.ActiveCfg = Release|Any CPU | 31 | {E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}.Release|x86.ActiveCfg = Release|Any CPU |
| 30 | {E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}.Release|x86.Build.0 = Release|Any CPU | 32 | {E89E52C9-A4A1-4174-A1B1-3B72975E6ED6}.Release|x86.Build.0 = Release|Any CPU |
| 33 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| 34 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| 35 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|x64.ActiveCfg = Debug|Any CPU | ||
| 36 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|x64.Build.0 = Debug|Any CPU | ||
| 37 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
| 38 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Debug|x86.Build.0 = Debug|Any CPU | ||
| 39 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| 40 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| 41 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|x64.ActiveCfg = Release|Any CPU | ||
| 42 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|x64.Build.0 = Release|Any CPU | ||
| 43 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|x86.ActiveCfg = Release|Any CPU | ||
| 44 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4}.Release|x86.Build.0 = Release|Any CPU | ||
| 31 | EndGlobalSection | 45 | EndGlobalSection |
| 32 | GlobalSection(SolutionProperties) = preSolution | 46 | GlobalSection(SolutionProperties) = preSolution |
| 33 | HideSolutionNode = FALSE | 47 | HideSolutionNode = FALSE |
| 34 | EndGlobalSection | 48 | EndGlobalSection |
| 35 | GlobalSection(NestedProjects) = preSolution | 49 | GlobalSection(NestedProjects) = preSolution |
| 36 | {E89E52C9-A4A1-4174-A1B1-3B72975E6ED6} = {00E50075-E896-42D1-AC30-2D2E7D129FB9} | 50 | {E89E52C9-A4A1-4174-A1B1-3B72975E6ED6} = {00E50075-E896-42D1-AC30-2D2E7D129FB9} |
| 51 | {DB6EF6F3-51B1-4214-9A14-D501C23F6FA4} = {00E50075-E896-42D1-AC30-2D2E7D129FB9} | ||
| 37 | EndGlobalSection | 52 | EndGlobalSection |
| 38 | GlobalSection(ExtensibilityGlobals) = postSolution | 53 | GlobalSection(ExtensibilityGlobals) = postSolution |
| 39 | SolutionGuid = {83E9E075-B440-471A-9C37-9D84BA0AE3E0} | 54 | SolutionGuid = {83E9E075-B440-471A-9C37-9D84BA0AE3E0} |
diff --git a/src/WixBuildTools.MsgGen/AssemblyInfo.cs b/src/WixBuildTools.MsgGen/AssemblyInfo.cs new file mode 100644 index 00000000..378adbf0 --- /dev/null +++ b/src/WixBuildTools.MsgGen/AssemblyInfo.cs | |||
| @@ -0,0 +1,8 @@ | |||
| 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 | using System.Reflection; | ||
| 4 | |||
| 5 | // General Information about an assembly is controlled through the following | ||
| 6 | // set of attributes. Change these attribute values to modify the information | ||
| 7 | // associated with an assembly. | ||
| 8 | [assembly: AssemblyCulture("")] | ||
diff --git a/src/WixBuildTools.MsgGen/GenerateMessageFiles.cs b/src/WixBuildTools.MsgGen/GenerateMessageFiles.cs new file mode 100644 index 00000000..6f51dbf9 --- /dev/null +++ b/src/WixBuildTools.MsgGen/GenerateMessageFiles.cs | |||
| @@ -0,0 +1,250 @@ | |||
| 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 WixBuildTools.MsgGen | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.CodeDom; | ||
| 7 | using System.Collections; | ||
| 8 | using System.Globalization; | ||
| 9 | using System.Reflection; | ||
| 10 | using System.Resources; | ||
| 11 | using System.Xml; | ||
| 12 | |||
| 13 | /// <summary> | ||
| 14 | /// Message files generation class. | ||
| 15 | /// </summary> | ||
| 16 | public class GenerateMessageFiles | ||
| 17 | { | ||
| 18 | /// <summary> | ||
| 19 | /// Generate the message files. | ||
| 20 | /// </summary> | ||
| 21 | /// <param name="messagesDoc">Input Xml document containing message definitions.</param> | ||
| 22 | /// <param name="codeCompileUnit">CodeDom container.</param> | ||
| 23 | /// <param name="resourceWriter">Writer for default resource file.</param> | ||
| 24 | public static void Generate(XmlDocument messagesDoc, CodeCompileUnit codeCompileUnit, ResourceWriter resourceWriter) | ||
| 25 | { | ||
| 26 | Hashtable usedNumbers = new Hashtable(); | ||
| 27 | |||
| 28 | if (null == messagesDoc) | ||
| 29 | { | ||
| 30 | throw new ArgumentNullException("messagesDoc"); | ||
| 31 | } | ||
| 32 | |||
| 33 | if (null == codeCompileUnit) | ||
| 34 | { | ||
| 35 | throw new ArgumentNullException("codeCompileUnit"); | ||
| 36 | } | ||
| 37 | |||
| 38 | if (null == resourceWriter) | ||
| 39 | { | ||
| 40 | throw new ArgumentNullException("resourceWriter"); | ||
| 41 | } | ||
| 42 | |||
| 43 | string namespaceAttr = messagesDoc.DocumentElement.GetAttribute("Namespace"); | ||
| 44 | string resourcesAttr = messagesDoc.DocumentElement.GetAttribute("Resources"); | ||
| 45 | |||
| 46 | // namespace | ||
| 47 | CodeNamespace messagesNamespace = new CodeNamespace(namespaceAttr); | ||
| 48 | codeCompileUnit.Namespaces.Add(messagesNamespace); | ||
| 49 | |||
| 50 | // imports | ||
| 51 | messagesNamespace.Imports.Add(new CodeNamespaceImport("System")); | ||
| 52 | messagesNamespace.Imports.Add(new CodeNamespaceImport("System.Reflection")); | ||
| 53 | messagesNamespace.Imports.Add(new CodeNamespaceImport("System.Resources")); | ||
| 54 | if (namespaceAttr != "WixToolset.Data") | ||
| 55 | { | ||
| 56 | messagesNamespace.Imports.Add(new CodeNamespaceImport("WixToolset.Data")); | ||
| 57 | } | ||
| 58 | |||
| 59 | foreach (XmlElement classElement in messagesDoc.DocumentElement.ChildNodes) | ||
| 60 | { | ||
| 61 | string className = classElement.GetAttribute("Name"); | ||
| 62 | string baseContainerName = classElement.GetAttribute("BaseContainerName"); | ||
| 63 | string containerName = classElement.GetAttribute("ContainerName"); | ||
| 64 | string messageLevel = classElement.GetAttribute("Level"); | ||
| 65 | |||
| 66 | // message container class | ||
| 67 | messagesNamespace.Types.Add(CreateContainer(namespaceAttr, baseContainerName, containerName, messageLevel, resourcesAttr)); | ||
| 68 | |||
| 69 | // class | ||
| 70 | CodeTypeDeclaration messagesClass = new CodeTypeDeclaration(className); | ||
| 71 | messagesClass.TypeAttributes = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed; | ||
| 72 | messagesNamespace.Types.Add(messagesClass); | ||
| 73 | |||
| 74 | // private constructor (needed since all methods in this class are static) | ||
| 75 | CodeConstructor constructor = new CodeConstructor(); | ||
| 76 | constructor.Attributes = MemberAttributes.Private; | ||
| 77 | constructor.ReturnType = null; | ||
| 78 | messagesClass.Members.Add(constructor); | ||
| 79 | |||
| 80 | // messages | ||
| 81 | foreach (XmlElement messageElement in classElement.ChildNodes) | ||
| 82 | { | ||
| 83 | int number; | ||
| 84 | string id = messageElement.GetAttribute("Id"); | ||
| 85 | string numberString = messageElement.GetAttribute("Number"); | ||
| 86 | bool sourceLineNumbers = true; | ||
| 87 | |||
| 88 | // determine the message number (and ensure it was set properly) | ||
| 89 | if (0 < numberString.Length) | ||
| 90 | { | ||
| 91 | number = Convert.ToInt32(numberString, CultureInfo.InvariantCulture); | ||
| 92 | } | ||
| 93 | else | ||
| 94 | { | ||
| 95 | throw new ApplicationException(String.Format("Message number must be assigned for {0} '{1}'.", containerName, id)); | ||
| 96 | } | ||
| 97 | |||
| 98 | // check for message number collisions | ||
| 99 | if (usedNumbers.Contains(number)) | ||
| 100 | { | ||
| 101 | throw new ApplicationException(String.Format("Collision detected between two or more messages with number '{0}'.", number)); | ||
| 102 | } | ||
| 103 | |||
| 104 | usedNumbers.Add(number, null); | ||
| 105 | |||
| 106 | if ("no" == messageElement.GetAttribute("SourceLineNumbers")) | ||
| 107 | { | ||
| 108 | sourceLineNumbers = false; | ||
| 109 | } | ||
| 110 | |||
| 111 | int instanceCount = 0; | ||
| 112 | foreach (XmlElement instanceElement in messageElement.ChildNodes) | ||
| 113 | { | ||
| 114 | string formatString = instanceElement.InnerText.Trim(); | ||
| 115 | string resourceName = String.Concat(className, "_", id, "_", (++instanceCount).ToString()); | ||
| 116 | |||
| 117 | // create a resource | ||
| 118 | resourceWriter.AddResource(resourceName, formatString); | ||
| 119 | |||
| 120 | // create method | ||
| 121 | CodeMemberMethod method = new CodeMemberMethod(); | ||
| 122 | method.ReturnType = new CodeTypeReference(baseContainerName); | ||
| 123 | method.Attributes = MemberAttributes.Public | MemberAttributes.Static; | ||
| 124 | messagesClass.Members.Add(method); | ||
| 125 | |||
| 126 | // method name | ||
| 127 | method.Name = id; | ||
| 128 | |||
| 129 | // return statement | ||
| 130 | CodeMethodReturnStatement stmt = new CodeMethodReturnStatement(); | ||
| 131 | method.Statements.Add(stmt); | ||
| 132 | |||
| 133 | // return statement expression | ||
| 134 | CodeObjectCreateExpression expr = new CodeObjectCreateExpression(); | ||
| 135 | stmt.Expression = expr; | ||
| 136 | |||
| 137 | // new struct | ||
| 138 | expr.CreateType = new CodeTypeReference(containerName); | ||
| 139 | |||
| 140 | // optionally have sourceLineNumbers as the first parameter | ||
| 141 | if (sourceLineNumbers) | ||
| 142 | { | ||
| 143 | // sourceLineNumbers parameter | ||
| 144 | expr.Parameters.Add(new CodeArgumentReferenceExpression("sourceLineNumbers")); | ||
| 145 | } | ||
| 146 | else | ||
| 147 | { | ||
| 148 | expr.Parameters.Add(new CodePrimitiveExpression(null)); | ||
| 149 | } | ||
| 150 | |||
| 151 | // message number parameter | ||
| 152 | expr.Parameters.Add(new CodePrimitiveExpression(number)); | ||
| 153 | |||
| 154 | // resource name parameter | ||
| 155 | expr.Parameters.Add(new CodePrimitiveExpression(resourceName)); | ||
| 156 | |||
| 157 | // optionally have sourceLineNumbers as the first parameter | ||
| 158 | if (sourceLineNumbers) | ||
| 159 | { | ||
| 160 | method.Parameters.Add(new CodeParameterDeclarationExpression("SourceLineNumber", "sourceLineNumbers")); | ||
| 161 | } | ||
| 162 | |||
| 163 | foreach (XmlNode parameterNode in instanceElement.ChildNodes) | ||
| 164 | { | ||
| 165 | XmlElement parameterElement; | ||
| 166 | |||
| 167 | if (null != (parameterElement = parameterNode as XmlElement)) | ||
| 168 | { | ||
| 169 | string type = parameterElement.GetAttribute("Type"); | ||
| 170 | string name = parameterElement.GetAttribute("Name"); | ||
| 171 | |||
| 172 | // method parameter | ||
| 173 | method.Parameters.Add(new CodeParameterDeclarationExpression(type, name)); | ||
| 174 | |||
| 175 | // String.Format parameter | ||
| 176 | expr.Parameters.Add(new CodeArgumentReferenceExpression(name)); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | } | ||
| 180 | } | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | /// <summary> | ||
| 185 | /// Create message container class. | ||
| 186 | /// </summary> | ||
| 187 | /// <param name="namespaceName">Namespace to use for resources stream.</param> | ||
| 188 | /// <param name="baseContainerName">Name of the base message container class.</param> | ||
| 189 | /// <param name="containerName">Name of the message container class.</param> | ||
| 190 | /// <param name="messageLevel">Message level of for the message.</param> | ||
| 191 | /// <param name="resourcesName">Name of the resources stream (will get namespace prepended).</param> | ||
| 192 | /// <returns>Message container class CodeDom object.</returns> | ||
| 193 | private static CodeTypeDeclaration CreateContainer(string namespaceName, string baseContainerName, string containerName, string messageLevel, string resourcesName) | ||
| 194 | { | ||
| 195 | CodeTypeDeclaration messageContainer = new CodeTypeDeclaration(); | ||
| 196 | |||
| 197 | messageContainer.Name = containerName; | ||
| 198 | messageContainer.BaseTypes.Add(new CodeTypeReference(baseContainerName)); | ||
| 199 | |||
| 200 | // constructor | ||
| 201 | CodeConstructor constructor = new CodeConstructor(); | ||
| 202 | constructor.Attributes = MemberAttributes.Public; | ||
| 203 | constructor.ReturnType = null; | ||
| 204 | messageContainer.Members.Add(constructor); | ||
| 205 | |||
| 206 | CodeMemberField resourceManager = new CodeMemberField(); | ||
| 207 | resourceManager.Attributes = MemberAttributes.Private | MemberAttributes.Static; | ||
| 208 | resourceManager.Name = "resourceManager"; | ||
| 209 | resourceManager.Type = new CodeTypeReference("ResourceManager"); | ||
| 210 | resourceManager.InitExpression = new CodeObjectCreateExpression("ResourceManager", new CodeSnippetExpression(String.Format("\"{0}.{1}\"", namespaceName, resourcesName)), new CodeSnippetExpression("Assembly.GetExecutingAssembly()")); | ||
| 211 | messageContainer.Members.Add(resourceManager); | ||
| 212 | |||
| 213 | // constructor parameters | ||
| 214 | constructor.Parameters.Add(new CodeParameterDeclarationExpression("SourceLineNumber", "sourceLineNumbers")); | ||
| 215 | constructor.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "id")); | ||
| 216 | constructor.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "resourceName")); | ||
| 217 | CodeParameterDeclarationExpression messageArgsParam = new CodeParameterDeclarationExpression("params object[]", "messageArgs"); | ||
| 218 | constructor.Parameters.Add(messageArgsParam); | ||
| 219 | |||
| 220 | constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("sourceLineNumbers")); | ||
| 221 | constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("id")); | ||
| 222 | constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("resourceName")); | ||
| 223 | constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("messageArgs")); | ||
| 224 | |||
| 225 | // assign base.Level if messageLevel is specified | ||
| 226 | if (!String.IsNullOrEmpty(messageLevel)) | ||
| 227 | { | ||
| 228 | CodePropertyReferenceExpression levelReference = new CodePropertyReferenceExpression(new CodeBaseReferenceExpression(), "Level"); | ||
| 229 | CodeFieldReferenceExpression messageLevelField = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("MessageLevel"), messageLevel); | ||
| 230 | constructor.Statements.Add(new CodeAssignStatement(levelReference, messageLevelField)); | ||
| 231 | } | ||
| 232 | |||
| 233 | // Assign base.ResourceManager property | ||
| 234 | CodePropertyReferenceExpression baseResourceManagerReference = new CodePropertyReferenceExpression(new CodeBaseReferenceExpression(), "ResourceManager"); | ||
| 235 | CodeFieldReferenceExpression resourceManagerField = new CodeFieldReferenceExpression(null, "resourceManager"); | ||
| 236 | constructor.Statements.Add(new CodeAssignStatement(baseResourceManagerReference, resourceManagerField)); | ||
| 237 | |||
| 238 | //CodeMemberProperty resourceManagerProperty = new CodeMemberProperty(); | ||
| 239 | //resourceManagerProperty.Attributes = MemberAttributes.Public | MemberAttributes.Override; | ||
| 240 | //resourceManagerProperty.Name = "ResourceManager"; | ||
| 241 | //resourceManagerProperty.Type = new CodeTypeReference("ResourceManager"); | ||
| 242 | //CodeFieldReferenceExpression resourceManagerReference = new CodeFieldReferenceExpression(); | ||
| 243 | //resourceManagerReference.FieldName = "resourceManager"; | ||
| 244 | //resourceManagerProperty.GetStatements.Add(new CodeMethodReturnStatement(resourceManagerReference)); | ||
| 245 | //messageContainer.Members.Add(resourceManagerProperty); | ||
| 246 | |||
| 247 | return messageContainer; | ||
| 248 | } | ||
| 249 | } | ||
| 250 | } | ||
diff --git a/src/WixBuildTools.MsgGen/MsgGen.cs b/src/WixBuildTools.MsgGen/MsgGen.cs new file mode 100644 index 00000000..ff4a4a90 --- /dev/null +++ b/src/WixBuildTools.MsgGen/MsgGen.cs | |||
| @@ -0,0 +1,261 @@ | |||
| 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 WixBuildTools.MsgGen | ||
| 4 | { | ||
| 5 | using Microsoft.CSharp; | ||
| 6 | using System; | ||
| 7 | using System.CodeDom; | ||
| 8 | using System.CodeDom.Compiler; | ||
| 9 | using System.Collections; | ||
| 10 | using System.IO; | ||
| 11 | using System.Reflection; | ||
| 12 | using System.Resources; | ||
| 13 | using System.Runtime.InteropServices; | ||
| 14 | using System.Xml; | ||
| 15 | using System.Xml.Schema; | ||
| 16 | |||
| 17 | /// <summary> | ||
| 18 | /// The main entry point for MsgGen. | ||
| 19 | /// </summary> | ||
| 20 | public class MsgGen | ||
| 21 | { | ||
| 22 | /// <summary> | ||
| 23 | /// The main entry point for MsgGen. | ||
| 24 | /// </summary> | ||
| 25 | /// <param name="args">Commandline arguments for the application.</param> | ||
| 26 | /// <returns>Returns the application error code.</returns> | ||
| 27 | [STAThread] | ||
| 28 | public static int Main(string[] args) | ||
| 29 | { | ||
| 30 | try | ||
| 31 | { | ||
| 32 | MsgGenMain msgGen = new MsgGenMain(args); | ||
| 33 | } | ||
| 34 | catch (Exception e) | ||
| 35 | { | ||
| 36 | Console.WriteLine("MsgGen.exe : fatal error MSGG0000: {0}\r\n\r\nStack Trace:\r\n{1}", e.Message, e.StackTrace); | ||
| 37 | if (e is NullReferenceException || e is SEHException) | ||
| 38 | { | ||
| 39 | throw; | ||
| 40 | } | ||
| 41 | return 2; | ||
| 42 | } | ||
| 43 | |||
| 44 | return 0; | ||
| 45 | } | ||
| 46 | |||
| 47 | /// <summary> | ||
| 48 | /// Main class for MsgGen. | ||
| 49 | /// </summary> | ||
| 50 | private class MsgGenMain | ||
| 51 | { | ||
| 52 | private bool showLogo; | ||
| 53 | private bool showHelp; | ||
| 54 | |||
| 55 | private string sourceFile; | ||
| 56 | private string destClassFile; | ||
| 57 | private string destResourcesFile; | ||
| 58 | |||
| 59 | /// <summary> | ||
| 60 | /// Main method for the MsgGen application within the MsgGenMain class. | ||
| 61 | /// </summary> | ||
| 62 | /// <param name="args">Commandline arguments to the application.</param> | ||
| 63 | public MsgGenMain(string[] args) | ||
| 64 | { | ||
| 65 | this.showLogo = true; | ||
| 66 | this.showHelp = false; | ||
| 67 | |||
| 68 | this.sourceFile = null; | ||
| 69 | this.destClassFile = null; | ||
| 70 | this.destResourcesFile = null; | ||
| 71 | |||
| 72 | // parse the command line | ||
| 73 | this.ParseCommandLine(args); | ||
| 74 | |||
| 75 | if (null == this.sourceFile || null == this.destClassFile) | ||
| 76 | { | ||
| 77 | this.showHelp = true; | ||
| 78 | } | ||
| 79 | if (null == this.destResourcesFile) | ||
| 80 | { | ||
| 81 | this.destResourcesFile = Path.ChangeExtension(this.destClassFile, ".resources"); | ||
| 82 | } | ||
| 83 | |||
| 84 | // get the assemblies | ||
| 85 | Assembly msgGenAssembly = Assembly.GetExecutingAssembly(); | ||
| 86 | |||
| 87 | if (this.showLogo) | ||
| 88 | { | ||
| 89 | Console.WriteLine("Microsoft (R) Message Generation Tool version {0}", msgGenAssembly.GetName().Version.ToString()); | ||
| 90 | Console.WriteLine("Copyright (C) Microsoft Corporation 2004. All rights reserved."); | ||
| 91 | Console.WriteLine(); | ||
| 92 | } | ||
| 93 | if (this.showHelp) | ||
| 94 | { | ||
| 95 | Console.WriteLine(" usage: MsgGen.exe [-?] [-nologo] sourceFile destClassFile [destResourcesFile]"); | ||
| 96 | Console.WriteLine(); | ||
| 97 | Console.WriteLine(" -? this help information"); | ||
| 98 | Console.WriteLine(); | ||
| 99 | Console.WriteLine("For more information see: http://wix.sourceforge.net"); | ||
| 100 | return; // exit | ||
| 101 | } | ||
| 102 | |||
| 103 | // load the schema | ||
| 104 | XmlReader reader = null; | ||
| 105 | XmlSchemaCollection schemaCollection = null; | ||
| 106 | try | ||
| 107 | { | ||
| 108 | reader = new XmlTextReader(msgGenAssembly.GetManifestResourceStream("WixBuildTools.MsgGen.Xsd.messages.xsd")); | ||
| 109 | schemaCollection = new XmlSchemaCollection(); | ||
| 110 | schemaCollection.Add("http://schemas.microsoft.com/genmsgs/2004/07/messages", reader); | ||
| 111 | } | ||
| 112 | finally | ||
| 113 | { | ||
| 114 | reader.Close(); | ||
| 115 | } | ||
| 116 | |||
| 117 | // load the source file and process it | ||
| 118 | using (StreamReader sr = new StreamReader(this.sourceFile)) | ||
| 119 | { | ||
| 120 | XmlParserContext context = new XmlParserContext(null, null, null, XmlSpace.None); | ||
| 121 | XmlValidatingReader validatingReader = new XmlValidatingReader(sr.BaseStream, XmlNodeType.Document, context); | ||
| 122 | validatingReader.Schemas.Add(schemaCollection); | ||
| 123 | |||
| 124 | XmlDocument errorsDoc = new XmlDocument(); | ||
| 125 | errorsDoc.Load(validatingReader); | ||
| 126 | |||
| 127 | CodeCompileUnit codeCompileUnit = new CodeCompileUnit(); | ||
| 128 | |||
| 129 | using (ResourceWriter resourceWriter = new ResourceWriter(this.destResourcesFile)) | ||
| 130 | { | ||
| 131 | GenerateMessageFiles.Generate(errorsDoc, codeCompileUnit, resourceWriter); | ||
| 132 | |||
| 133 | GenerateCSharpCode(codeCompileUnit, this.destClassFile); | ||
| 134 | } | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | /// <summary> | ||
| 139 | /// Generate the actual C# code. | ||
| 140 | /// </summary> | ||
| 141 | /// <param name="codeCompileUnit">The code DOM.</param> | ||
| 142 | /// <param name="destClassFile">Destination C# source file.</param> | ||
| 143 | public static void GenerateCSharpCode(CodeCompileUnit codeCompileUnit, string destClassFile) | ||
| 144 | { | ||
| 145 | // generate the code with the C# code provider | ||
| 146 | CSharpCodeProvider provider = new CSharpCodeProvider(); | ||
| 147 | |||
| 148 | // obtain an ICodeGenerator from the CodeDomProvider class | ||
| 149 | ICodeGenerator gen = provider.CreateGenerator(); | ||
| 150 | |||
| 151 | // create a TextWriter to a StreamWriter to the output file | ||
| 152 | using (StreamWriter sw = new StreamWriter(destClassFile)) | ||
| 153 | { | ||
| 154 | using (IndentedTextWriter tw = new IndentedTextWriter(sw, " ")) | ||
| 155 | { | ||
| 156 | CodeGeneratorOptions options = new CodeGeneratorOptions(); | ||
| 157 | |||
| 158 | // code generation options | ||
| 159 | options.BlankLinesBetweenMembers = true; | ||
| 160 | options.BracingStyle = "C"; | ||
| 161 | |||
| 162 | // generate source code using the code generator | ||
| 163 | gen.GenerateCodeFromCompileUnit(codeCompileUnit, tw, options); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | /// <summary> | ||
| 169 | /// Parse the commandline arguments. | ||
| 170 | /// </summary> | ||
| 171 | /// <param name="args">Commandline arguments.</param> | ||
| 172 | private void ParseCommandLine(string[] args) | ||
| 173 | { | ||
| 174 | for (int i = 0; i < args.Length; ++i) | ||
| 175 | { | ||
| 176 | string arg = args[i]; | ||
| 177 | if (null == arg || "" == arg) // skip blank arguments | ||
| 178 | { | ||
| 179 | continue; | ||
| 180 | } | ||
| 181 | |||
| 182 | if ('-' == arg[0] || '/' == arg[0]) | ||
| 183 | { | ||
| 184 | string parameter = arg.Substring(1); | ||
| 185 | if ("nologo" == parameter) | ||
| 186 | { | ||
| 187 | this.showLogo = false; | ||
| 188 | } | ||
| 189 | else if ("?" == parameter || "help" == parameter) | ||
| 190 | { | ||
| 191 | this.showHelp = true; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | else if ('@' == arg[0]) | ||
| 195 | { | ||
| 196 | using (StreamReader reader = new StreamReader(arg.Substring(1))) | ||
| 197 | { | ||
| 198 | string line; | ||
| 199 | ArrayList newArgs = new ArrayList(); | ||
| 200 | |||
| 201 | while (null != (line = reader.ReadLine())) | ||
| 202 | { | ||
| 203 | string newArg = ""; | ||
| 204 | bool betweenQuotes = false; | ||
| 205 | for (int j = 0; j < line.Length; ++j) | ||
| 206 | { | ||
| 207 | // skip whitespace | ||
| 208 | if (!betweenQuotes && (' ' == line[j] || '\t' == line[j])) | ||
| 209 | { | ||
| 210 | if ("" != newArg) | ||
| 211 | { | ||
| 212 | newArgs.Add(newArg); | ||
| 213 | newArg = null; | ||
| 214 | } | ||
| 215 | |||
| 216 | continue; | ||
| 217 | } | ||
| 218 | |||
| 219 | // if we're escaping a quote | ||
| 220 | if ('\\' == line[j] && '"' == line[j]) | ||
| 221 | { | ||
| 222 | ++j; | ||
| 223 | } | ||
| 224 | else if ('"' == line[j]) // if we've hit a new quote | ||
| 225 | { | ||
| 226 | betweenQuotes = !betweenQuotes; | ||
| 227 | continue; | ||
| 228 | } | ||
| 229 | |||
| 230 | newArg = String.Concat(newArg, line[j]); | ||
| 231 | } | ||
| 232 | if ("" != newArg) | ||
| 233 | { | ||
| 234 | newArgs.Add(newArg); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | string[] ar = (string[])newArgs.ToArray(typeof(string)); | ||
| 238 | this.ParseCommandLine(ar); | ||
| 239 | } | ||
| 240 | } | ||
| 241 | else if (null == this.sourceFile) | ||
| 242 | { | ||
| 243 | this.sourceFile = arg; | ||
| 244 | } | ||
| 245 | else if (null == this.destClassFile) | ||
| 246 | { | ||
| 247 | this.destClassFile = arg; | ||
| 248 | } | ||
| 249 | else if (null == this.destResourcesFile) | ||
| 250 | { | ||
| 251 | this.destResourcesFile = arg; | ||
| 252 | } | ||
| 253 | else | ||
| 254 | { | ||
| 255 | throw new ArgumentException(String.Format("Unknown argument '{0}'.", arg)); | ||
| 256 | } | ||
| 257 | } | ||
| 258 | } | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | ||
diff --git a/src/WixBuildTools.MsgGen/WixBuildTools.MsgGen.csproj b/src/WixBuildTools.MsgGen/WixBuildTools.MsgGen.csproj new file mode 100644 index 00000000..7d7da64c --- /dev/null +++ b/src/WixBuildTools.MsgGen/WixBuildTools.MsgGen.csproj | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | <Project Sdk="Microsoft.NET.Sdk"> | ||
| 2 | |||
| 3 | <PropertyGroup> | ||
| 4 | <OutputType>Exe</OutputType> | ||
| 5 | <TargetFramework>net461</TargetFramework> | ||
| 6 | <IsTool>true</IsTool> | ||
| 7 | </PropertyGroup> | ||
| 8 | |||
| 9 | <ItemGroup> | ||
| 10 | <Content Include="build\WixBuildTools.MsgGen.targets" PackagePath="build\" /> | ||
| 11 | <Content Include="buildCrossTargeting\WixBuildTools.MsgGen.targets" PackagePath="buildCrossTargeting\" /> | ||
| 12 | </ItemGroup> | ||
| 13 | |||
| 14 | <ItemGroup> | ||
| 15 | <EmbeddedResource Include="Xsd\messages.xsd" /> | ||
| 16 | </ItemGroup> | ||
| 17 | |||
| 18 | <ItemGroup> | ||
| 19 | <PackageReference Include="Nerdbank.GitVersioning" Version="2.0.37-beta" PrivateAssets="all" /> | ||
| 20 | </ItemGroup> | ||
| 21 | |||
| 22 | </Project> | ||
diff --git a/src/WixBuildTools.MsgGen/Xsd/messages.xsd b/src/WixBuildTools.MsgGen/Xsd/messages.xsd new file mode 100644 index 00000000..fd086502 --- /dev/null +++ b/src/WixBuildTools.MsgGen/Xsd/messages.xsd | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- 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. --> | ||
| 3 | |||
| 4 | |||
| 5 | <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" | ||
| 6 | targetNamespace="http://schemas.microsoft.com/genmsgs/2004/07/messages" | ||
| 7 | xmlns="http://schemas.microsoft.com/genmsgs/2004/07/messages"> | ||
| 8 | <xs:annotation> | ||
| 9 | <xs:documentation> | ||
| 10 | Schema for describing any kind of messages. | ||
| 11 | </xs:documentation> | ||
| 12 | </xs:annotation> | ||
| 13 | |||
| 14 | <xs:element name="Messages"> | ||
| 15 | <xs:complexType> | ||
| 16 | <xs:sequence maxOccurs="unbounded"> | ||
| 17 | <xs:element ref="Class"/> | ||
| 18 | </xs:sequence> | ||
| 19 | <xs:attribute name="Namespace" type="xs:string" use="required"> | ||
| 20 | <xs:annotation><xs:documentation>Namespace of the generated class.</xs:documentation></xs:annotation> | ||
| 21 | </xs:attribute> | ||
| 22 | <xs:attribute name="Resources" type="xs:string" use="required"> | ||
| 23 | <xs:annotation><xs:documentation>Resources stream for messages. Will get namespace prepended to it.</xs:documentation></xs:annotation> | ||
| 24 | </xs:attribute> | ||
| 25 | </xs:complexType> | ||
| 26 | </xs:element> | ||
| 27 | |||
| 28 | <xs:element name="Class"> | ||
| 29 | <xs:complexType> | ||
| 30 | <xs:sequence minOccurs="0" maxOccurs="unbounded"> | ||
| 31 | <xs:element ref="Message"/> | ||
| 32 | </xs:sequence> | ||
| 33 | <xs:attribute name="Name" type="xs:string" use="required"> | ||
| 34 | <xs:annotation><xs:documentation>Name of the generated class.</xs:documentation></xs:annotation> | ||
| 35 | </xs:attribute> | ||
| 36 | <xs:attribute name="ContainerName" type="xs:string" use="required"> | ||
| 37 | <xs:annotation><xs:documentation>Name of the generated container class.</xs:documentation></xs:annotation> | ||
| 38 | </xs:attribute> | ||
| 39 | <xs:attribute name="BaseContainerName" type="xs:string" use="required"> | ||
| 40 | <xs:annotation><xs:documentation>Name of the base container class.</xs:documentation></xs:annotation> | ||
| 41 | </xs:attribute> | ||
| 42 | <xs:attribute name="Level" type="MessageLevelType"> | ||
| 43 | <xs:annotation><xs:documentation>Optional message level for this container class and derivative classes.</xs:documentation></xs:annotation> | ||
| 44 | </xs:attribute> | ||
| 45 | </xs:complexType> | ||
| 46 | </xs:element> | ||
| 47 | |||
| 48 | <xs:element name="Message"> | ||
| 49 | <xs:complexType> | ||
| 50 | <xs:sequence maxOccurs="unbounded"> | ||
| 51 | <xs:element ref="Instance"/> | ||
| 52 | </xs:sequence> | ||
| 53 | <xs:attribute name="Id" type="xs:string" use="required"> | ||
| 54 | <xs:annotation><xs:documentation>Name of the message type.</xs:documentation></xs:annotation> | ||
| 55 | </xs:attribute> | ||
| 56 | <xs:attribute name="Number" type="xs:integer" use="required"> | ||
| 57 | <xs:annotation><xs:documentation>Override the number for this message type.</xs:documentation></xs:annotation> | ||
| 58 | </xs:attribute> | ||
| 59 | <xs:attribute name="SourceLineNumbers" type="YesNoType"> | ||
| 60 | <xs:annotation><xs:documentation>Associate SourceLineNumbers with this message. The default value is "yes".</xs:documentation></xs:annotation> | ||
| 61 | </xs:attribute> | ||
| 62 | </xs:complexType> | ||
| 63 | </xs:element> | ||
| 64 | |||
| 65 | <xs:element name="Instance"> | ||
| 66 | <xs:complexType mixed="true"> | ||
| 67 | <xs:sequence minOccurs="0" maxOccurs="unbounded"> | ||
| 68 | <xs:element ref="Parameter"/> | ||
| 69 | </xs:sequence> | ||
| 70 | </xs:complexType> | ||
| 71 | </xs:element> | ||
| 72 | |||
| 73 | <xs:element name="Parameter"> | ||
| 74 | <xs:complexType> | ||
| 75 | <xs:attribute name="Type" type="xs:string" use="required"> | ||
| 76 | <xs:annotation><xs:documentation>Type of the parameter.</xs:documentation></xs:annotation> | ||
| 77 | </xs:attribute> | ||
| 78 | <xs:attribute name="Name" type="xs:string" use="required"> | ||
| 79 | <xs:annotation><xs:documentation>Name of the parameter.</xs:documentation></xs:annotation> | ||
| 80 | </xs:attribute> | ||
| 81 | </xs:complexType> | ||
| 82 | </xs:element> | ||
| 83 | |||
| 84 | <xs:simpleType name="YesNoType"> | ||
| 85 | <xs:annotation><xs:documentation>Values of this type will either be "yes" or "no".</xs:documentation></xs:annotation> | ||
| 86 | <xs:restriction base="xs:NMTOKEN"> | ||
| 87 | <xs:enumeration value="no"/> | ||
| 88 | <xs:enumeration value="yes"/> | ||
| 89 | </xs:restriction> | ||
| 90 | </xs:simpleType> | ||
| 91 | |||
| 92 | <xs:simpleType name="MessageLevelType"> | ||
| 93 | <xs:annotation><xs:documentation>The message level for this message which corresponds to the WixToolset.MessageLevel enumeration.</xs:documentation></xs:annotation> | ||
| 94 | <xs:restriction base="xs:NMTOKEN"> | ||
| 95 | <xs:enumeration value="Verbose"/> | ||
| 96 | <xs:enumeration value="Information"/> | ||
| 97 | <xs:enumeration value="Warning"/> | ||
| 98 | <xs:enumeration value="Error"/> | ||
| 99 | </xs:restriction> | ||
| 100 | </xs:simpleType> | ||
| 101 | </xs:schema> | ||
diff --git a/src/WixBuildTools.MsgGen/build/WixBuildTools.MsgGen.targets b/src/WixBuildTools.MsgGen/build/WixBuildTools.MsgGen.targets new file mode 100644 index 00000000..dfa7bcbe --- /dev/null +++ b/src/WixBuildTools.MsgGen/build/WixBuildTools.MsgGen.targets | |||
| @@ -0,0 +1,102 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- 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. --> | ||
| 3 | |||
| 4 | <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> | ||
| 5 | <PropertyGroup> | ||
| 6 | <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> | ||
| 7 | </PropertyGroup> | ||
| 8 | |||
| 9 | <ItemGroup> | ||
| 10 | <!--Provide support for setting type (BuildAction) from VS--> | ||
| 11 | <AvailableItemName Include="MsgGenSource" /> | ||
| 12 | </ItemGroup> | ||
| 13 | |||
| 14 | <PropertyGroup> | ||
| 15 | <MsgGenPath Condition=" '$(MsgGenPath)'=='' ">$(MSBuildThisFileDirectory)..\tools\</MsgGenPath> | ||
| 16 | </PropertyGroup> | ||
| 17 | |||
| 18 | <!-- | ||
| 19 | ================================================================================================ | ||
| 20 | MsgGen | ||
| 21 | |||
| 22 | Generates a .cs class file and a .resx file from an XML file. | ||
| 23 | |||
| 24 | [IN] | ||
| 25 | @(MsgGenSource) - The items to run through the MsgGen tool. | ||
| 26 | |||
| 27 | [OUT] | ||
| 28 | $(IntermediateOutputPath)%(Filename).cs - The generated .cs files to include in the compilation. | ||
| 29 | $(IntermediateOutputPath)%(MsgGenSource.ResourcesLogicalName) - The generated .resources file to embed in the assembly. | ||
| 30 | ================================================================================================ | ||
| 31 | --> | ||
| 32 | <PropertyGroup> | ||
| 33 | <MsgGenDependsOn> | ||
| 34 | PrepareMsgGen | ||
| 35 | </MsgGenDependsOn> | ||
| 36 | <PrepareResourcesDependsOn> | ||
| 37 | MsgGen; | ||
| 38 | $(PrepareResourcesDependsOn) | ||
| 39 | </PrepareResourcesDependsOn> | ||
| 40 | </PropertyGroup> | ||
| 41 | <Target | ||
| 42 | Name="MsgGen" | ||
| 43 | BeforeTargets="PrepareResources" | ||
| 44 | DependsOnTargets="$(MsgGenDependsOn)" | ||
| 45 | Condition=" '@(MsgGenSource)' != '' " | ||
| 46 | Inputs="@(MsgGenSource)" | ||
| 47 | Outputs="$(IntermediateOutputPath)%(MsgGenSource.Filename).cs; | ||
| 48 | $(IntermediateOutputPath)%(MsgGenSource.ResourcesLogicalName)"> | ||
| 49 | |||
| 50 | <Exec Command=""$(MsgGenPath)WixBuildTools.MsgGen.exe" -nologo "%(MsgGenSource.FullPath)" "$(MsgGenCsFile)" "$(MsgGenResourcesFile)"" | ||
| 51 | Outputs="$(MsgGenCsFile);$(MsgGenResourcesFile)" /> | ||
| 52 | |||
| 53 | <ItemGroup> | ||
| 54 | <!-- This will tell MSBuild to clean up the .cs and .resources file during a Clean build --> | ||
| 55 | <FileWrites Include="$(MsgGenCsFile);$(MsgGenResourcesFile)" /> | ||
| 56 | </ItemGroup> | ||
| 57 | </Target> | ||
| 58 | |||
| 59 | <!-- | ||
| 60 | ================================================================================================ | ||
| 61 | PrepareMsgGen | ||
| 62 | |||
| 63 | Creates properties and Include items for MsgGen. This must be separate from the MsgGen target | ||
| 64 | to workaround an MSBuild bug: AdditionalMetadata is ignored when the target is up-to-date. | ||
| 65 | |||
| 66 | ================================================================================================ | ||
| 67 | --> | ||
| 68 | <Target | ||
| 69 | Name="PrepareMsgGen" | ||
| 70 | Condition=" '@(MsgGenSource)' != '' "> | ||
| 71 | |||
| 72 | <CreateProperty Value="$(IntermediateOutputPath)%(MsgGenSource.Filename).cs"> | ||
| 73 | <Output TaskParameter="Value" PropertyName="MsgGenCsFile" /> | ||
| 74 | </CreateProperty> | ||
| 75 | |||
| 76 | <CreateProperty | ||
| 77 | Value="$(IntermediateOutputPath)%(MsgGenSource.ResourcesLogicalName)" | ||
| 78 | Condition=" '%(MsgGenSource.ResourcesLogicalName)' != '' "> | ||
| 79 | |||
| 80 | <Output TaskParameter="Value" PropertyName="MsgGenResourcesFile" /> | ||
| 81 | </CreateProperty> | ||
| 82 | |||
| 83 | <!-- Add the generated .cs file to the list of source files to compile --> | ||
| 84 | <CreateItem | ||
| 85 | Include="$(MsgGenCsFile)" | ||
| 86 | AdditionalMetadata="Link=%(MsgGenCsFile.Filename)%(MsgGenCsFile.Extension)"> | ||
| 87 | |||
| 88 | <Output TaskParameter="Include" ItemName="Compile" /> | ||
| 89 | </CreateItem> | ||
| 90 | |||
| 91 | <!-- Add the generated .resources file to the list of resources to embed --> | ||
| 92 | <CreateItem | ||
| 93 | Include="$(MsgGenResourcesFile)" | ||
| 94 | AdditionalMetadata="Link=%(MsgGenResourcesFile.Filename)%(MsgGenResourcesFile.Extension); | ||
| 95 | LogicalName=%(MsgGenSource.ResourcesLogicalName)" | ||
| 96 | Condition=" '$(MsgGenResourcesFile)' != '' "> | ||
| 97 | |||
| 98 | <Output TaskParameter="Include" ItemName="EmbeddedResource" /> | ||
| 99 | </CreateItem> | ||
| 100 | </Target> | ||
| 101 | |||
| 102 | </Project> | ||
diff --git a/src/WixBuildTools.MsgGen/buildCrossTargeting/WixBuildTools.MsgGen.targets b/src/WixBuildTools.MsgGen/buildCrossTargeting/WixBuildTools.MsgGen.targets new file mode 100644 index 00000000..a3985af5 --- /dev/null +++ b/src/WixBuildTools.MsgGen/buildCrossTargeting/WixBuildTools.MsgGen.targets | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- 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. --> | ||
| 3 | |||
| 4 | <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> | ||
| 5 | <Import Project="..\build\WixBuildTools.MsgGen.targets" /> | ||
| 6 | </Project> | ||
