3 using System.Collections.Generic;
5 using System.Globalization;
7 using System.Xml.XPath;
12 Library, Exe, Module, WinExe
15 public enum LanguageVersion {
25 public static readonly string NewLine = "\r\n"; //Environment.NewLine; // "\n";
26 public SlnGenerator (string formatVersion = "2012")
28 switch (formatVersion) {
30 this.header = MakeHeader ("10.00", "2008");
33 this.header = MakeHeader ("12.00", "2012");
38 const string project_start = "Project(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"{0}\", \"{1}\", \"{2}\""; // Note: No need to double up on {} around {2}
39 const string project_end = "EndProject";
41 List<MsbuildGenerator.VsCsproj> libraries = new List<MsbuildGenerator.VsCsproj> ();
44 string MakeHeader (string formatVersion, string yearTag)
46 return string.Format ("Microsoft Visual Studio Solution File, Format Version {0}" + NewLine + "# Visual Studio {1}", formatVersion, yearTag);
49 public void Add (MsbuildGenerator.VsCsproj vsproj)
52 libraries.Add (vsproj);
53 } catch (Exception ex) {
54 Console.WriteLine (ex);
58 public void Write (string filename)
60 using (var sln = new StreamWriter (filename)) {
62 sln.WriteLine (header);
63 foreach (var proj in libraries) {
64 sln.WriteLine (project_start, proj.library, proj.csProjFilename, proj.projectGuid);
65 sln.WriteLine (project_end);
67 sln.WriteLine ("Global");
69 sln.WriteLine ("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
70 sln.WriteLine ("\t\tDebug|Any CPU = Debug|Any CPU");
71 sln.WriteLine ("\t\tRelease|Any CPU = Release|Any CPU");
72 sln.WriteLine ("\tEndGlobalSection");
74 sln.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
75 foreach (var proj in libraries) {
76 var guid = proj.projectGuid;
77 sln.WriteLine ("\t\t{0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", guid);
78 sln.WriteLine ("\t\t{0}.Debug|Any CPU.Build.0 = Debug|Any CPU", guid);
79 sln.WriteLine ("\t\t{0}.Release|Any CPU.ActiveCfg = Release|Any CPU", guid);
80 sln.WriteLine ("\t\t{0}.Release|Any CPU.Build.0 = Release|Any CPU", guid);
82 sln.WriteLine ("\tEndGlobalSection");
84 sln.WriteLine ("\tGlobalSection(SolutionProperties) = preSolution");
85 sln.WriteLine ("\t\tHideSolutionNode = FALSE");
86 sln.WriteLine ("\tEndGlobalSection");
88 sln.WriteLine ("EndGlobal");
92 internal bool ContainsProjectIdentifier (string projId)
94 return libraries.FindIndex (x => (x.library == projId)) >= 0;
97 public int Count { get { return libraries.Count; } }
100 class MsbuildGenerator {
101 static readonly string NewLine = SlnGenerator.NewLine;
102 static XmlNamespaceManager xmlns;
104 public const string profile_2_0 = "_2_0";
105 public const string profile_3_5 = "_3_5";
106 public const string profile_4_0 = "_4_0";
107 public const string profile_4_5 = "_4_5";
111 Console.WriteLine ("Invalid argument");
114 static string template;
115 static MsbuildGenerator ()
117 using (var input = new StreamReader ("csproj.tmpl")) {
118 template = input.ReadToEnd ();
121 xmlns = new XmlNamespaceManager (new NameTable ());
122 xmlns.AddNamespace ("x", "http://schemas.microsoft.com/developer/msbuild/2003");
125 // The directory as specified in order.xml
132 public string CsprojFilename;
135 // Our base directory, this is relative to our exectution point mono/msvc/scripts
139 public string LibraryOutput, AbsoluteLibraryOutput;
141 public MsbuildGenerator (XElement xproject)
143 this.xproject = xproject;
144 dir = xproject.Attribute ("dir").Value;
145 library = xproject.Attribute ("library").Value;
146 CsprojFilename = "..\\..\\mcs\\" + dir + "\\" + library + ".csproj";
147 LibraryOutput = xproject.Element ("library_output").Value;
149 projectGuid = LookupOrGenerateGuid ();
150 fx_version = xproject.Element ("fx_version").Value;
151 Csproj = new VsCsproj () {
152 csProjFilename = this.CsprojFilename,
153 projectGuid = this.projectGuid,
154 library_output = this.LibraryOutput,
155 fx_version = double.Parse (fx_version),
156 library = this.library
161 class_dir = "../class/";
162 base_dir = "../../mcs/mcs";
166 foreach (char c in dir) {
168 mcs_topdir = "..//" + mcs_topdir;
170 class_dir = mcs_topdir.Substring (3);
172 base_dir = Path.Combine ("..", "..", "mcs", dir);
174 AbsoluteLibraryOutput = Path.GetFullPath (Path.Combine (base_dir, LibraryOutput));
177 string LookupOrGenerateGuid ()
179 var projectFile = NativeName (CsprojFilename);
180 if (File.Exists (projectFile)){
181 var doc = XDocument.Load (projectFile);
182 return doc.XPathSelectElement ("x:Project/x:PropertyGroup/x:ProjectGuid", xmlns).Value;
184 return "{" + Guid.NewGuid ().ToString ().ToUpper () + "}";
189 StringBuilder defines = new StringBuilder ();
190 bool Optimize = true;
191 bool want_debugging_support = false;
192 Dictionary<string, string> embedded_resources = new Dictionary<string, string> ();
193 List<string> warning_as_error = new List<string> ();
194 List<int> ignore_warning = new List<int> ();
195 bool load_default_config = true;
197 List<string> references = new List<string> ();
198 List<string> libs = new List<string> ();
199 List<string> reference_aliases = new List<string> ();
200 bool showWarnings = false;
203 #pragma warning disable 0219, 0414
204 int WarningLevel = 4;
206 bool Checked = false;
207 bool WarningsAreErrors;
208 bool VerifyClsCompliance = true;
209 string win32IconFile;
210 string StrongNameKeyFile;
211 bool copyLocal = true;
212 Target Target = Target.Exe;
213 string TargetExt = ".exe";
215 string StrongNameKeyContainer;
216 bool StrongNameDelaySign = false;
217 LanguageVersion Version = LanguageVersion.Default;
220 // Class directory, relative to
222 #pragma warning restore 0219,414
224 readonly char [] argument_value_separator = new char [] { ';', ',' };
227 // This parses the -arg and /arg options to the compiler, even if the strings
228 // in the following text use "/arg" on the strings.
230 bool CSCParseOption (string option, ref string [] args)
232 int idx = option.IndexOf (':');
239 arg = option.Substring (0, idx);
241 value = option.Substring (idx + 1);
244 switch (arg.ToLower (CultureInfo.InvariantCulture)) {
256 Target = Target.WinExe;
260 Target = Target.Library;
265 Target = Target.Module;
266 TargetExt = ".netmodule";
275 if (value.Length == 0) {
277 Environment.Exit (1);
295 case "/incremental+":
296 case "/incremental-":
302 if (value.Length == 0) {
304 Environment.Exit (1);
307 foreach (string d in value.Split (argument_value_separator)) {
308 if (defines.Length != 0)
309 defines.Append (";");
318 // We should collect data, runtime, etc and store in the file specified
322 case "/linkresource":
325 bool embeded = arg [1] == 'r' || arg [1] == 'R';
326 string [] s = value.Split (argument_value_separator);
329 if (s [0].Length == 0)
331 embedded_resources [s [0]] = Path.GetFileName (s [0]);
334 embedded_resources [s [0]] = s [1];
337 Console.WriteLine ("Does not support this method yet: {0}", arg);
338 Environment.Exit (1);
341 Console.WriteLine ("Wrong number of arguments for option `{0}'", option);
342 Environment.Exit (1);
349 Console.WriteLine ("/recurse not supported");
350 Environment.Exit (1);
355 if (value.Length == 0) {
356 Console.WriteLine ("-reference requires an argument");
357 Environment.Exit (1);
360 string [] refs = value.Split (argument_value_separator);
361 foreach (string r in refs) {
363 int index = val.IndexOf ('=');
365 reference_aliases.Add (r);
370 references.Add (val);
380 Console.WriteLine ("{0} = not supported", arg);
388 win32IconFile = value;
392 want_debugging_support = false;
397 want_debugging_support = true;
414 VerifyClsCompliance = false;
427 case "/warnaserror+":
428 if (value.Length == 0) {
429 WarningsAreErrors = true;
431 foreach (string wid in value.Split (argument_value_separator))
432 warning_as_error.Add (wid);
437 // Console.WriteLine ("Warning ignoring /runtime:v4");
440 case "/warnaserror-":
441 if (value.Length == 0) {
442 WarningsAreErrors = false;
444 foreach (string wid in value.Split (argument_value_separator))
445 warning_as_error.Remove (wid);
450 WarningLevel = Int32.Parse (value);
456 if (value.Length == 0) {
457 Console.WriteLine ("/nowarn requires an argument");
458 Environment.Exit (1);
461 warns = value.Split (argument_value_separator);
462 foreach (string wc in warns) {
464 if (wc.Trim ().Length == 0)
467 int warn = Int32.Parse (wc);
469 throw new ArgumentOutOfRangeException ("warn");
471 ignore_warning.Add (warn);
473 Console.WriteLine (String.Format ("`{0}' is not a valid warning number", wc));
474 Environment.Exit (1);
481 load_default_config = false;
497 if (value == String.Empty) {
498 Console.WriteLine ("{0} requires an argument", arg);
499 Environment.Exit (1);
501 StrongNameKeyFile = value;
503 case "/keycontainer":
504 if (value == String.Empty) {
505 Console.WriteLine ("{0} requires an argument", arg);
506 Environment.Exit (1);
508 StrongNameKeyContainer = value;
512 StrongNameDelaySign = true;
515 StrongNameDelaySign = false;
519 switch (value.ToLower (CultureInfo.InvariantCulture)) {
521 Version = LanguageVersion.ISO_1;
525 Version = LanguageVersion.Default;
528 Version = LanguageVersion.ISO_2;
531 Version = LanguageVersion.Future;
534 Console.WriteLine ("Invalid option `{0}' for /langversion. It must be either `ISO-1', `ISO-2' or `Default'", value);
535 Environment.Exit (1);
543 Console.WriteLine ("Failing with : {0}", arg);
547 static string [] LoadArgs (string file)
550 var args = new List<string> ();
553 f = new StreamReader (file);
558 StringBuilder sb = new StringBuilder ();
560 while ((line = f.ReadLine ()) != null) {
563 for (int i = 0; i < t; i++) {
566 if (c == '"' || c == '\'') {
569 for (i++; i < t; i++) {
576 } else if (c == ' ') {
578 args.Add (sb.ToString ());
585 args.Add (sb.ToString ());
590 string [] ret_value = new string [args.Count];
591 args.CopyTo (ret_value, 0);
596 static string Load (string f)
598 var native = NativeName (f);
600 if (File.Exists (native)) {
601 using (var sr = new StreamReader (native)) {
602 return sr.ReadToEnd ();
608 public static string NativeName (string path)
610 if (System.IO.Path.DirectorySeparatorChar == '/')
611 return path.Replace ("\\", "/");
613 return path.Replace ("/", "\\");
616 public class VsCsproj {
617 public string projectGuid;
618 public string output;
619 public string library_output;
620 public string csProjFilename;
621 public double fx_version;
622 public List<VsCsproj> projReferences = new List<VsCsproj> ();
623 public string library;
626 public VsCsproj Csproj;
628 public VsCsproj Generate (Dictionary<string,MsbuildGenerator> projects, bool showWarnings = false)
630 var generatedProjFile = NativeName (Csproj.csProjFilename);
631 //Console.WriteLine ("Generating: {0}", generatedProjFile);
633 string boot, flags, output_name, built_sources, response, profile;
635 boot = xproject.Element ("boot").Value;
636 flags = xproject.Element ("flags").Value;
637 output_name = xproject.Element ("output").Value;
638 built_sources = xproject.Element ("built_sources").Value;
639 response = xproject.Element ("response").Value;
640 //if (library.EndsWith("-build")) fx_version = "2.0"; // otherwise problem if .NET4.5 is installed, seems. (https://github.com/nikhilk/scriptsharp/issues/156)
641 profile = xproject.Element ("profile").Value;
642 if (string.IsNullOrEmpty (response)) {
643 // Address the issue where entries are missing the fx_version
644 // Should be fixed in the Makefile or elsewhere; this is a workaround
645 //<fx_version>basic</fx_version>
646 //<profile>./../build/deps/mcs.exe.sources.response</profile>
647 //<response></response>
649 profile = fx_version;
650 if (response.Contains ("build") || response.Contains ("basic") || response.Contains (profile_2_0)) {
652 if (response.Contains (profile_2_0)) profile = "net_2_0";
653 } if (response.Contains ("build") || response.Contains ("basic") || response.Contains (profile_2_0)) {
655 } else if (response.Contains (profile_3_5)) {
658 } else if (response.Contains (profile_4_0)) {
661 } else if (response.Contains (profile_4_5)) {
667 // Prebuild code, might be in inputs, check:
668 // inputs/LIBRARY-PROFILE.pre
669 // inputs/LIBRARY.pre
671 string prebuild = Load (library + ".pre");
672 string prebuild_windows, prebuild_unix;
674 int q = library.IndexOf ("-");
676 prebuild = prebuild + Load (library.Substring (0, q) + ".pre");
678 if (prebuild.IndexOf ("@MONO@") != -1){
679 prebuild_unix = prebuild.Replace ("@MONO@", "mono").Replace ("@CAT@", "cat");
680 prebuild_windows = prebuild.Replace ("@MONO@", "").Replace ("@CAT@", "type");
682 prebuild_unix = prebuild.Replace ("jay.exe", "jay");
683 prebuild_windows = prebuild;
686 const string condition_unix = "Condition=\" '$(OS)' != 'Windows_NT' \"";
687 const string condition_windows = "Condition=\" '$(OS)' == 'Windows_NT' \"";
689 " <PreBuildEvent " + condition_unix + ">\n" + prebuild_unix + "\n </PreBuildEvent>\n" +
690 " <PreBuildEvent " + condition_windows + ">\n" + prebuild_windows + "\n </PreBuildEvent>\n";
692 var all_args = new Queue<string []> ();
693 all_args.Enqueue (flags.Split ());
694 while (all_args.Count > 0) {
695 string [] f = all_args.Dequeue ();
697 for (int i = 0; i < f.Length; i++) {
698 if (f [i].Length > 0 && f [i][0] == '-')
699 f [i] = "/" + f [i].Substring (1);
701 if (f [i] [0] == '@') {
702 string [] extra_args;
703 string response_file = f [i].Substring (1);
705 var resp_file_full = Path.Combine (base_dir, response_file);
706 extra_args = LoadArgs (resp_file_full);
707 if (extra_args == null) {
708 Console.WriteLine ("Unable to open response file: " + resp_file_full);
709 Environment.Exit (1);
712 all_args.Enqueue (extra_args);
716 if (CSCParseOption (f [i], ref f))
718 Console.WriteLine ("Failure with {0}", f [i]);
719 Environment.Exit (1);
723 string [] source_files;
724 //Console.WriteLine ("Base: {0} res: {1}", base_dir, response);
725 using (var reader = new StreamReader (NativeName (base_dir + "\\" + response))) {
726 source_files = reader.ReadToEnd ().Split ();
729 Array.Sort (source_files);
731 StringBuilder sources = new StringBuilder ();
732 foreach (string s in source_files) {
736 string src = s.Replace ("/", "\\");
737 if (src.StartsWith (@"Test\..\"))
738 src = src.Substring (8, src.Length - 8);
740 sources.AppendFormat (" <Compile Include=\"{0}\" />" + NewLine, src);
743 source_files = built_sources.Split ();
744 Array.Sort (source_files);
746 foreach (string s in source_files) {
750 string src = s.Replace ("/", "\\");
751 if (src.StartsWith (@"Test\..\"))
752 src = src.Substring (8, src.Length - 8);
754 sources.AppendFormat (" <Compile Include=\"{0}\" />" + NewLine, src);
756 sources.Remove (sources.Length - 1, 1);
758 //if (library == "corlib-build") // otherwise, does not compile on fx_version == 4.0
760 // references.Add("System.dll");
761 // references.Add("System.Xml.dll");
764 //if (library == "System.Core-build") // otherwise, slow compile. May be a transient need.
766 // this.ignore_warning.Add(1685);
767 // this.ignore_warning.Add(0436);
770 var refs = new StringBuilder ();
772 bool is_test = response.Contains ("_test_");
774 // F:\src\mono\mcs\class\lib\net_2_0\nunit.framework.dll
775 // F:\src\mono\mcs\class\SomeProject\SomeProject_test_-net_2_0.csproj
776 var nunitLibPath = string.Format (@"..\lib\{0}\nunit.framework.dll", profile);
777 refs.Append (string.Format (" <Reference Include=\"{0}\" />" + NewLine, nunitLibPath));
780 var resources = new StringBuilder ();
781 if (embedded_resources.Count > 0) {
782 resources.AppendFormat (" <ItemGroup>" + NewLine);
783 foreach (var dk in embedded_resources) {
784 resources.AppendFormat (" <EmbeddedResource Include=\"{0}\">" + NewLine, dk.Key);
785 resources.AppendFormat (" <LogicalName>{0}</LogicalName>" + NewLine, dk.Value);
786 resources.AppendFormat (" </EmbeddedResource>" + NewLine);
788 resources.AppendFormat (" </ItemGroup>" + NewLine);
792 if (references.Count > 0 || reference_aliases.Count > 0) {
793 // -r:mscorlib.dll -r:System.dll
794 //<ProjectReference Include="..\corlib\corlib-basic.csproj">
795 // <Project>{155aef28-c81f-405d-9072-9d52780e3e70}</Project>
796 // <Name>corlib-basic</Name>
797 //</ProjectReference>
798 //<ProjectReference Include="..\System\System-basic.csproj">
799 // <Project>{2094e859-db2f-481f-9630-f89d31d9ed48}</Project>
800 // <Name>System-basic</Name>
801 //</ProjectReference>
802 var refdistinct = references.Distinct ();
803 foreach (string r in refdistinct) {
804 var match = GetMatchingCsproj (Path.GetFileName (r), projects);
806 AddProjectReference (refs, Csproj, match, r, null);
809 Console.WriteLine ("{0}: Could not find a matching project reference for {1}", library, Path.GetFileName (r));
810 Console.WriteLine (" --> Adding reference with hintpath instead");
812 refs.Append (" <Reference Include=\"" + r + "\">" + NewLine);
813 refs.Append (" <SpecificVersion>False</SpecificVersion>" + NewLine);
814 refs.Append (" <HintPath>" + r + "</HintPath>" + NewLine);
815 refs.Append (" <Private>False</Private>" + NewLine);
816 refs.Append (" </Reference>" + NewLine);
820 foreach (string r in reference_aliases) {
821 int index = r.IndexOf ('=');
822 string alias = r.Substring (0, index);
823 string assembly = r.Substring (index + 1);
824 var match = GetMatchingCsproj (assembly, projects, explicitPath: true);
826 AddProjectReference (refs, Csproj, match, r, alias);
828 throw new NotSupportedException (string.Format ("From {0}, could not find a matching project reference for {1}", library, r));
829 refs.Append (" <Reference Include=\"" + assembly + "\">" + NewLine);
830 refs.Append (" <SpecificVersion>False</SpecificVersion>" + NewLine);
831 refs.Append (" <HintPath>" + r + "</HintPath>" + NewLine);
832 refs.Append (" <Aliases>" + alias + "</Aliases>" + NewLine);
833 refs.Append (" </Reference>" + NewLine);
840 // ../class/lib/build/tmp/System.Xml.dll [No longer possible, we should be removing this from order.xml]
841 // /class/lib/basic/System.Core.dll
842 // <library_output>mcs.exe</library_output>
843 string build_output_dir;
844 if (LibraryOutput.Contains ("/"))
845 build_output_dir = Path.GetDirectoryName (LibraryOutput);
847 build_output_dir = "bin\\Debug\\" + library;
850 string postbuild_unix = string.Empty;
851 string postbuild_windows = string.Empty;
854 " <PostBuildEvent " + condition_unix + ">\n" + postbuild_unix + "\n </PostBuildEvent>\n" +
855 " <PostBuildEvent " + condition_windows + ">\n" + postbuild_windows + "\n </PostBuildEvent>";
858 bool basic_or_build = (library.Contains ("-basic") || library.Contains ("-build"));
861 // Replace the template values
864 string strongNameSection = "";
865 if (StrongNameKeyFile != null){
866 strongNameSection = String.Format (
867 " <PropertyGroup>\n" +
868 " <SignAssembly>true</SignAssembly>\n" +
870 " </PropertyGroup>\n" +
871 " <PropertyGroup>\n" +
872 " <AssemblyOriginatorKeyFile>{0}</AssemblyOriginatorKeyFile>\n" +
873 " </PropertyGroup>", StrongNameKeyFile, StrongNameDelaySign ? " <DelaySign>true</DelaySign>\n" : "");
875 Csproj.output = template.
876 Replace ("@SIGNATURE@", strongNameSection).
877 Replace ("@PROJECTGUID@", Csproj.projectGuid).
878 Replace ("@DEFINES@", defines.ToString ()).
879 Replace ("@DISABLEDWARNINGS@", string.Join (",", (from i in ignore_warning select i.ToString ()).ToArray ())).
880 //Replace("@NOSTDLIB@", (basic_or_build || (!StdLib)) ? "<NoStdLib>true</NoStdLib>" : string.Empty).
881 Replace ("@NOSTDLIB@", "<NoStdLib>" + (!StdLib).ToString () + "</NoStdLib>").
882 Replace ("@NOCONFIG@", "<NoConfig>" + (!load_default_config).ToString () + "</NoConfig>").
883 Replace ("@ALLOWUNSAFE@", Unsafe ? "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>" : "").
884 Replace ("@FX_VERSION", fx_version).
885 Replace ("@ASSEMBLYNAME@", Path.GetFileNameWithoutExtension (output_name)).
886 Replace ("@OUTPUTDIR@", build_output_dir).
887 Replace ("@DEFINECONSTANTS@", defines.ToString ()).
888 Replace ("@DEBUG@", want_debugging_support ? "true" : "false").
889 Replace ("@DEBUGTYPE@", want_debugging_support ? "full" : "pdbonly").
890 Replace ("@REFERENCES@", refs.ToString ()).
891 Replace ("@PREBUILD@", prebuild).
892 Replace ("@POSTBUILD@", postbuild).
893 //Replace ("@ADDITIONALLIBPATHS@", String.Format ("<AdditionalLibPaths>{0}</AdditionalLibPaths>", string.Join (",", libs.ToArray ()))).
894 Replace ("@ADDITIONALLIBPATHS@", String.Empty).
895 Replace ("@RESOURCES@", resources.ToString ()).
896 Replace ("@OPTIMIZE@", Optimize ? "true" : "false").
897 Replace ("@SOURCES@", sources.ToString ());
899 //Console.WriteLine ("Generated {0}", ofile.Replace ("\\", "/"));
900 using (var o = new StreamWriter (generatedProjFile)) {
901 o.WriteLine (Csproj.output);
907 void AddProjectReference (StringBuilder refs, VsCsproj result, MsbuildGenerator match, string r, string alias)
909 refs.AppendFormat (" <ProjectReference Include=\"{0}\">{1}", GetRelativePath (result.csProjFilename, match.CsprojFilename), NewLine);
910 refs.Append (" <Project>" + match.projectGuid + "</Project>" + NewLine);
911 refs.Append (" <Name>" + Path.GetFileNameWithoutExtension (match.CsprojFilename) + "</Name>" + NewLine);
913 refs.Append (" <Aliases>" + alias + "</Aliases>");
914 refs.Append (" </ProjectReference>" + NewLine);
915 if (!result.projReferences.Contains (match.Csproj))
916 result.projReferences.Add (match.Csproj);
919 static string GetRelativePath (string from, string to)
921 from = from.Replace ("\\", "/");
922 to = to.Replace ("\\", "/");
923 var fromUri = new Uri (Path.GetFullPath (from));
924 var toUri = new Uri (Path.GetFullPath (to));
926 var ret = fromUri.MakeRelativeUri (toUri).ToString ().Replace ("%5C", "\x5c");
930 MsbuildGenerator GetMatchingCsproj (string dllReferenceName, Dictionary<string,MsbuildGenerator> projects, bool explicitPath = false)
932 // libDir would be "./../../class/lib/net_4_5 for example
934 if (!dllReferenceName.EndsWith (".dll"))
935 dllReferenceName += ".dll";
938 var probe = Path.GetFullPath (Path.Combine (base_dir, dllReferenceName));
939 foreach (var project in projects){
940 if (probe == project.Value.AbsoluteLibraryOutput)
941 return project.Value;
945 // not explicit, search for the library in the lib path order specified
947 foreach (var libDir in libs) {
948 var abs = Path.GetFullPath (Path.Combine (base_dir, libDir));
949 foreach (var project in projects){
950 var probe = Path.Combine (abs, dllReferenceName);
952 if (probe == project.Value.AbsoluteLibraryOutput)
953 return project.Value;
956 Console.WriteLine ("Did not find referenced {0} with libs={1}", dllReferenceName, String.Join (", ", libs));
957 foreach (var p in projects) {
958 Console.WriteLine (" => {0}", p.Value.AbsoluteLibraryOutput);
965 public class Driver {
967 static IEnumerable<XElement> GetProjects ()
969 XDocument doc = XDocument.Load ("order.xml");
970 foreach (XElement project in doc.Root.Elements ()) {
971 string dir = project.Attribute ("dir").Value;
972 string library = project.Attribute ("library").Value;
973 var profile = project.Element ("profile").Value;
976 // Do only class libraries for now
978 if (!(dir.StartsWith ("class") || dir.StartsWith ("mcs") || dir.StartsWith ("basic")))
982 // Do not do 2.1, it is not working yet
983 // Do not do basic, as there is no point (requires a system mcs to be installed).
985 if (library.Contains ("moonlight") || library.Contains ("-basic") || library.EndsWith ("bootstrap") || library.Contains ("build"))
988 // The next ones are to make debugging easier for now
989 if (profile == "basic")
991 if (profile != "net_4_5" || library.Contains ("tests"))
994 yield return project;
998 static void Main (string [] args)
1000 if (!File.Exists ("genproj.cs")) {
1001 Console.WriteLine ("This command must be executed from mono/msvc/scripts");
1002 Environment.Exit (1);
1005 if (args.Length == 1 && args [0].ToLower ().Contains ("-h")) {
1006 Console.WriteLine ("Usage:");
1007 Console.WriteLine ("genproj.exe [visual_studio_release] [output_full_solutions]");
1008 Console.WriteLine ("If output_full_solutions is false, only the main System*.dll");
1009 Console.WriteLine (" assemblies (and dependencies) is included in the solution.");
1010 Console.WriteLine ("Example:");
1011 Console.WriteLine ("genproj.exe 2012 false");
1012 Console.WriteLine ("genproj.exe with no arguments is equivalent to 'genproj.exe 2012 true'");
1013 Environment.Exit (0);
1015 var slnVersion = (args.Length > 0) ? args [0] : "2012";
1016 bool fullSolutions = (args.Length > 1) ? bool.Parse (args [1]) : true;
1018 var sln_gen = new SlnGenerator (slnVersion);
1019 var two_sln_gen = new SlnGenerator (slnVersion);
1020 var four_sln_gen = new SlnGenerator (slnVersion);
1021 var three_five_sln_gen = new SlnGenerator (slnVersion);
1022 var four_five_sln_gen = new SlnGenerator (slnVersion);
1023 var projects = new Dictionary<string,MsbuildGenerator> ();
1025 var duplicates = new List<string> ();
1026 foreach (var project in GetProjects ()) {
1027 var library_output = project.Element ("library_output").Value;
1028 projects [library_output] = new MsbuildGenerator (project);
1030 foreach (var project in GetProjects ()){
1031 var library_output = project.Element ("library_output").Value;
1032 var gen = projects [library_output];
1034 var csproj = gen.Generate (projects);
1035 var csprojFilename = csproj.csProjFilename;
1036 if (!sln_gen.ContainsProjectIdentifier (csproj.library)) {
1037 sln_gen.Add (csproj);
1039 duplicates.Add (csprojFilename);
1042 } catch (Exception e) {
1043 Console.WriteLine ("Error in {0}\n{1}", project, e);
1047 Func<MsbuildGenerator.VsCsproj, bool> additionalFilter;
1048 additionalFilter = fullSolutions ? (Func<MsbuildGenerator.VsCsproj, bool>)null : IsCommonLibrary;
1050 FillSolution (two_sln_gen, MsbuildGenerator.profile_2_0, projects.Values, additionalFilter);
1051 FillSolution (four_five_sln_gen, MsbuildGenerator.profile_4_5, projects.Values, additionalFilter);
1052 FillSolution (four_sln_gen, MsbuildGenerator.profile_4_0, projects.Values, additionalFilter);
1053 FillSolution (three_five_sln_gen, MsbuildGenerator.profile_3_5, projects.Values, additionalFilter);
1055 var sb = new StringBuilder ();
1056 sb.AppendLine ("WARNING: Skipped some project references, apparent duplicates in order.xml:");
1057 foreach (var item in duplicates) {
1058 sb.AppendLine (item);
1060 Console.WriteLine (sb.ToString ());
1062 WriteSolution (two_sln_gen, MakeSolutionName (MsbuildGenerator.profile_2_0));
1063 WriteSolution (three_five_sln_gen, MakeSolutionName (MsbuildGenerator.profile_3_5));
1064 WriteSolution (four_sln_gen, MakeSolutionName (MsbuildGenerator.profile_4_0));
1065 WriteSolution (four_five_sln_gen, MakeSolutionName (MsbuildGenerator.profile_4_5));
1067 // A few other optional solutions
1068 // Solutions with 'everything' and the most common libraries used in development may be of interest
1069 //WriteSolution (sln_gen, "mcs_full.sln");
1070 //WriteSolution (small_full_sln_gen, "small_full.sln");
1071 // The following may be useful if lacking visual studio or MonoDevelop, to bootstrap mono compiler self-hosting
1072 //WriteSolution (basic_sln_gen, "mcs_basic.sln");
1073 //WriteSolution (build_sln_gen, "mcs_build.sln");
1076 static string MakeSolutionName (string profileTag)
1078 return "net" + profileTag + ".sln";
1081 static void FillSolution (SlnGenerator solution, string profileString, IEnumerable<MsbuildGenerator> projects, Func<MsbuildGenerator.VsCsproj, bool> additionalFilter = null)
1083 foreach (var generator in projects) {
1084 var vsCsproj = generator.Csproj;
1085 if (!vsCsproj.library.Contains (profileString))
1087 if (additionalFilter != null && !additionalFilter (vsCsproj))
1089 var csprojFilename = vsCsproj.csProjFilename;
1090 if (!solution.ContainsProjectIdentifier (vsCsproj.library)) {
1091 solution.Add (vsCsproj);
1092 RecursiveAddProj (solution, vsCsproj);
1097 static void RecursiveAddProj (SlnGenerator solution, MsbuildGenerator.VsCsproj vsCsproj, int recursiveDepth = 1)
1099 const int max_recursive = 16;
1100 if (recursiveDepth > max_recursive) throw new Exception (string.Format ("Reached {0} levels of project dependency", max_recursive));
1101 foreach (var projRef in vsCsproj.projReferences) {
1102 if (!solution.ContainsProjectIdentifier (projRef.library)) {
1103 solution.Add (projRef);
1104 RecursiveAddProj (solution, projRef, recursiveDepth + 1);
1109 static void WriteSolution (SlnGenerator sln_gen, string slnfilename)
1111 Console.WriteLine (String.Format ("Writing solution {1}, with {0} projects", sln_gen.Count, slnfilename));
1112 sln_gen.Write (slnfilename);
1115 static bool IsCommonLibrary (MsbuildGenerator.VsCsproj proj)
1117 var library = proj.library;
1118 //if (library.Contains ("-basic"))
1120 //if (library.Contains ("-build"))
1122 //if (library.StartsWith ("corlib"))
1124 if (library.StartsWith ("System-"))
1126 if (library.StartsWith ("System.Xml"))
1128 if (library.StartsWith ("System.Secu"))
1130 if (library.StartsWith ("System.Configuration"))
1132 if (library.StartsWith ("System.Core"))
1134 //if (library.StartsWith ("Mono."))