diff options
author | Katelyn Gadd <kg@luminance.org> | 2018-07-18 03:04:42 +0300 |
---|---|---|
committer | Alexander Köplinger <alex.koeplinger@outlook.com> | 2018-07-18 03:04:42 +0300 |
commit | 5ff02dd3bfa8289a66329a7ebba266dcd7312740 (patch) | |
tree | eeb142490a0c4da396d25c3c9aed50dec7fadb84 /msvc/scripts | |
parent | c7ceb8f1e168adf14082b8a9b62e7f2e0a290514 (diff) |
Auto-generate Consts.cs on Windows when building from Visual Studio (#9598)
This adds a simple script for generating Consts.cs that can run on Windows, and makes it a dependency of corlib.csproj in the BCL solution file. From my initial testing this will autogenerate Consts.cs if it's missing and then corlib will successfully build.
This (mostly?) addresses issue https://github.com/mono/mono/issues/6886.
This currently has an awkward dependency on ```winsetup.bat``` and I modified it slightly to make it clearer whether the batch file succeeded.
Diffstat (limited to 'msvc/scripts')
-rwxr-xr-x | msvc/scripts/genconsts.cs | 98 | ||||
-rwxr-xr-x | msvc/scripts/genconsts.csproj | 23 | ||||
-rwxr-xr-x[-rw-r--r--] | msvc/scripts/genproj.cs | 32 |
3 files changed, 141 insertions, 12 deletions
diff --git a/msvc/scripts/genconsts.cs b/msvc/scripts/genconsts.cs new file mode 100755 index 00000000000..1ec83657e4e --- /dev/null +++ b/msvc/scripts/genconsts.cs @@ -0,0 +1,98 @@ +using System; +using System.IO; +using System.Reflection; +using System.Diagnostics; +using System.Text; +using System.Text.RegularExpressions; + +public static class Program { + public static int Main (string[] args) { + var myAssembly = Assembly.GetExecutingAssembly (); + var codeBase = new Uri (myAssembly.CodeBase); + var executablePath = Path.GetFullPath (codeBase.LocalPath); + var executableDirectory = Path.GetDirectoryName (executablePath); + + var winsetupDirectory = Path.Combine (executableDirectory, ".."); + var winsetupPath = Path.Combine (winsetupDirectory, "winsetup.bat"); + + var psi = new ProcessStartInfo (winsetupPath) { + WorkingDirectory = winsetupDirectory, + UseShellExecute = false, + ErrorDialog = false, + RedirectStandardOutput = true + }; + + string monoVersion, monoCorlibVersion; + + Process winsetupProcess; + + try { + winsetupProcess = Process.Start (psi); + } catch (Exception exc) { + Console.Error.WriteLine ("Failed starting winsetup.bat"); + Console.Error.WriteLine (exc); + return 1; + } + + using (winsetupProcess) { + var outputBuffer = new StringBuilder (); + + winsetupProcess.OutputDataReceived += (s, e) => { + outputBuffer.AppendLine (e.Data); + }; + winsetupProcess.BeginOutputReadLine (); + winsetupProcess.WaitForExit (); + + var output = outputBuffer.ToString ().Trim (); + + if (winsetupProcess.ExitCode != 0) { + Console.Error.WriteLine ("Failed running winsetup.bat"); + Console.Write (output); + return winsetupProcess.ExitCode; + } else { + var m = Regex.Match (output, "MONO_VERSION=([0-9.]+)"); + if (!m.Success) + return 1; + monoVersion = m.Groups[1].Value; + + // HACK: winsetup.bat produces N.N.N instead of N.N.N.N like configure.ac, + // so we add .0's to match the Consts.cs generated by make + while (monoVersion.Split ('.').Length < 4) + monoVersion += ".0"; + + Console.WriteLine ($"MONO_VERSION={monoVersion}"); + m = Regex.Match (output, "MONO_CORLIB_VERSION=([0-9]+)"); + if (!m.Success) + return 1; + monoCorlibVersion = m.Groups[1].Value; + Console.WriteLine ($"MONO_CORLIB_VERSION={monoCorlibVersion}"); + } + } + + var constsDirectory = Path.Combine (executableDirectory, "..", "..", "mcs", "build", "common"); + var constsTemplatePath = Path.Combine (constsDirectory, "Consts.cs.in"); + if (!Directory.Exists (constsDirectory) || !File.Exists (constsTemplatePath)) { + Console.Error.WriteLine ($"File not found: {constsTemplatePath}"); + return 1; + } + + var resultPath = Path.GetFullPath (Path.Combine (constsDirectory, "Consts.cs")); + var templateText = File.ReadAllText (constsTemplatePath); + + var resultText = templateText.Replace ("@MONO_VERSION@", monoVersion) + .Replace ("@MONO_CORLIB_VERSION@", monoCorlibVersion); + + if (File.Exists (resultPath)) { + var existingText = File.ReadAllText (resultPath); + if (existingText.Trim () == resultText.Trim ()) { + Console.WriteLine ($"{resultPath} not changed"); + return 0; + } + } + + File.WriteAllText (resultPath, resultText); + Console.WriteLine ($"Generated {resultPath} successfully"); + + return 0; + } +}
\ No newline at end of file diff --git a/msvc/scripts/genconsts.csproj b/msvc/scripts/genconsts.csproj new file mode 100755 index 00000000000..fa523495fff --- /dev/null +++ b/msvc/scripts/genconsts.csproj @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">Any CPU</Platform>
+ <OutputType>Exe</OutputType>
+ <AssemblyName>genconsts</AssemblyName>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <OutputPath>.\</OutputPath>
+ <ProjectGuid>{702AE2C0-71DD-4112-9A06-E4FABCA59986}</ProjectGuid>
+ <RunPostBuildEvent>Always</RunPostBuildEvent>
+ <PostBuildEvent>cd $(MSBuildProjectDirectory)
+$(TargetPath)</PostBuildEvent>
+ </PropertyGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <ItemGroup>
+ <Compile Include="genconsts.cs" />
+ <Reference Include="System" />
+ </ItemGroup>
+</Project>
\ No newline at end of file diff --git a/msvc/scripts/genproj.cs b/msvc/scripts/genproj.cs index fab5c4e6d4f..86794ed0ef5 100644..100755 --- a/msvc/scripts/genproj.cs +++ b/msvc/scripts/genproj.cs @@ -25,7 +25,7 @@ public enum Target { Library, Exe, Module, WinExe } -class SlnGenerator { +public class SlnGenerator { public static readonly string NewLine = "\r\n"; //Environment.NewLine; // "\n"; public SlnGenerator (string slnVersion) { @@ -53,8 +53,11 @@ class SlnGenerator { "net_4_x" }; - const string jay_vcxproj_guid = "{5D485D32-3B9F-4287-AB24-C8DA5B89F537}"; - const string jay_sln_guid = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"; + public const string csproj_type_guid = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"; + public const string vcxproj_type_guid = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"; + + public const string jay_vcxproj_guid = "{5D485D32-3B9F-4287-AB24-C8DA5B89F537}"; + public const string genconsts_csproj_guid = "{702AE2C0-71DD-4112-9A06-E4FABCA59986}"; public static Dictionary<string, HashSet<string>> profilesByGuid = new Dictionary<string, HashSet<string>> (); public List<MsbuildGenerator.VsCsproj> libraries = new List<MsbuildGenerator.VsCsproj> (); @@ -103,6 +106,7 @@ class SlnGenerator { var relativePath = MsbuildGenerator.GetRelativePath (slnFullPath, fullProjPath); var dependencyGuids = new string[0]; + if (proj.preBuildEvent.Contains ("jay")) dependencyGuids = new [] { jay_vcxproj_guid }; @@ -115,10 +119,10 @@ class SlnGenerator { if (dependencyGuids.Length > 0) Console.WriteLine ($"Project {fullProjPath} has {dependencyGuids.Length} dependencies: {string.Join(", ", dependencyGuids)}"); - WriteProjectReference(sln, "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}", proj.library, relativePath, proj.projectGuid, dependencyGuids); + WriteProjectReference(sln, csproj_type_guid, proj.library, relativePath, proj.projectGuid, dependencyGuids); } - private void WriteProjectConfigurationPlatforms (StreamWriter sln, string guid, string defaultPlatform) + private void WriteProjectConfigurationPlatforms (StreamWriter sln, string guid, string defaultPlatform, bool forceBuild) { var fallbackProfileNames = new List<string> (); @@ -136,8 +140,7 @@ class SlnGenerator { ) { fallbackProfileNames.Add (platformToBuild); platformToBuild = defaultPlatform; - // HACK: Force build for C++ executables like jay ('Win32') but not for managed assemblies - isBuildEnabled = (defaultPlatform == "Win32"); + isBuildEnabled = forceBuild; } sln.WriteLine ("\t\t{0}.Debug|{1}.ActiveCfg = Debug|{2}", guid, profile, platformToBuild); @@ -161,7 +164,10 @@ class SlnGenerator { sln.WriteLine (header); // Manually insert jay's vcxproj. We depend on jay.exe to perform build steps later. - WriteProjectReference (sln, jay_sln_guid, "jay", "mcs/jay/jay.vcxproj", jay_vcxproj_guid, null); + WriteProjectReference (sln, vcxproj_type_guid, "jay", "mcs/jay/jay.vcxproj", jay_vcxproj_guid, null); + + // Manually insert genconsts. This is used to generate Consts.cs. + WriteProjectReference (sln, csproj_type_guid, "genconsts", "msvc/scripts/genconsts.csproj", genconsts_csproj_guid, null); foreach (var proj in libraries) { WriteProjectReference (sln, fullPath, proj); @@ -181,11 +187,12 @@ class SlnGenerator { sln.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"); - // Manually insert jay's configurations because they are different - WriteProjectConfigurationPlatforms (sln, jay_vcxproj_guid, "Win32"); + // Manually insert configurations for jay and genconsts + WriteProjectConfigurationPlatforms (sln, jay_vcxproj_guid, "Win32", true); + WriteProjectConfigurationPlatforms (sln, genconsts_csproj_guid, "x86", true); foreach (var proj in libraries) { - WriteProjectConfigurationPlatforms (sln, proj.projectGuid, "net_4_x"); + WriteProjectConfigurationPlatforms (sln, proj.projectGuid, "net_4_x", false); } sln.WriteLine ("\tEndGlobalSection"); @@ -206,7 +213,7 @@ class SlnGenerator { public int Count { get { return libraries.Count; } } } -class MsbuildGenerator { +public class MsbuildGenerator { static readonly string NewLine = SlnGenerator.NewLine; static XmlNamespaceManager xmlns; @@ -222,6 +229,7 @@ class MsbuildGenerator { }; public static readonly (string, string[])[] fixed_dependencies = new [] { + ("corlib/corlib.csproj", new [] { SlnGenerator.genconsts_csproj_guid }), ("class/System.Web/System.Web.csproj", new [] { culevel_guid }) }; |