diff options
Diffstat (limited to 'src/WixToolset.BuildTasks/CreateProjectReferenceDefineConstants.cs')
-rw-r--r-- | src/WixToolset.BuildTasks/CreateProjectReferenceDefineConstants.cs | 271 |
1 files changed, 0 insertions, 271 deletions
diff --git a/src/WixToolset.BuildTasks/CreateProjectReferenceDefineConstants.cs b/src/WixToolset.BuildTasks/CreateProjectReferenceDefineConstants.cs deleted file mode 100644 index 7cda6b01..00000000 --- a/src/WixToolset.BuildTasks/CreateProjectReferenceDefineConstants.cs +++ /dev/null | |||
@@ -1,271 +0,0 @@ | |||
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.BuildTasks | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Globalization; | ||
8 | using System.IO; | ||
9 | using Microsoft.Build.Framework; | ||
10 | using Microsoft.Build.Utilities; | ||
11 | |||
12 | /// <summary> | ||
13 | /// An MSBuild task to create a list of preprocessor defines to be passed to candle from the | ||
14 | /// list of referenced projects. | ||
15 | /// </summary> | ||
16 | public sealed class CreateProjectReferenceDefineConstants : Task | ||
17 | { | ||
18 | private ITaskItem[] defineConstants; | ||
19 | private ITaskItem[] projectConfigurations; | ||
20 | private ITaskItem[] projectReferencePaths; | ||
21 | |||
22 | [Output] | ||
23 | public ITaskItem[] DefineConstants | ||
24 | { | ||
25 | get { return this.defineConstants; } | ||
26 | } | ||
27 | |||
28 | [Required] | ||
29 | public ITaskItem[] ProjectReferencePaths | ||
30 | { | ||
31 | get { return this.projectReferencePaths; } | ||
32 | set { this.projectReferencePaths = value; } | ||
33 | } | ||
34 | |||
35 | public ITaskItem[] ProjectConfigurations | ||
36 | { | ||
37 | get { return this.projectConfigurations; } | ||
38 | set { this.projectConfigurations = value; } | ||
39 | } | ||
40 | |||
41 | public override bool Execute() | ||
42 | { | ||
43 | List<ITaskItem> outputItems = new List<ITaskItem>(); | ||
44 | Dictionary<string, string> defineConstants = new Dictionary<string, string>(); | ||
45 | |||
46 | for (int i = 0; i < this.ProjectReferencePaths.Length; i++) | ||
47 | { | ||
48 | ITaskItem item = this.ProjectReferencePaths[i]; | ||
49 | |||
50 | string configuration = item.GetMetadata("Configuration"); | ||
51 | string fullConfiguration = item.GetMetadata("FullConfiguration"); | ||
52 | string platform = item.GetMetadata("Platform"); | ||
53 | |||
54 | string projectPath = CreateProjectReferenceDefineConstants.GetProjectPath(this.ProjectReferencePaths, i); | ||
55 | string projectDir = Path.GetDirectoryName(projectPath) + Path.DirectorySeparatorChar; | ||
56 | string projectExt = Path.GetExtension(projectPath); | ||
57 | string projectFileName = Path.GetFileName(projectPath); | ||
58 | string projectName = Path.GetFileNameWithoutExtension(projectPath); | ||
59 | |||
60 | string referenceName = CreateProjectReferenceDefineConstants.GetReferenceName(item, projectName); | ||
61 | |||
62 | string targetPath = item.GetMetadata("FullPath"); | ||
63 | string targetDir = Path.GetDirectoryName(targetPath) + Path.DirectorySeparatorChar; | ||
64 | string targetExt = Path.GetExtension(targetPath); | ||
65 | string targetFileName = Path.GetFileName(targetPath); | ||
66 | string targetName = Path.GetFileNameWithoutExtension(targetPath); | ||
67 | |||
68 | // If there is no configuration metadata on the project reference task item, | ||
69 | // check for any additional configuration data provided in the optional task property. | ||
70 | if (String.IsNullOrEmpty(fullConfiguration)) | ||
71 | { | ||
72 | fullConfiguration = this.FindProjectConfiguration(projectName); | ||
73 | if (!String.IsNullOrEmpty(fullConfiguration)) | ||
74 | { | ||
75 | string[] typeAndPlatform = fullConfiguration.Split('|'); | ||
76 | configuration = typeAndPlatform[0]; | ||
77 | platform = (typeAndPlatform.Length > 1 ? typeAndPlatform[1] : String.Empty); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | // write out the platform/configuration defines | ||
82 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.Configuration", referenceName)] = configuration; | ||
83 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.FullConfiguration", referenceName)] = fullConfiguration; | ||
84 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.Platform", referenceName)] = platform; | ||
85 | |||
86 | // write out the ProjectX defines | ||
87 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.ProjectDir", referenceName)] = projectDir; | ||
88 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.ProjectExt", referenceName)] = projectExt; | ||
89 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.ProjectFileName", referenceName)] = projectFileName; | ||
90 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.ProjectName", referenceName)] = projectName; | ||
91 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.ProjectPath", referenceName)] = projectPath; | ||
92 | |||
93 | // write out the TargetX defines | ||
94 | string targetDirDefine = String.Format(CultureInfo.InvariantCulture, "{0}.TargetDir", referenceName); | ||
95 | if (defineConstants.ContainsKey(targetDirDefine)) | ||
96 | { | ||
97 | //if target dir was already defined, redefine it as the common root shared by multiple references from the same project | ||
98 | string commonDir = FindCommonRoot(targetDir, defineConstants[targetDirDefine]); | ||
99 | if (!String.IsNullOrEmpty(commonDir)) | ||
100 | { | ||
101 | targetDir = commonDir; | ||
102 | } | ||
103 | } | ||
104 | defineConstants[targetDirDefine] = CreateProjectReferenceDefineConstants.EnsureEndsWithBackslash(targetDir); | ||
105 | |||
106 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.TargetExt", referenceName)] = targetExt; | ||
107 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.TargetFileName", referenceName)] = targetFileName; | ||
108 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.TargetName", referenceName)] = targetName; | ||
109 | |||
110 | //if target path was already defined, append to it creating a list of multiple references from the same project | ||
111 | string targetPathDefine = String.Format(CultureInfo.InvariantCulture, "{0}.TargetPath", referenceName); | ||
112 | if (defineConstants.ContainsKey(targetPathDefine)) | ||
113 | { | ||
114 | string oldTargetPath = defineConstants[targetPathDefine]; | ||
115 | if (!targetPath.Equals(oldTargetPath, StringComparison.OrdinalIgnoreCase)) | ||
116 | { | ||
117 | defineConstants[targetPathDefine] += ";" + targetPath; | ||
118 | } | ||
119 | |||
120 | //If there was only one targetpath we need to create its culture specific define | ||
121 | if (!oldTargetPath.Contains(";")) | ||
122 | { | ||
123 | string oldSubFolder = FindSubfolder(oldTargetPath, targetDir, targetFileName); | ||
124 | if (!String.IsNullOrEmpty(oldSubFolder)) | ||
125 | { | ||
126 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.{1}.TargetPath", referenceName, oldSubFolder.Replace('\\', '_'))] = oldTargetPath; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | // Create a culture specific define | ||
131 | string subFolder = FindSubfolder(targetPath, targetDir, targetFileName); | ||
132 | if (!String.IsNullOrEmpty(subFolder)) | ||
133 | { | ||
134 | defineConstants[String.Format(CultureInfo.InvariantCulture, "{0}.{1}.TargetPath", referenceName, subFolder.Replace('\\', '_'))] = targetPath; | ||
135 | } | ||
136 | |||
137 | } | ||
138 | else | ||
139 | { | ||
140 | defineConstants[targetPathDefine] = targetPath; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | foreach (KeyValuePair<string, string> define in defineConstants) | ||
145 | { | ||
146 | outputItems.Add(new TaskItem(String.Format(CultureInfo.InvariantCulture, "{0}={1}", define.Key, define.Value))); | ||
147 | } | ||
148 | |||
149 | this.defineConstants = outputItems.ToArray(); | ||
150 | |||
151 | return true; | ||
152 | } | ||
153 | |||
154 | public static string GetProjectPath(ITaskItem[] projectReferencePaths, int i) | ||
155 | { | ||
156 | return projectReferencePaths[i].GetMetadata("MSBuildSourceProjectFile"); | ||
157 | } | ||
158 | |||
159 | public static string GetReferenceName(ITaskItem item, string projectName) | ||
160 | { | ||
161 | string referenceName = item.GetMetadata("Name"); | ||
162 | if (String.IsNullOrEmpty(referenceName)) | ||
163 | { | ||
164 | referenceName = projectName; | ||
165 | } | ||
166 | |||
167 | // We cannot have an equals sign in the variable name because it | ||
168 | // messes with the preprocessor definitions on the command line. | ||
169 | referenceName = referenceName.Replace('=', '_'); | ||
170 | |||
171 | // We cannot have a double quote on the command line because it | ||
172 | // there is no way to escape it on the command line. | ||
173 | referenceName = referenceName.Replace('\"', '_'); | ||
174 | |||
175 | // We cannot have parens in the variable name because the WiX | ||
176 | // preprocessor will not be able to parse it. | ||
177 | referenceName = referenceName.Replace('(', '_'); | ||
178 | referenceName = referenceName.Replace(')', '_'); | ||
179 | |||
180 | return referenceName; | ||
181 | } | ||
182 | |||
183 | /// <summary> | ||
184 | /// Look through the configuration data in the ProjectConfigurations property | ||
185 | /// to find the configuration for a project, if available. | ||
186 | /// </summary> | ||
187 | /// <param name="projectName">Name of the project that is being searched for.</param> | ||
188 | /// <returns>Full configuration spec, for example "Release|Win32".</returns> | ||
189 | private string FindProjectConfiguration(string projectName) | ||
190 | { | ||
191 | string configuration = String.Empty; | ||
192 | |||
193 | if (this.ProjectConfigurations != null) | ||
194 | { | ||
195 | foreach (ITaskItem configItem in this.ProjectConfigurations) | ||
196 | { | ||
197 | string configProject = configItem.ItemSpec; | ||
198 | if (configProject.Length > projectName.Length && | ||
199 | configProject.StartsWith(projectName) && | ||
200 | configProject[projectName.Length] == '=') | ||
201 | { | ||
202 | configuration = configProject.Substring(projectName.Length + 1); | ||
203 | break; | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | |||
208 | return configuration; | ||
209 | } | ||
210 | |||
211 | /// <summary> | ||
212 | /// Finds the common root between two paths | ||
213 | /// </summary> | ||
214 | /// <param name="path1"></param> | ||
215 | /// <param name="path2"></param> | ||
216 | /// <returns>common root on success, empty string on failure</returns> | ||
217 | private static string FindCommonRoot(string path1, string path2) | ||
218 | { | ||
219 | path1 = path1.TrimEnd(Path.DirectorySeparatorChar); | ||
220 | path2 = path2.TrimEnd(Path.DirectorySeparatorChar); | ||
221 | |||
222 | while (!String.IsNullOrEmpty(path1)) | ||
223 | { | ||
224 | for (string searchPath = path2; !String.IsNullOrEmpty(searchPath); searchPath = Path.GetDirectoryName(searchPath)) | ||
225 | { | ||
226 | if (path1.Equals(searchPath, StringComparison.OrdinalIgnoreCase)) | ||
227 | { | ||
228 | return searchPath; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | path1 = Path.GetDirectoryName(path1); | ||
233 | } | ||
234 | |||
235 | return path1; | ||
236 | } | ||
237 | |||
238 | /// <summary> | ||
239 | /// Finds the subfolder of a path, excluding a root and filename. | ||
240 | /// </summary> | ||
241 | /// <param name="path">Path to examine</param> | ||
242 | /// <param name="rootPath">Root that must be present </param> | ||
243 | /// <param name="fileName"></param> | ||
244 | /// <returns></returns> | ||
245 | private static string FindSubfolder(string path, string rootPath, string fileName) | ||
246 | { | ||
247 | if (Path.GetFileName(path).Equals(fileName, StringComparison.OrdinalIgnoreCase)) | ||
248 | { | ||
249 | path = Path.GetDirectoryName(path); | ||
250 | } | ||
251 | |||
252 | if (path.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase)) | ||
253 | { | ||
254 | // cut out the root and return the subpath | ||
255 | return path.Substring(rootPath.Length).Trim(Path.DirectorySeparatorChar); | ||
256 | } | ||
257 | |||
258 | return String.Empty; | ||
259 | } | ||
260 | |||
261 | private static string EnsureEndsWithBackslash(string dir) | ||
262 | { | ||
263 | if (dir[dir.Length - 1] != Path.DirectorySeparatorChar) | ||
264 | { | ||
265 | dir += Path.DirectorySeparatorChar; | ||
266 | } | ||
267 | |||
268 | return dir; | ||
269 | } | ||
270 | } | ||
271 | } | ||