1 <?xml version=
"1.0" encoding=
"utf-8"?>
2 <Project DefaultTargets=
"Build" ToolsVersion=
"4.0" xmlns=
"http://schemas.microsoft.com/developer/msbuild/2003">
4 <UsingTask TaskName=
"WinConfigSetup" TaskFactory=
"CodeTaskFactory" AssemblyFile=
"$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
6 <ConfigFileRoot ParameterType=
"System.String" Required=
"true" />
7 <DisableDefines ParameterType=
"System.String" Required=
"false" />
8 <EnableDefines ParameterType=
"System.String" Required=
"false" />
9 <HaveDefines ParameterType=
"System.String" Required=
"false" />
12 <Code Type=
"Class" Language=
"cs">
18 using Microsoft.Build.Framework;
19 using Microsoft.Build.Utilities;
20 using System.Collections.Generic;
21 using System.Text.RegularExpressions;
23 public class _WinConfigSetup : Task
25 bool GetVersionsFromConfigureAC (string configureACFile, out string monoVersion, out string monoCorlibVersion)
29 monoCorlibVersion = null;
30 if (File.Exists (configureACFile))
32 // These are both fairly arbitrary strings.
33 var monoVersionRegEx = new Regex (@
"^AC_INIT\s*\(\s*mono,\s*\[?\s*([^\],\s]+)");
34 var monoCorlibVersionRegEx = new Regex (@
"^MONO_CORLIB_VERSION\s*=\s*(\S+)");
35 using (StreamReader reader = new StreamReader (configureACFile))
38 while ((line = reader.ReadLine ()) != null && (monoVersion == null || monoCorlibVersion == null))
40 var monoVersionMatch = monoVersionRegEx.Match (line);
41 if (monoVersionMatch.Success)
43 if (monoVersion != null)
45 Log.LogError(
"duplicate MONO_INIT in {0}", configureACFile);
48 monoVersion = monoVersionMatch.Groups[
1].Value;
49 Log.LogMessage (
"{0}:AC_INIT:MONO_VERSION=\"{
1}\
"", configureACFile, monoVersion);
53 var monoCorlibVersionMatch = monoCorlibVersionRegEx.Match (line);
54 if (monoCorlibVersionMatch.Success)
56 if (monoCorlibVersion != null)
58 // This is misleading. The loop stops when both found, so duplicates usually not noticed.
59 Log.LogError(
"duplicate MONO_CORLIB_VERSION in {0}", configureACFile);
62 monoCorlibVersion = monoCorlibVersionMatch.Groups[
1].Value;
63 Log.LogMessage (
"{0}:MONO_CORLIB_VERSION=\"{
1}\
"", configureACFile, monoCorlibVersion);
72 List
<string> GetConfigFeatures (string path, string featuresRegex)
74 var features = new List
<string> ();
75 if (File.Exists (path))
77 var regex = new Regex (featuresRegex);
78 using (StreamReader reader = new StreamReader (path))
81 while ((line = reader.ReadLine ()) != null)
83 var match = regex.Match (line);
84 if (match != null && match.Success)
86 if (match.Groups != null && match.Groups.Count ==
1)
88 var configLine = match.Groups[
0].ToString ();
89 if (!String.IsNullOrEmpty (configLine))
91 var configItems = configLine.Trim ().Split (' ');
92 if (configItems != null && configItems.Length ==
3)
94 // Second item should be the define.
95 features.Add (configItems[
1]);
106 string [] GetEnabledConfigFeatures (string path, string enableDefines)
108 string [] supportedFeatures = {
"ENABLE_ICALL_SYMBOL_MAP",
110 "ENABLE_LLVM_RUNTIME",
111 "ENABLE_HYBRID_SUSPEND",
112 "ENABLE_COOP_SUSPEND" };
114 var enableFeatures = GetConfigFeatures(path,
".*#define.*ENABLE_.*1");
115 if (enableDefines != null)
116 enableFeatures.AddRange (enableDefines.Split (';'));
118 // Only keep supported features on Windows platforms using MSVC.
119 var features = new List
<string> ();
120 foreach (var feature in enableFeatures)
121 if (Array.Exists(supportedFeatures, s =
> String.CompareOrdinal (s,feature) ==
0))
122 features.Add(feature);
123 return features.ToArray ();
126 string [] GetDisabledConfigFeatures (string path)
128 return GetConfigFeatures(path,
".*#define.*DISABLE_.*1").ToArray ();
131 void CreateConfigUsingTemplate (string templatePath, string targetPath, string [] disabledDefines, string [] enabledDefines, string [] haveDefines, string monoVersion, string monoCorlibVersion)
133 string tempFilePath =
"";
137 if (File.Exists (templatePath))
139 var disabledDefinesRegex = new Regex (
".*@DISABLE_DEFINES@.*");
140 var enabledDefinesRegex = new Regex (
".*@ENABLE_DEFINES@.*");
141 var haveDefinesRegex = new Regex (
".*@HAVE_DEFINES.*");
143 var definesList = new List
<Tuple<Regex, string []
>>
145 new Tuple
<Regex, string []
>(disabledDefinesRegex, disabledDefines),
146 new Tuple
<Regex, string []
>(enabledDefinesRegex, enabledDefines),
147 new Tuple
<Regex, string []
>(haveDefinesRegex, haveDefines)
150 var monoCorlibVersions = new string [] {
151 ".*#MONO_CORLIB_VERSION#.*",
152 "#MONO_CORLIB_VERSION#",
155 var monoCorlibVersionRegex = new Regex (monoCorlibVersions[
0]);
157 var monoVersions = new string [] {
158 ".*#MONO_VERSION#.*",
162 var monoVersionRegex = new Regex (monoVersions[
0]);
164 var versionList = new List
<Tuple<Regex, string []
>>
166 new Tuple
<Regex, string []
>(monoCorlibVersionRegex, monoCorlibVersions),
167 new Tuple
<Regex, string []
>(monoVersionRegex, monoVersions)
170 tempFilePath = Path.GetTempFileName ();
172 using (StreamReader reader = new StreamReader (templatePath))
173 using (StreamWriter writer = new StreamWriter (tempFilePath))
177 while ((line = reader.ReadLine ()) != null)
179 var replaced = false;
180 foreach (var defines in definesList)
182 match = defines.Item1.Match (line);
183 if (match != null && match.Success && defines.Item2 != null)
185 // Replace with disabled defines.
186 foreach (var define in defines.Item2)
188 writer.WriteLine (
"#ifndef {0}", define);
189 writer.WriteLine (
"#define {0} 1", define);
190 writer.WriteLine (
"#endif");
199 foreach (var version in versionList)
201 match = version.Item1.Match (line);
202 if (match != null && match.Success)
204 writer.WriteLine (line.Replace(version.Item2[
1], version.Item2[
2]));
212 writer.WriteLine (line);
216 bool overwrite = true;
217 if (File.Exists (targetPath))
219 if (File.ReadAllBytes (tempFilePath).SequenceEqual (File.ReadAllBytes (targetPath)))
224 File.Copy (tempFilePath, targetPath, true);
229 if (!String.IsNullOrEmpty (tempFilePath))
230 File.Delete (tempFilePath);
234 void CreateVersionFile (string targetFile)
236 string tempFile =
"";
240 tempFile = Path.GetTempFileName ();
242 using (StreamWriter writer = new StreamWriter (tempFile))
244 writer.WriteLine (
"#define FULL_VERSION \"Visual Studio built mono\
"");
247 bool overwrite = true;
248 if (File.Exists (targetFile))
250 if (File.ReadAllBytes (tempFile).SequenceEqual (File.ReadAllBytes (targetFile)))
255 File.Copy (tempFile, targetFile, true);
259 if (!String.IsNullOrEmpty (tempFile))
260 File.Delete (tempFile);
264 bool BackupConfigFile (string sourceConfigFile, string targetConfigFile)
267 if (File.Exists (sourceConfigFile))
269 var includesCygconfig = new Regex (
".*#include \"cygconfig.h\
".*");
271 var allText = File.ReadAllText (sourceConfigFile);
272 var match = includesCygconfig.Match (allText);
273 if (match == null || !match.Success)
275 File.Copy (sourceConfigFile, targetConfigFile, true);
283 public string ConfigFileRoot { get; set; }
284 public string DisableDefines { get; set; }
285 public string EnableDefines { get; set; }
286 public string HaveDefines { get; set; }
288 public override bool Execute ()
290 string configureACFile = Path.Combine (ConfigFileRoot, @
"configure.ac");
291 string configFile = Path.Combine (ConfigFileRoot, @
"config.h");
292 string cygConfigFile = Path.Combine (ConfigFileRoot, @
"cygconfig.h");
293 string winConfigFile = Path.Combine (ConfigFileRoot, @
"winconfig.h");
294 string versionFile = Path.Combine (ConfigFileRoot, @
"mono\mini\version.h");
296 Log.LogMessage (MessageImportance.High,
"Setting up Mono configuration headers...");
298 BackupConfigFile (configFile, cygConfigFile);
300 string monoVersion = null;
301 string monoCorlibVersion = null;
302 if (!GetVersionsFromConfigureAC (configureACFile, out monoVersion, out monoCorlibVersion))
305 if (monoVersion == null)
307 Log.LogError(
"failed to parse version from AC_INIT in {0}", configureACFile);
311 if (monoCorlibVersion == null)
313 Log.LogError(
"failed to parse MONO_CORLIB_VERSION from {0}", configureACFile);
317 var disableDefines = GetDisabledConfigFeatures (cygConfigFile);
318 var enableDefines = GetEnabledConfigFeatures (cygConfigFile, EnableDefines);
319 var haveDefines = (HaveDefines != null) ? HaveDefines.Split (';') : null;
320 CreateConfigUsingTemplate (winConfigFile, configFile, disableDefines, enableDefines, haveDefines, monoVersion, monoCorlibVersion);
322 CreateVersionFile (versionFile);
324 Log.LogMessage (MessageImportance.High,
"Successfully setup Mono configuration headers {0} and {1} from {2}.", configFile, versionFile, winConfigFile);
334 <Target Name=
"RunWinConfigSetup">
335 <WinConfigSetup ConfigFileRoot=
"$(MSBuildThisFileDirectory)..\"