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 const string project_start = "Project(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"{0}\", \"{1}\", \"{2}\""; // Note: No need to double up on {} around {2}
37 const string project_end = "EndProject";
39 List<MsbuildGenerator.VsCsproj> libraries = new List<MsbuildGenerator.VsCsproj> ();
42 string MakeHeader (string formatVersion, string yearTag)
44 return string.Format ("Microsoft Visual Studio Solution File, Format Version {0}" + NewLine + "# Visual Studio {1}", formatVersion, yearTag);
47 public void Add (MsbuildGenerator.VsCsproj vsproj)
50 libraries.Add (vsproj);
51 } catch (Exception ex) {
52 Console.WriteLine (ex);
56 public void Write (string filename)
58 using (var sln = new StreamWriter (filename)) {
60 sln.WriteLine (header);
61 foreach (var proj in libraries) {
62 sln.WriteLine (project_start, proj.library, proj.csprojFileName, proj.projectGuid);
63 sln.WriteLine (project_end);
65 sln.WriteLine ("Global");
67 sln.WriteLine ("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
68 sln.WriteLine ("\t\tDebug|Any CPU = Debug|Any CPU");
69 sln.WriteLine ("\t\tRelease|Any CPU = Release|Any CPU");
70 sln.WriteLine ("\tEndGlobalSection");
72 sln.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
73 foreach (var proj in libraries) {
74 var guid = proj.projectGuid;
75 sln.WriteLine ("\t\t{0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", guid);
76 sln.WriteLine ("\t\t{0}.Debug|Any CPU.Build.0 = Debug|Any CPU", guid);
77 sln.WriteLine ("\t\t{0}.Release|Any CPU.ActiveCfg = Release|Any CPU", guid);
78 sln.WriteLine ("\t\t{0}.Release|Any CPU.Build.0 = Release|Any CPU", guid);
80 sln.WriteLine ("\tEndGlobalSection");
82 sln.WriteLine ("\tGlobalSection(SolutionProperties) = preSolution");
83 sln.WriteLine ("\t\tHideSolutionNode = FALSE");
84 sln.WriteLine ("\tEndGlobalSection");
86 sln.WriteLine ("EndGlobal");
90 internal bool ContainsProjectIdentifier (string projId)
92 return libraries.FindIndex (x => (x.library == projId)) >= 0;
95 public int Count { get { return libraries.Count; } }
98 class MsbuildGenerator {
99 static readonly string NewLine = SlnGenerator.NewLine;
101 public const string profile_2_0 = "_2_0";
102 public const string profile_3_5 = "_3_5";
103 public const string profile_4_0 = "_4_0";
104 public const string profile_4_5 = "_4_5";
108 Console.WriteLine ("Invalid argument");
111 static string template;
112 static MsbuildGenerator ()
114 using (var input = new StreamReader ("csproj.tmpl")) {
115 template = input.ReadToEnd ();
119 // The directory as specified in order.xml
123 // Our base directory, this is relative to our exectution point mono/msvc/scripts
127 public MsbuildGenerator (string dir)
133 class_dir = "..\\class\\";
134 base_dir = "..\\..\\mcs\\mcs";
138 foreach (char c in dir) {
140 mcs_topdir = "..//" + mcs_topdir;
142 class_dir = mcs_topdir.Substring (3);
144 base_dir = Path.Combine ("..", "..", "mcs", dir);
150 StringBuilder defines = new StringBuilder ();
151 bool Optimize = true;
152 bool want_debugging_support = false;
153 Dictionary<string, string> embedded_resources = new Dictionary<string, string> ();
154 List<string> warning_as_error = new List<string> ();
155 List<int> ignore_warning = new List<int> ();
156 bool load_default_config = true;
158 List<string> references = new List<string> ();
159 List<string> libs = new List<string> ();
160 List<string> reference_aliases = new List<string> ();
161 bool showWarnings = false;
164 #pragma warning disable 0219, 0414
165 int WarningLevel = 4;
167 bool Checked = false;
168 bool WarningsAreErrors;
169 bool VerifyClsCompliance = true;
170 string win32IconFile;
171 string StrongNameKeyFile;
172 bool copyLocal = true;
173 Target Target = Target.Exe;
174 string TargetExt = ".exe";
176 string StrongNameKeyContainer;
177 bool StrongNameDelaySign = false;
178 LanguageVersion Version = LanguageVersion.Default;
181 // Class directory, relative to
183 #pragma warning restore 0219,414
185 readonly char [] argument_value_separator = new char [] { ';', ',' };
188 // This parses the -arg and /arg options to the compiler, even if the strings
189 // in the following text use "/arg" on the strings.
191 bool CSCParseOption (string option, ref string [] args)
193 int idx = option.IndexOf (':');
200 arg = option.Substring (0, idx);
202 value = option.Substring (idx + 1);
205 switch (arg.ToLower (CultureInfo.InvariantCulture)) {
217 Target = Target.WinExe;
221 Target = Target.Library;
226 Target = Target.Module;
227 TargetExt = ".netmodule";
236 if (value.Length == 0) {
238 Environment.Exit (1);
256 case "/incremental+":
257 case "/incremental-":
263 if (value.Length == 0) {
265 Environment.Exit (1);
268 foreach (string d in value.Split (argument_value_separator)) {
269 if (defines.Length != 0)
270 defines.Append (";");
279 // We should collect data, runtime, etc and store in the file specified
283 case "/linkresource":
286 bool embeded = arg [1] == 'r' || arg [1] == 'R';
287 string [] s = value.Split (argument_value_separator);
290 if (s [0].Length == 0)
292 embedded_resources [s [0]] = Path.GetFileName (s [0]);
295 embedded_resources [s [0]] = s [1];
298 Console.WriteLine ("Does not support this method yet: {0}", arg);
299 Environment.Exit (1);
302 Console.WriteLine ("Wrong number of arguments for option `{0}'", option);
303 Environment.Exit (1);
310 Console.WriteLine ("/recurse not supported");
311 Environment.Exit (1);
316 if (value.Length == 0) {
317 Console.WriteLine ("-reference requires an argument");
318 Environment.Exit (1);
321 string [] refs = value.Split (argument_value_separator);
322 foreach (string r in refs) {
324 int index = val.IndexOf ('=');
326 reference_aliases.Add (r);
331 references.Add (val);
341 Console.WriteLine ("{0} = not supported", arg);
349 win32IconFile = value;
353 want_debugging_support = false;
358 want_debugging_support = true;
375 VerifyClsCompliance = false;
388 case "/warnaserror+":
389 if (value.Length == 0) {
390 WarningsAreErrors = true;
392 foreach (string wid in value.Split (argument_value_separator))
393 warning_as_error.Add (wid);
398 // Console.WriteLine ("Warning ignoring /runtime:v4");
401 case "/warnaserror-":
402 if (value.Length == 0) {
403 WarningsAreErrors = false;
405 foreach (string wid in value.Split (argument_value_separator))
406 warning_as_error.Remove (wid);
411 WarningLevel = Int32.Parse (value);
417 if (value.Length == 0) {
418 Console.WriteLine ("/nowarn requires an argument");
419 Environment.Exit (1);
422 warns = value.Split (argument_value_separator);
423 foreach (string wc in warns) {
425 if (wc.Trim ().Length == 0)
428 int warn = Int32.Parse (wc);
430 throw new ArgumentOutOfRangeException ("warn");
432 ignore_warning.Add (warn);
434 Console.WriteLine (String.Format ("`{0}' is not a valid warning number", wc));
435 Environment.Exit (1);
442 load_default_config = false;
458 if (value == String.Empty) {
459 Console.WriteLine ("{0} requires an argument", arg);
460 Environment.Exit (1);
462 StrongNameKeyFile = value;
464 case "/keycontainer":
465 if (value == String.Empty) {
466 Console.WriteLine ("{0} requires an argument", arg);
467 Environment.Exit (1);
469 StrongNameKeyContainer = value;
473 StrongNameDelaySign = true;
476 StrongNameDelaySign = false;
480 switch (value.ToLower (CultureInfo.InvariantCulture)) {
482 Version = LanguageVersion.ISO_1;
486 Version = LanguageVersion.Default;
489 Version = LanguageVersion.ISO_2;
492 Version = LanguageVersion.Future;
495 Console.WriteLine ("Invalid option `{0}' for /langversion. It must be either `ISO-1', `ISO-2' or `Default'", value);
496 Environment.Exit (1);
504 Console.WriteLine ("Failing with : {0}", arg);
508 static string [] LoadArgs (string file)
511 var args = new List<string> ();
514 f = new StreamReader (file);
519 StringBuilder sb = new StringBuilder ();
521 while ((line = f.ReadLine ()) != null) {
524 for (int i = 0; i < t; i++) {
527 if (c == '"' || c == '\'') {
530 for (i++; i < t; i++) {
537 } else if (c == ' ') {
539 args.Add (sb.ToString ());
546 args.Add (sb.ToString ());
551 string [] ret_value = new string [args.Count];
552 args.CopyTo (ret_value, 0);
557 static string Load (string f)
559 var native = NativeName (f);
561 if (File.Exists (native)) {
562 using (var sr = new StreamReader (native)) {
563 return sr.ReadToEnd ();
569 public static string NativeName (string path)
571 if (System.IO.Path.DirectorySeparatorChar == '/')
572 return path.Replace ("\\", "/");
574 return path.Replace ("/", "\\");
577 public class VsCsproj {
578 public string projectGuid;
579 public string output;
580 public string csprojFileName;
581 public string library_output;
582 public double fx_version;
583 public List<VsCsproj> projReferences = new List<VsCsproj> ();
584 public string library;
587 public VsCsproj Generate (XElement xproject, List<MsbuildGenerator.VsCsproj> projects, bool showWarnings = false)
590 var result = new VsCsproj ();
591 string library = xproject.Attribute ("library").Value;
592 string boot, flags, output_name, built_sources, library_output, response, fx_version, profile;
594 boot = xproject.Element ("boot").Value;
595 flags = xproject.Element ("flags").Value;
596 output_name = xproject.Element ("output").Value;
597 built_sources = xproject.Element ("built_sources").Value;
598 library_output = xproject.Element ("library_output").Value;
599 response = xproject.Element ("response").Value;
600 fx_version = xproject.Element ("fx_version").Value;
601 //if (library.EndsWith("-build")) fx_version = "2.0"; // otherwise problem if .NET4.5 is installed, seems. (https://github.com/nikhilk/scriptsharp/issues/156)
602 profile = xproject.Element ("profile").Value;
603 if (string.IsNullOrEmpty (response)) {
604 // Address the issue where entries are missing the fx_version
605 // Should be fixed in the Makefile or elsewhere; this is a workaround
606 //<fx_version>basic</fx_version>
607 //<profile>./../build/deps/mcs.exe.sources.response</profile>
608 //<response></response>
610 profile = fx_version;
611 if (response.Contains ("build") || response.Contains ("basic") || response.Contains (profile_2_0)) {
613 if (response.Contains (profile_2_0)) profile = "net_2_0";
614 } if (response.Contains ("build") || response.Contains ("basic") || response.Contains (profile_2_0)) {
616 } else if (response.Contains (profile_3_5)) {
619 } else if (response.Contains (profile_4_0)) {
622 } else if (response.Contains (profile_4_5)) {
628 // Prebuild code, might be in inputs, check:
629 // inputs/LIBRARY-PROFILE.pre
630 // inputs/LIBRARY.pre
632 string prebuild = Load (library + ".pre");
633 string prebuild_windows, prebuild_unix;
635 int q = library.IndexOf ("-");
637 prebuild = prebuild + Load (library.Substring (0, q) + ".pre");
639 if (prebuild.IndexOf ("@MONO@") != -1){
640 prebuild_unix = prebuild.Replace ("@MONO@", "mono").Replace ("@CAT@", "cat");
641 prebuild_windows = prebuild.Replace ("@MONO@", "").Replace ("@CAT@", "type");
643 prebuild_unix = prebuild;
644 prebuild_windows = prebuild;
647 const string condition_unix = "Condition=\" '$(OS)' != 'Windows_NT' \"";
648 const string condition_windows = "Condition=\" '$(OS)' == 'Windows_NT' \"";
650 " <PreBuildEvent " + condition_unix + ">\n" + prebuild_unix + "\n </PreBuildEvent>\n" +
651 " <PreBuildEvent " + condition_windows + ">\n" + prebuild_windows + "\n </PreBuildEvent>\n";
653 var all_args = new Queue<string []> ();
654 all_args.Enqueue (flags.Split ());
655 while (all_args.Count > 0) {
656 string [] f = all_args.Dequeue ();
658 for (int i = 0; i < f.Length; i++) {
659 if (f [i] [0] == '-')
660 f [i] = "/" + f [i].Substring (1);
662 if (f [i] [0] == '@') {
663 string [] extra_args;
664 string response_file = f [i].Substring (1);
666 var resp_file_full = Path.Combine (base_dir, response_file);
667 extra_args = LoadArgs (resp_file_full);
668 if (extra_args == null) {
669 Console.WriteLine ("Unable to open response file: " + resp_file_full);
670 Environment.Exit (1);
673 all_args.Enqueue (extra_args);
677 if (CSCParseOption (f [i], ref f))
679 Console.WriteLine ("Failure with {0}", f [i]);
680 Environment.Exit (1);
684 string [] source_files;
685 //Console.WriteLine ("Base: {0} res: {1}", base_dir, response);
686 using (var reader = new StreamReader (NativeName (base_dir + "\\" + response))) {
687 source_files = reader.ReadToEnd ().Split ();
690 Array.Sort (source_files);
692 StringBuilder sources = new StringBuilder ();
693 foreach (string s in source_files) {
697 string src = s.Replace ("/", "\\");
698 if (src.StartsWith (@"Test\..\"))
699 src = src.Substring (8, src.Length - 8);
701 sources.AppendFormat (" <Compile Include=\"{0}\" />" + NewLine, src);
704 source_files = built_sources.Split ();
705 Array.Sort (source_files);
707 foreach (string s in source_files) {
711 string src = s.Replace ("/", "\\");
712 if (src.StartsWith (@"Test\..\"))
713 src = src.Substring (8, src.Length - 8);
715 sources.AppendFormat (" <Compile Include=\"{0}\" />" + NewLine, src);
717 sources.Remove (sources.Length - 1, 1);
719 //if (library == "corlib-build") // otherwise, does not compile on fx_version == 4.0
721 // references.Add("System.dll");
722 // references.Add("System.Xml.dll");
725 //if (library == "System.Core-build") // otherwise, slow compile. May be a transient need.
727 // this.ignore_warning.Add(1685);
728 // this.ignore_warning.Add(0436);
731 result.library = library;
732 result.csprojFileName = "..\\..\\mcs\\" + dir + "\\" + library + ".csproj";
734 var refs = new StringBuilder ();
736 bool is_test = response.Contains ("_test_");
738 // F:\src\mono\mcs\class\lib\net_2_0\nunit.framework.dll
739 // F:\src\mono\mcs\class\SomeProject\SomeProject_test_-net_2_0.csproj
740 var nunitLibPath = string.Format (@"..\lib\{0}\nunit.framework.dll", profile);
741 refs.Append (string.Format (" <Reference Include=\"{0}\" />" + NewLine, nunitLibPath));
744 var resources = new StringBuilder ();
745 if (embedded_resources.Count > 0) {
746 resources.AppendFormat (" <ItemGroup>" + NewLine);
747 foreach (var dk in embedded_resources) {
748 resources.AppendFormat (" <EmbeddedResource Include=\"{0}\">" + NewLine, dk.Key);
749 resources.AppendFormat (" <LogicalName>{0}</LogicalName>" + NewLine, dk.Value);
750 resources.AppendFormat (" </EmbeddedResource>" + NewLine);
752 resources.AppendFormat (" </ItemGroup>" + NewLine);
754 if (references.Count > 0 || reference_aliases.Count > 0) {
755 // -r:mscorlib.dll -r:System.dll
756 //<ProjectReference Include="..\corlib\corlib-basic.csproj">
757 // <Project>{155aef28-c81f-405d-9072-9d52780e3e70}</Project>
758 // <Name>corlib-basic</Name>
759 //</ProjectReference>
760 //<ProjectReference Include="..\System\System-basic.csproj">
761 // <Project>{2094e859-db2f-481f-9630-f89d31d9ed48}</Project>
762 // <Name>System-basic</Name>
763 //</ProjectReference>
764 var refdistinct = references.Distinct ();
765 foreach (string r in refdistinct) {
766 VsCsproj lastMatching = GetMatchingCsproj (Path.GetFileName (r), projects);
767 if (lastMatching != null) {
768 AddProjectReference (refs, result, lastMatching, r, null);
771 Console.WriteLine ("{0}: Could not find a matching project reference for {1}", library, Path.GetFileName (r));
772 Console.WriteLine (" --> Adding reference with hintpath instead");
774 refs.Append (" <Reference Include=\"" + r + "\">" + NewLine);
775 refs.Append (" <SpecificVersion>False</SpecificVersion>" + NewLine);
776 refs.Append (" <HintPath>" + r + "</HintPath>" + NewLine);
777 refs.Append (" <Private>False</Private>" + NewLine);
778 refs.Append (" </Reference>" + NewLine);
782 foreach (string r in reference_aliases) {
783 int index = r.IndexOf ('=');
784 string alias = r.Substring (0, index);
785 string assembly = r.Substring (index + 1);
786 VsCsproj lastMatching = GetMatchingCsproj (Path.GetFileName (assembly), projects);
787 if (lastMatching != null) {
788 AddProjectReference (refs, result, lastMatching, r, alias);
790 throw new NotSupportedException (string.Format ("From {0}, could not find a matching project reference for {1}", library, r));
791 refs.Append (" <Reference Include=\"" + assembly + "\">" + NewLine);
792 refs.Append (" <SpecificVersion>False</SpecificVersion>" + NewLine);
793 refs.Append (" <HintPath>" + r + "</HintPath>" + NewLine);
794 refs.Append (" <Aliases>" + alias + "</Aliases>" + NewLine);
795 refs.Append (" </Reference>" + NewLine);
802 // ../class/lib/build/tmp/System.Xml.dll [No longer possible, we should be removing this from order.xml]
803 // /class/lib/basic/System.Core.dll
804 // <library_output>mcs.exe</library_output>
805 string build_output_dir;
806 if (library_output.Contains ("/"))
807 build_output_dir = Path.GetDirectoryName (library_output);
809 build_output_dir = "bin\\Debug\\" + library;
812 string postbuild_unix = string.Empty;
813 string postbuild_windows = string.Empty;
816 " <PostBuildEvent " + condition_unix + ">\n" + postbuild_unix + "\n </PostBuildEvent>\n" +
817 " <PostBuildEvent " + condition_windows + ">\n" + postbuild_windows + "\n </PostBuildEvent>";
820 bool basic_or_build = (library.Contains ("-basic") || library.Contains ("-build"));
823 // Replace the template values
825 result.projectGuid = "{" + Guid.NewGuid ().ToString ().ToUpper () + "}";
826 result.library_output = library_output;
827 result.fx_version = double.Parse (fx_version);
828 result.output = template.
829 Replace ("@PROJECTGUID@", result.projectGuid).
830 Replace ("@DEFINES@", defines.ToString ()).
831 Replace ("@DISABLEDWARNINGS@", string.Join (",", (from i in ignore_warning select i.ToString ()).ToArray ())).
832 //Replace("@NOSTDLIB@", (basic_or_build || (!StdLib)) ? "<NoStdLib>true</NoStdLib>" : string.Empty).
833 Replace ("@NOSTDLIB@", "<NoStdLib>" + (!StdLib).ToString () + "</NoStdLib>").
834 Replace ("@NOCONFIG@", "<NoConfig>" + (!load_default_config).ToString () + "</NoConfig>").
835 Replace ("@ALLOWUNSAFE@", Unsafe ? "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>" : "").
836 Replace ("@FX_VERSION", fx_version).
837 Replace ("@ASSEMBLYNAME@", Path.GetFileNameWithoutExtension (output_name)).
838 Replace ("@OUTPUTDIR@", build_output_dir).
839 Replace ("@DEFINECONSTANTS@", defines.ToString ()).
840 Replace ("@DEBUG@", want_debugging_support ? "true" : "false").
841 Replace ("@DEBUGTYPE@", want_debugging_support ? "full" : "pdbonly").
842 Replace ("@REFERENCES@", refs.ToString ()).
843 Replace ("@PREBUILD@", prebuild).
844 Replace ("@POSTBUILD@", postbuild).
845 //Replace ("@ADDITIONALLIBPATHS@", String.Format ("<AdditionalLibPaths>{0}</AdditionalLibPaths>", string.Join (",", libs.ToArray ()))).
846 Replace ("@ADDITIONALLIBPATHS@", String.Empty).
847 Replace ("@RESOURCES@", resources.ToString ()).
848 Replace ("@OPTIMIZE@", Optimize ? "true" : "false").
849 Replace ("@SOURCES@", sources.ToString ());
851 //Console.WriteLine ("Generated {0}", ofile.Replace ("\\", "/"));
852 var generatedProjFile = NativeName (result.csprojFileName);
853 Console.WriteLine ("Generating: {0}", generatedProjFile);
854 using (var o = new StreamWriter (generatedProjFile)) {
855 o.WriteLine (result.output);
861 void AddProjectReference (StringBuilder refs, VsCsproj result, VsCsproj lastMatching, string r, string alias)
863 refs.AppendFormat (" <ProjectReference Include=\"{0}\">{1}", GetRelativePath (result.csprojFileName, lastMatching.csprojFileName), NewLine);
864 refs.Append (" <Project>" + lastMatching.projectGuid + "</Project>" + NewLine);
865 refs.Append (" <Name>" + Path.GetFileNameWithoutExtension (lastMatching.csprojFileName) + "</Name>" + NewLine);
867 refs.Append (" <Aliases>" + alias + "</Aliases>");
868 refs.Append (" </ProjectReference>" + NewLine);
869 if (!result.projReferences.Contains (lastMatching))
870 result.projReferences.Add (lastMatching);
873 static string GetRelativePath (string from, string to)
875 from = from.Replace ("\\", "/");
876 to = to.Replace ("\\", "/");
877 var fromUri = new Uri (Path.GetFullPath (from));
878 var toUri = new Uri (Path.GetFullPath (to));
880 var ret = fromUri.MakeRelativeUri (toUri).ToString ().Replace ("%5C", "\x5c");
884 static VsCsproj GetMatchingCsproj (string dllReferenceName, List<VsCsproj> projects)
886 return projects.LastOrDefault (x => Path.GetFileName (x.library_output).Replace (".dll", "") == dllReferenceName.Replace (".dll", ""));
891 public class Driver {
893 static void Main (string [] args)
895 if (!File.Exists ("genproj.cs")) {
896 Console.WriteLine ("This command must be executed from mono/msvc/scripts");
897 Environment.Exit (1);
900 if (args.Length == 1 && args [0].ToLower ().Contains ("-h")) {
901 Console.WriteLine ("Usage:");
902 Console.WriteLine ("genproj.exe [visual_studio_release] [output_full_solutions]");
903 Console.WriteLine ("If output_full_solutions is false, only the main System*.dll");
904 Console.WriteLine (" assemblies (and dependencies) is included in the solution.");
905 Console.WriteLine ("Example:");
906 Console.WriteLine ("genproj.exe 2012 false");
907 Console.WriteLine ("genproj.exe with no arguments is equivalent to 'genproj.exe 2012 true'");
908 Environment.Exit (0);
910 var slnVersion = (args.Length > 0) ? args [0] : "2012";
911 bool fullSolutions = (args.Length > 1) ? bool.Parse (args [1]) : true;
913 var sln_gen = new SlnGenerator (slnVersion);
914 var two_sln_gen = new SlnGenerator (slnVersion);
915 var four_sln_gen = new SlnGenerator (slnVersion);
916 var three_five_sln_gen = new SlnGenerator (slnVersion);
917 var four_five_sln_gen = new SlnGenerator (slnVersion);
918 var projects = new List<MsbuildGenerator.VsCsproj> ();
920 XDocument doc = XDocument.Load ("order.xml");
921 var duplicates = new List<string> ();
922 foreach (XElement project in doc.Root.Elements ()) {
923 string dir = project.Attribute ("dir").Value;
924 string library = project.Attribute ("library").Value;
927 // Do only class libraries for now
929 if (!(dir.StartsWith ("class") || dir.StartsWith ("mcs") || dir.StartsWith ("basic")))
933 // Do not do 2.1, it is not working yet
934 // Do not do basic, as there is no point (requires a system mcs to be installed).
936 //if (library.Contains ("moonlight") || library.Contains ("-basic") || library.EndsWith ("bootstrap"))
937 if (library.Contains ("moonlight") || library.EndsWith ("bootstrap"))
940 var gen = new MsbuildGenerator (dir);
942 var csproj = gen.Generate (project, projects);
943 var csprojFilename = csproj.csprojFileName;
944 if (!sln_gen.ContainsProjectIdentifier (csproj.library)) {
945 projects.Add (csproj);
946 sln_gen.Add (csproj);
948 duplicates.Add (csprojFilename);
951 } catch (Exception e) {
952 Console.WriteLine ("Error in {0}\n{1}", dir, e);
956 Func<MsbuildGenerator.VsCsproj, bool> additionalFilter;
957 additionalFilter = fullSolutions ? (Func<MsbuildGenerator.VsCsproj, bool>)null : IsCommonLibrary;
959 FillSolution (two_sln_gen, MsbuildGenerator.profile_2_0, projects, additionalFilter);
960 FillSolution (four_five_sln_gen, MsbuildGenerator.profile_4_5, projects, additionalFilter);
961 FillSolution (four_sln_gen, MsbuildGenerator.profile_4_0, projects, additionalFilter);
962 FillSolution (three_five_sln_gen, MsbuildGenerator.profile_3_5, projects, additionalFilter);
964 var sb = new StringBuilder ();
965 sb.AppendLine ("WARNING: Skipped some project references, apparent duplicates in order.xml:");
966 foreach (var item in duplicates) {
967 sb.AppendLine (item);
969 Console.WriteLine (sb.ToString ());
971 WriteSolution (two_sln_gen, MakeSolutionName (MsbuildGenerator.profile_2_0));
972 WriteSolution (three_five_sln_gen, MakeSolutionName (MsbuildGenerator.profile_3_5));
973 WriteSolution (four_sln_gen, MakeSolutionName (MsbuildGenerator.profile_4_0));
974 WriteSolution (four_five_sln_gen, MakeSolutionName (MsbuildGenerator.profile_4_5));
976 // A few other optional solutions
977 // Solutions with 'everything' and the most common libraries used in development may be of interest
978 //WriteSolution (sln_gen, "mcs_full.sln");
979 //WriteSolution (small_full_sln_gen, "small_full.sln");
980 // The following may be useful if lacking visual studio or MonoDevelop, to bootstrap mono compiler self-hosting
981 //WriteSolution (basic_sln_gen, "mcs_basic.sln");
982 //WriteSolution (build_sln_gen, "mcs_build.sln");
985 static string MakeSolutionName (string profileTag)
987 return "net" + profileTag + ".sln";
990 static void FillSolution (SlnGenerator solution, string profileString, List<MsbuildGenerator.VsCsproj> projects, Func<MsbuildGenerator.VsCsproj, bool> additionalFilter = null)
992 foreach (var vsCsproj in projects) {
993 if (!vsCsproj.library.Contains (profileString))
995 if (additionalFilter != null && !additionalFilter (vsCsproj))
997 var csprojFilename = vsCsproj.csprojFileName;
998 if (!solution.ContainsProjectIdentifier (vsCsproj.library)) {
999 solution.Add (vsCsproj);
1000 RecursiveAddProj (solution, vsCsproj);
1005 static void RecursiveAddProj (SlnGenerator solution, MsbuildGenerator.VsCsproj vsCsproj, int recursiveDepth = 1)
1007 const int max_recursive = 16;
1008 if (recursiveDepth > max_recursive) throw new Exception (string.Format ("Reached {0} levels of project dependency", max_recursive));
1009 foreach (var projRef in vsCsproj.projReferences) {
1010 if (!solution.ContainsProjectIdentifier (projRef.library)) {
1011 solution.Add (projRef);
1012 RecursiveAddProj (solution, projRef, recursiveDepth + 1);
1017 static void WriteSolution (SlnGenerator sln_gen, string slnfilename)
1019 Console.WriteLine (String.Format ("Writing solution {1}, with {0} projects", sln_gen.Count, slnfilename));
1020 sln_gen.Write (slnfilename);
1023 static bool IsCommonLibrary (MsbuildGenerator.VsCsproj proj)
1025 var library = proj.library;
1026 //if (library.Contains ("-basic"))
1028 //if (library.Contains ("-build"))
1030 //if (library.StartsWith ("corlib"))
1032 if (library.StartsWith ("System-"))
1034 if (library.StartsWith ("System.Xml"))
1036 if (library.StartsWith ("System.Secu"))
1038 if (library.StartsWith ("System.Configuration"))
1040 if (library.StartsWith ("System.Core"))
1042 //if (library.StartsWith ("Mono."))