3 using System.Collections.Generic;
5 using System.Globalization;
10 Library, Exe, Module, WinExe
13 public enum LanguageVersion {
23 public static readonly string NewLine = "\r\n"; //Environment.NewLine; // "\n";
24 public SlnGenerator (string formatVersion = "2012")
26 switch (formatVersion) {
28 this.header = makeHeader ("10.00", "2008");
31 this.header = makeHeader ("12.00", "2012");
36 private string makeHeader (string formatVersion, string yearTag)
38 return string.Format ("Microsoft Visual Studio Solution File, Format Version {0}" + NewLine + "# Visual Studio {1}", formatVersion, yearTag);
40 const string project_start = "Project(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"{0}\", \"{1}\", \"{2}\""; // Note: No need to double up on {} around {2}
41 const string project_end = "EndProject";
43 List<MsbuildGenerator.VsCsproj> libraries = new List<MsbuildGenerator.VsCsproj> ();
44 private string header;
46 public void Add (MsbuildGenerator.VsCsproj vsproj)
49 libraries.Add (vsproj);
50 } catch (Exception ex) {
51 Console.WriteLine (ex);
55 public void Write (string filename)
57 using (var sln = new StreamWriter (filename)) {
59 sln.WriteLine (header);
60 foreach (var proj in libraries) {
61 sln.WriteLine (project_start, proj.library, proj.csprojFileName, proj.projectGuid);
62 sln.WriteLine (project_end);
64 sln.WriteLine ("Global");
66 sln.WriteLine ("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
67 sln.WriteLine ("\t\tDebug|Any CPU = Debug|Any CPU");
68 sln.WriteLine ("\t\tRelease|Any CPU = Release|Any CPU");
69 sln.WriteLine ("\tEndGlobalSection");
71 sln.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
72 foreach (var proj in libraries) {
73 var guid = proj.projectGuid;
74 sln.WriteLine ("\t\t{0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", guid);
75 sln.WriteLine ("\t\t{0}.Debug|Any CPU.Build.0 = Debug|Any CPU", guid);
76 sln.WriteLine ("\t\t{0}.Release|Any CPU.ActiveCfg = Release|Any CPU", guid);
77 sln.WriteLine ("\t\t{0}.Release|Any CPU.Build.0 = Release|Any CPU", guid);
79 sln.WriteLine ("\tEndGlobalSection");
81 sln.WriteLine ("\tGlobalSection(SolutionProperties) = preSolution");
82 sln.WriteLine ("\t\tHideSolutionNode = FALSE");
83 sln.WriteLine ("\tEndGlobalSection");
85 sln.WriteLine ("EndGlobal");
89 internal bool ContainsProjectIdentifier (string projId)
91 return libraries.FindIndex (x => (x.library == projId)) >= 0;
94 public int Count { get { return libraries.Count; } }
97 class MsbuildGenerator {
98 static readonly string NewLine = SlnGenerator.NewLine;
100 public const string profile_2_0 = "_2_0";
101 public const string profile_3_5 = "_3_5";
102 public const string profile_4_0 = "_4_0";
103 public const string profile_4_5 = "_4_5";
107 Console.WriteLine ("Invalid argument");
110 static string template;
111 static MsbuildGenerator ()
113 using (var input = new StreamReader ("csproj.tmpl")) {
114 template = input.ReadToEnd ();
118 // The directory as specified in order.xml
122 // Our base directory, this is relative to our exectution point mono/msvc/scripts
127 // Class directory, relative to
130 public MsbuildGenerator (string dir)
136 class_dir = "..\\class\\";
137 base_dir = "..\\..\\mcs\\mcs";
141 foreach (char c in dir) {
143 mcs_topdir = "..//" + mcs_topdir;
145 class_dir = mcs_topdir.Substring (3);
147 base_dir = Path.Combine ("..", "..", "mcs", dir);
153 StringBuilder defines = new StringBuilder ();
155 private bool copyLocal = true;
158 Target Target = Target.Exe;
159 string TargetExt = ".exe";
161 bool Optimize = true;
162 bool VerifyClsCompliance = true;
164 string win32IconFile;
165 bool want_debugging_support = false;
166 bool Checked = false;
167 bool WarningsAreErrors;
168 Dictionary<string, string> embedded_resources = new Dictionary<string, string> ();
169 List<string> references = new List<string> ();
170 List<string> libs = new List<string> ();
171 List<string> reference_aliases = new List<string> ();
172 List<string> warning_as_error = new List<string> ();
173 int WarningLevel = 4;
174 List<int> ignore_warning = new List<int> ();
175 bool load_default_config = true;
176 string StrongNameKeyFile;
177 string StrongNameKeyContainer;
178 bool StrongNameDelaySign = false;
179 LanguageVersion Version = LanguageVersion.Default;
182 readonly char [] argument_value_separator = new char [] { ';', ',' };
185 // This parses the -arg and /arg options to the compiler, even if the strings
186 // in the following text use "/arg" on the strings.
188 bool CSCParseOption (string option, ref string [] args)
190 int idx = option.IndexOf (':');
197 arg = option.Substring (0, idx);
199 value = option.Substring (idx + 1);
202 switch (arg.ToLower (CultureInfo.InvariantCulture)) {
214 Target = Target.WinExe;
218 Target = Target.Library;
223 Target = Target.Module;
224 TargetExt = ".netmodule";
233 if (value.Length == 0) {
235 Environment.Exit (1);
253 case "/incremental+":
254 case "/incremental-":
260 if (value.Length == 0) {
262 Environment.Exit (1);
265 foreach (string d in value.Split (argument_value_separator)) {
266 if (defines.Length != 0)
267 defines.Append (";");
276 // We should collect data, runtime, etc and store in the file specified
280 case "/linkresource":
283 bool embeded = arg [1] == 'r' || arg [1] == 'R';
284 string [] s = value.Split (argument_value_separator);
287 if (s [0].Length == 0)
289 embedded_resources [s [0]] = Path.GetFileName (s [0]);
292 embedded_resources [s [0]] = s [1];
295 Console.WriteLine ("Does not support this method yet: {0}", arg);
296 Environment.Exit (1);
299 Console.WriteLine ("Wrong number of arguments for option `{0}'", option);
300 Environment.Exit (1);
308 Console.WriteLine ("/recurse not supported");
309 Environment.Exit (1);
314 if (value.Length == 0) {
315 Console.WriteLine ("-reference requires an argument");
316 Environment.Exit (1);
319 string [] refs = value.Split (argument_value_separator);
320 foreach (string r in refs) {
322 int index = val.IndexOf ('=');
324 reference_aliases.Add (r);
329 references.Add (val);
338 Console.WriteLine ("{0} = not supported", arg);
339 return true; // throwing an exception was a showstopper, so far as I can see.
346 win32IconFile = value;
350 want_debugging_support = false;
355 want_debugging_support = true;
372 VerifyClsCompliance = false;
385 case "/warnaserror+":
386 if (value.Length == 0) {
387 WarningsAreErrors = true;
389 foreach (string wid in value.Split (argument_value_separator))
390 warning_as_error.Add (wid);
395 Console.WriteLine ("Warning ignoring /runtime:v4");
398 case "/warnaserror-":
399 if (value.Length == 0) {
400 WarningsAreErrors = false;
402 foreach (string wid in value.Split (argument_value_separator))
403 warning_as_error.Remove (wid);
408 WarningLevel = Int32.Parse (value);
414 if (value.Length == 0) {
415 Console.WriteLine ("/nowarn requires an argument");
416 Environment.Exit (1);
419 warns = value.Split (argument_value_separator);
420 foreach (string wc in warns) {
422 if (wc.Trim ().Length == 0)
425 int warn = Int32.Parse (wc);
427 throw new ArgumentOutOfRangeException ("warn");
429 ignore_warning.Add (warn);
431 Console.WriteLine (String.Format ("`{0}' is not a valid warning number", wc));
432 Environment.Exit (1);
439 load_default_config = false;
455 if (value == String.Empty) {
456 Console.WriteLine ("{0} requires an argument", arg);
457 Environment.Exit (1);
459 StrongNameKeyFile = value;
461 case "/keycontainer":
462 if (value == String.Empty) {
463 Console.WriteLine ("{0} requires an argument", arg);
464 Environment.Exit (1);
466 StrongNameKeyContainer = value;
470 StrongNameDelaySign = true;
473 StrongNameDelaySign = false;
477 switch (value.ToLower (CultureInfo.InvariantCulture)) {
479 Version = LanguageVersion.ISO_1;
483 Version = LanguageVersion.Default;
486 Version = LanguageVersion.ISO_2;
489 Version = LanguageVersion.Future;
492 Console.WriteLine ("Invalid option `{0}' for /langversion. It must be either `ISO-1', `ISO-2' or `Default'", value);
493 Environment.Exit (1);
501 Console.WriteLine ("Failing with : {0}", arg);
505 static string [] LoadArgs (string file)
508 var args = new List<string> ();
511 f = new StreamReader (file);
516 StringBuilder sb = new StringBuilder ();
518 while ((line = f.ReadLine ()) != null) {
521 for (int i = 0; i < t; i++) {
524 if (c == '"' || c == '\'') {
527 for (i++; i < t; i++) {
534 } else if (c == ' ') {
536 args.Add (sb.ToString ());
543 args.Add (sb.ToString ());
548 string [] ret_value = new string [args.Count];
549 args.CopyTo (ret_value, 0);
554 static string Load (string f)
556 var native = NativeName (f);
558 if (File.Exists (native)) {
559 using (var sr = new StreamReader (native)) {
560 return sr.ReadToEnd ();
566 public static string NativeName (string path)
568 if (System.IO.Path.DirectorySeparatorChar == '/')
569 return path.Replace ("\\", "/");
571 return path.Replace ("/", "\\");
574 public class VsCsproj {
575 public string projectGuid;
576 public string output;
577 public string csprojFileName;
578 public string library_output;
579 public double fx_version;
580 public List<VsCsproj> projReferences = new List<VsCsproj> ();
581 public string library;
584 public VsCsproj Generate (XElement xproject, List<MsbuildGenerator.VsCsproj> projects)
587 var result = new VsCsproj ();
588 string library = xproject.Attribute ("library").Value;
589 string boot, flags, output_name, built_sources, library_output, response, fx_version, profile;
591 boot = xproject.Element ("boot").Value;
592 flags = xproject.Element ("flags").Value;
593 output_name = xproject.Element ("output").Value;
594 built_sources = xproject.Element ("built_sources").Value;
595 library_output = xproject.Element ("library_output").Value;
596 response = xproject.Element ("response").Value;
597 fx_version = xproject.Element ("fx_version").Value;
598 //if (library.EndsWith("-build")) fx_version = "2.0"; // otherwise problem if .NET4.5 is installed, seems. (https://github.com/nikhilk/scriptsharp/issues/156)
599 profile = xproject.Element ("profile").Value;
600 if (string.IsNullOrEmpty (response)) {
601 // Address the issue where entries are missing the fx_version
602 // Should be fixed in the Makefile or elsewhere; this is a workaround
603 //<fx_version>basic</fx_version>
604 //<profile>./../build/deps/mcs.exe.sources.response</profile>
605 //<response></response>
607 profile = fx_version;
608 if (response.Contains ("build") || response.Contains ("basic") || response.Contains (profile_2_0)) {
610 if (response.Contains (profile_2_0)) profile = "net_2_0";
611 } if (response.Contains ("build") || response.Contains ("basic") || response.Contains (profile_2_0)) {
613 } else if (response.Contains (profile_3_5)) {
616 } else if (response.Contains (profile_4_0)) {
619 } else if (response.Contains (profile_4_5)) {
625 // Prebuild code, might be in inputs, check:
626 // inputs/LIBRARY-PROFILE.pre
627 // inputs/LIBRARY.pre
629 string prebuild = Load (library + ".pre");
631 int q = library.IndexOf ("-");
633 prebuild = prebuild + Load (library.Substring (0, q) + ".pre");
635 var all_args = new Queue<string []> ();
636 all_args.Enqueue (flags.Split ());
637 while (all_args.Count > 0) {
638 string [] f = all_args.Dequeue ();
640 for (int i = 0; i < f.Length; i++) {
641 if (f [i] [0] == '-')
642 f [i] = "/" + f [i].Substring (1);
644 if (f [i] [0] == '@') {
645 string [] extra_args;
646 string response_file = f [i].Substring (1);
648 var resp_file_full = Path.Combine (base_dir, response_file);
649 extra_args = LoadArgs (resp_file_full);
650 if (extra_args == null) {
651 Console.WriteLine ("Unable to open response file: " + resp_file_full);
652 Environment.Exit (1);
655 all_args.Enqueue (extra_args);
659 if (CSCParseOption (f [i], ref f))
661 Console.WriteLine ("Failure with {0}", f [i]);
662 Environment.Exit (1);
666 string [] source_files;
667 //Console.WriteLine ("Base: {0} res: {1}", base_dir, response);
668 using (var reader = new StreamReader (NativeName (base_dir + "\\" + response))) {
669 source_files = reader.ReadToEnd ().Split ();
672 Array.Sort (source_files);
674 StringBuilder sources = new StringBuilder ();
675 foreach (string s in source_files) {
679 string src = s.Replace ("/", "\\");
680 if (src.StartsWith (@"Test\..\"))
681 src = src.Substring (8, src.Length - 8);
683 sources.AppendFormat (" <Compile Include=\"{0}\" />" + NewLine, src);
686 source_files = built_sources.Split ();
687 Array.Sort (source_files);
689 foreach (string s in source_files) {
693 string src = s.Replace ("/", "\\");
694 if (src.StartsWith (@"Test\..\"))
695 src = src.Substring (8, src.Length - 8);
697 sources.AppendFormat (" <Compile Include=\"{0}\" />" + NewLine, src);
699 sources.Remove (sources.Length - 1, 1);
701 //if (library == "corlib-build") // otherwise, does not compile on fx_version == 4.0
703 // references.Add("System.dll");
704 // references.Add("System.Xml.dll");
707 //if (library == "System.Core-build") // otherwise, slow compile. May be a transient need.
709 // this.ignore_warning.Add(1685);
710 // this.ignore_warning.Add(0436);
713 result.library = library;
714 result.csprojFileName = "..\\..\\mcs\\" + dir + "\\" + library + ".csproj";
716 var refs = new StringBuilder ();
718 bool is_test = response.Contains ("_test_");
720 // F:\src\mono\mcs\class\lib\net_2_0\nunit.framework.dll
721 // F:\src\mono\mcs\class\SomeProject\SomeProject_test_-net_2_0.csproj
722 var nunitLibPath = string.Format (@"..\lib\{0}\nunit.framework.dll", profile);
723 refs.Append (string.Format (" <Reference Include=\"{0}\" />" + NewLine, nunitLibPath));
726 var resources = new StringBuilder ();
727 if (embedded_resources.Count > 0) {
728 resources.AppendFormat (" <ItemGroup>" + NewLine);
729 foreach (var dk in embedded_resources) {
730 resources.AppendFormat (" <EmbeddedResource Include=\"{0}\">" + NewLine, dk.Key);
731 resources.AppendFormat (" <LogicalName>{0}</LogicalName>" + NewLine, dk.Value);
732 resources.AppendFormat (" </EmbeddedResource>" + NewLine);
734 resources.AppendFormat (" </ItemGroup>" + NewLine);
736 if (references.Count > 0 || reference_aliases.Count > 0) {
737 // -r:mscorlib.dll -r:System.dll
738 //<ProjectReference Include="..\corlib\corlib-basic.csproj">
739 // <Project>{155aef28-c81f-405d-9072-9d52780e3e70}</Project>
740 // <Name>corlib-basic</Name>
741 //</ProjectReference>
742 //<ProjectReference Include="..\System\System-basic.csproj">
743 // <Project>{2094e859-db2f-481f-9630-f89d31d9ed48}</Project>
744 // <Name>System-basic</Name>
745 //</ProjectReference>
746 var refdistinct = references.Distinct ();
747 foreach (string r in refdistinct) {
748 VsCsproj lastMatching = getMatchingCsproj (Path.GetFileName (r), projects);
749 if (lastMatching != null) {
750 addProjectReference (refs, result, lastMatching, r);
752 var msg = string.Format ("", library, r);
753 Console.WriteLine ("{0}: Could not find a matching project reference for {1}", library, Path.GetFileName (r));
754 Console.WriteLine (" --> Adding reference with hintpath instead");
755 refs.Append (" <Reference Include=\"" + r + "\">" + NewLine);
756 refs.Append (" <SpecificVersion>False</SpecificVersion>" + NewLine);
757 refs.Append (" <HintPath>" + r + "</HintPath>" + NewLine);
758 refs.Append (" <Private>False</Private>" + NewLine);
759 refs.Append (" </Reference>" + NewLine);
763 foreach (string r in reference_aliases) {
764 int index = r.IndexOf ('=');
765 string alias = r.Substring (0, index);
766 string assembly = r.Substring (index + 1);
767 VsCsproj lastMatching = getMatchingCsproj (Path.GetFileName (assembly), projects);
768 if (lastMatching != null) {
769 addProjectReference (refs, result, lastMatching, r);
771 throw new NotSupportedException (string.Format ("From {0}, could not find a matching project reference for {1}", library, r));
772 refs.Append (" <Reference Include=\"" + assembly + "\">" + NewLine);
773 refs.Append (" <SpecificVersion>False</SpecificVersion>" + NewLine);
774 refs.Append (" <HintPath>" + r + "</HintPath>" + NewLine);
775 refs.Append (" <Aliases>" + alias + "</Aliases>" + NewLine);
776 refs.Append (" </Reference>" + NewLine);
782 string library_output_dir = string.Empty;
784 // ../class/lib/build/tmp/System.Xml.dll
785 // /class/lib/basic/System.Core.dll
786 // <library_output>mcs.exe</library_output>
787 bool has_tmp = library_output.Contains ("/tmp/");
788 string p = library_output.Replace ("/tmp/", "/").Replace ("/", @"\");
789 string profile_dir = Path.GetDirectoryName (p);
790 string d = has_tmp ? Path.Combine (profile_dir, library) : profile_dir;
791 library_output_dir = d;
792 if (string.IsNullOrEmpty (library_output_dir))
793 library_output_dir = @".\";
794 library_output = Path.Combine (library_output_dir, output_name).Replace (@"\", "/");
796 Console.WriteLine ("Error in path: {0} while processing {1}", library_output_dir, library);
799 // The build output directory shoudl be unique for each project, to overcome cyclic deps
800 var build_output_dir = string.Format (@"bin\Debug\{0}", library);
803 string postbuild = string.Empty;
804 postbuild = string.Format (
805 //"if not \"$(OutDir)\" == \"..\\lib\\{0}\" xcopy $(OutDir)$(TargetName).* ..\\lib\\{0}\\ /Y /R /D",
806 " xcopy $(TargetName).* $(ProjectDir)..\\lib\\{0}\\ /Y /R /D",
809 bool basic_or_build = (library.Contains ("-basic") || library.Contains ("-build"));
812 // Replace the template values
814 result.projectGuid = "{" + Guid.NewGuid ().ToString ().ToUpper () + "}";
815 result.library_output = library_output;
816 result.fx_version = double.Parse (fx_version);
817 result.output = template.
818 Replace ("@PROJECTGUID@", result.projectGuid).
819 Replace ("@DEFINES@", defines.ToString ()).
820 Replace ("@DISABLEDWARNINGS@", string.Join (",", (from i in ignore_warning select i.ToString ()).ToArray ())).
821 //Replace("@NOSTDLIB@", (basic_or_build || (!StdLib)) ? "<NoStdLib>true</NoStdLib>" : string.Empty).
822 Replace ("@NOSTDLIB@", "<NoStdLib>" + (!StdLib).ToString () + "</NoStdLib>").
823 Replace ("@NOCONFIG@", "<NoConfig>" + (!load_default_config).ToString () + "</NoConfig>").
824 Replace ("@ALLOWUNSAFE@", Unsafe ? "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>" : "").
825 Replace ("@FX_VERSION", fx_version).
826 Replace ("@ASSEMBLYNAME@", Path.GetFileNameWithoutExtension (output_name)).
827 Replace ("@OUTPUTDIR@", build_output_dir).
828 Replace ("@DEFINECONSTANTS@", defines.ToString ()).
829 Replace ("@DEBUG@", want_debugging_support ? "true" : "false").
830 Replace ("@DEBUGTYPE@", want_debugging_support ? "full" : "pdbonly").
831 Replace ("@REFERENCES@", refs.ToString ()).
832 Replace ("@PREBUILD@", prebuild).
833 Replace ("@POSTBUILD@", postbuild).
834 //Replace ("@ADDITIONALLIBPATHS@", String.Format ("<AdditionalLibPaths>{0}</AdditionalLibPaths>", string.Join (",", libs.ToArray ()))).
835 Replace ("@ADDITIONALLIBPATHS@", String.Empty).
836 Replace ("@RESOURCES@", resources.ToString ()).
837 Replace ("@OPTIMIZE@", Optimize ? "true" : "false").
838 Replace ("@SOURCES@", sources.ToString ());
840 //Console.WriteLine ("Generated {0}", ofile.Replace ("\\", "/"));
841 using (var o = new StreamWriter (NativeName (result.csprojFileName))) {
842 o.WriteLine (result.output);
848 private void addProjectReference (StringBuilder refs, VsCsproj result, VsCsproj lastMatching, string r)
850 refs.AppendFormat (" <ProjectReference Include=\"{0}\">{1}", getRelativePath (result.csprojFileName, lastMatching.csprojFileName), NewLine);
851 refs.Append (" <Project>" + lastMatching.projectGuid + "</Project>" + NewLine);
852 refs.Append (" <Name>" + Path.GetFileNameWithoutExtension (lastMatching.csprojFileName) + "</Name>" + NewLine);
853 //refs.Append(" <HintPath>" + r + "</HintPath>" + NewLine);
854 refs.Append (" </ProjectReference>" + NewLine);
855 if (!result.projReferences.Contains (lastMatching))
856 result.projReferences.Add (lastMatching);
859 static string getRelativePath (string referencerPath, string referenceePath)
861 // F:\src\mono\msvc\scripts\
862 //..\..\mcs\class\System\System-net_2_0.csproj
863 //..\..\mcs\class\corlib\corlib-net_2_0.csproj
864 // So from \System\, corlib needs to be referenced as:
865 // ..\corlib\corlib-net_2_0.csproj
867 // Could be possible to use PathRelativePathTo, but this is a P/Invoke to Win32 API.
868 // For now, simpler but less robust:
869 return referenceePath.Replace (@"..\..\mcs\class", "..").Replace ("/", "\\");
872 static VsCsproj getMatchingCsproj (string dllReferenceName, List<VsCsproj> projects)
874 return projects.LastOrDefault (x => Path.GetFileName (x.library_output).Replace (".dll", "") == dllReferenceName.Replace (".dll", ""));
879 public class Driver {
881 static void Main (string [] args)
883 if (!File.Exists ("genproj.cs")) {
884 Console.WriteLine ("This command must be executed from mono/msvc/scripts");
885 Environment.Exit (1);
888 if (args.Length == 1 && args [0].ToLower ().Contains ("-h")) {
889 Console.WriteLine ("Usage:");
890 Console.WriteLine ("genproj.exe [visual_studio_release] [output_full_solutions]");
891 Console.WriteLine ("If output_full_solutions is false, only the main System*.dll");
892 Console.WriteLine (" assemblies (and dependencies) is included in the solution.");
893 Console.WriteLine ("Example:");
894 Console.WriteLine ("genproj.exe 2012 false");
895 Console.WriteLine ("genproj.exe with no arguments is equivalent to 'genproj.exe 2012 true'");
896 Environment.Exit (0);
898 var slnVersion = (args.Length > 0) ? args [0] : "2012";
899 bool fullSolutions = (args.Length > 1) ? bool.Parse (args [1]) : true;
901 var sln_gen = new SlnGenerator (slnVersion);
902 var two_sln_gen = new SlnGenerator (slnVersion);
903 var four_sln_gen = new SlnGenerator (slnVersion);
904 var three_five_sln_gen = new SlnGenerator (slnVersion);
905 var four_five_sln_gen = new SlnGenerator (slnVersion);
906 var projects = new List<MsbuildGenerator.VsCsproj> ();
908 XDocument doc = XDocument.Load ("order.xml");
909 var duplicates = new List<string> ();
910 foreach (XElement project in doc.Root.Elements ()) {
911 string dir = project.Attribute ("dir").Value;
912 string library = project.Attribute ("library").Value;
915 // Do only class libraries for now
917 if (!(dir.StartsWith ("class") || dir.StartsWith ("mcs") || dir.StartsWith ("basic")))
921 // Do not do 2.1, it is not working yet
922 // Do not do basic, as there is no point (requires a system mcs to be installed).
924 //if (library.Contains ("moonlight") || library.Contains ("-basic") || library.EndsWith ("bootstrap"))
925 if (library.Contains ("moonlight") || library.EndsWith ("bootstrap"))
928 var gen = new MsbuildGenerator (dir);
930 var csproj = gen.Generate (project, projects);
931 var csprojFilename = csproj.csprojFileName;
932 if (!sln_gen.ContainsProjectIdentifier (csproj.library)) {
933 projects.Add (csproj);
934 sln_gen.Add (csproj);
936 duplicates.Add (csprojFilename);
939 } catch (Exception e) {
940 Console.WriteLine ("Error in {0}\n{1}", dir, e);
944 Func<MsbuildGenerator.VsCsproj, bool> additionalFilter;
945 additionalFilter = fullSolutions ? (Func<MsbuildGenerator.VsCsproj, bool>)null : isCommonLibrary;
947 fillSolution (two_sln_gen, MsbuildGenerator.profile_2_0, projects, additionalFilter);
948 fillSolution (four_five_sln_gen, MsbuildGenerator.profile_4_5, projects, additionalFilter);
949 fillSolution (four_sln_gen, MsbuildGenerator.profile_4_0, projects, additionalFilter);
950 fillSolution (three_five_sln_gen, MsbuildGenerator.profile_3_5, projects, additionalFilter);
952 var sb = new StringBuilder ();
953 sb.AppendLine ("WARNING: Skipped some project references, apparent duplicates in order.xml:");
954 foreach (var item in duplicates) {
955 sb.AppendLine (item);
957 Console.WriteLine (sb.ToString ());
959 writeSolution (two_sln_gen, mkSlnName (MsbuildGenerator.profile_2_0));
960 writeSolution (three_five_sln_gen, mkSlnName (MsbuildGenerator.profile_3_5));
961 writeSolution (four_sln_gen, mkSlnName (MsbuildGenerator.profile_4_0));
962 writeSolution (four_five_sln_gen, mkSlnName (MsbuildGenerator.profile_4_5));
963 // A few other optional solutions
964 // Solutions with 'everything' and the most common libraries used in development may be of interest
965 //writeSolution (sln_gen, "mcs_full.sln");
966 //writeSolution (small_full_sln_gen, "small_full.sln");
967 // The following may be useful if lacking visual studio or MonoDevelop, to bootstrap mono compiler self-hosting
968 //writeSolution (basic_sln_gen, "mcs_basic.sln");
969 //writeSolution (build_sln_gen, "mcs_build.sln");
972 private static string mkSlnName (string profileTag)
974 return "net" + profileTag + ".sln";
977 private static void fillSolution (SlnGenerator solution, string profileString, List<MsbuildGenerator.VsCsproj> projects, Func<MsbuildGenerator.VsCsproj, bool> additionalFilter = null)
979 foreach (var vsCsproj in projects) {
980 if (!vsCsproj.library.Contains (profileString))
982 if (additionalFilter != null && !additionalFilter (vsCsproj))
984 var csprojFilename = vsCsproj.csprojFileName;
985 if (!solution.ContainsProjectIdentifier (vsCsproj.library)) {
986 solution.Add (vsCsproj);
987 recursiveAddProj (solution, vsCsproj);
992 private static void recursiveAddProj (SlnGenerator solution, MsbuildGenerator.VsCsproj vsCsproj, int recursiveDepth = 1)
994 const int max_recursive = 16;
995 if (recursiveDepth > max_recursive) throw new Exception (string.Format ("Reached {0} levels of project dependency", max_recursive));
996 foreach (var projRef in vsCsproj.projReferences) {
997 if (!solution.ContainsProjectIdentifier (projRef.library)) {
998 solution.Add (projRef);
999 recursiveAddProj (solution, projRef, recursiveDepth + 1);
1004 private static void writeSolution (SlnGenerator sln_gen, string slnfilename)
1006 Console.WriteLine (String.Format ("Writing solution {1}, with {0} projects", sln_gen.Count, slnfilename));
1007 sln_gen.Write (slnfilename);
1010 private static bool isCommonLibrary (MsbuildGenerator.VsCsproj proj)
1012 var library = proj.library;
1013 //if (library.Contains ("-basic"))
1015 //if (library.Contains ("-build"))
1017 //if (library.StartsWith ("corlib"))
1019 if (library.StartsWith ("System-"))
1021 if (library.StartsWith ("System.Xml"))
1023 if (library.StartsWith ("System.Secu"))
1025 if (library.StartsWith ("System.Configuration"))
1027 if (library.StartsWith ("System.Core"))
1029 //if (library.StartsWith ("Mono."))