genproj.cs 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using System.Globalization;
  6. using System.Xml.Linq;
  7. using System.Xml.XPath;
  8. using System.Linq;
  9. using System.Xml;
  10. public enum Target {
  11. Library, Exe, Module, WinExe
  12. }
  13. public enum LanguageVersion {
  14. ISO_1 = 1,
  15. Default_MCS = 2,
  16. ISO_2 = 3,
  17. LINQ = 4,
  18. Future = 5,
  19. Default = LINQ
  20. }
  21. class SlnGenerator {
  22. public static readonly string NewLine = "\r\n"; //Environment.NewLine; // "\n";
  23. public SlnGenerator (string formatVersion = "2012")
  24. {
  25. switch (formatVersion) {
  26. case "2008":
  27. this.header = MakeHeader ("10.00", "2008");
  28. break;
  29. default:
  30. this.header = MakeHeader ("12.00", "2012");
  31. break;
  32. }
  33. }
  34. const string project_start = "Project(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"{0}\", \"{1}\", \"{2}\""; // Note: No need to double up on {} around {2}
  35. const string project_end = "EndProject";
  36. List<MsbuildGenerator.VsCsproj> libraries = new List<MsbuildGenerator.VsCsproj> ();
  37. string header;
  38. string MakeHeader (string formatVersion, string yearTag)
  39. {
  40. return string.Format ("Microsoft Visual Studio Solution File, Format Version {0}" + NewLine + "# Visual Studio {1}", formatVersion, yearTag);
  41. }
  42. public void Add (MsbuildGenerator.VsCsproj vsproj)
  43. {
  44. try {
  45. libraries.Add (vsproj);
  46. } catch (Exception ex) {
  47. Console.WriteLine (ex);
  48. }
  49. }
  50. public void Write (string filename)
  51. {
  52. using (var sln = new StreamWriter (filename)) {
  53. sln.WriteLine ();
  54. sln.WriteLine (header);
  55. foreach (var proj in libraries) {
  56. sln.WriteLine (project_start, proj.library, proj.csProjFilename, proj.projectGuid);
  57. sln.WriteLine (project_end);
  58. }
  59. sln.WriteLine ("Global");
  60. sln.WriteLine ("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
  61. sln.WriteLine ("\t\tDebug|Any CPU = Debug|Any CPU");
  62. sln.WriteLine ("\t\tRelease|Any CPU = Release|Any CPU");
  63. sln.WriteLine ("\tEndGlobalSection");
  64. sln.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
  65. foreach (var proj in libraries) {
  66. var guid = proj.projectGuid;
  67. sln.WriteLine ("\t\t{0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", guid);
  68. sln.WriteLine ("\t\t{0}.Debug|Any CPU.Build.0 = Debug|Any CPU", guid);
  69. sln.WriteLine ("\t\t{0}.Release|Any CPU.ActiveCfg = Release|Any CPU", guid);
  70. sln.WriteLine ("\t\t{0}.Release|Any CPU.Build.0 = Release|Any CPU", guid);
  71. }
  72. sln.WriteLine ("\tEndGlobalSection");
  73. sln.WriteLine ("\tGlobalSection(SolutionProperties) = preSolution");
  74. sln.WriteLine ("\t\tHideSolutionNode = FALSE");
  75. sln.WriteLine ("\tEndGlobalSection");
  76. sln.WriteLine ("EndGlobal");
  77. }
  78. }
  79. internal bool ContainsProjectIdentifier (string projId)
  80. {
  81. return libraries.FindIndex (x => (x.library == projId)) >= 0;
  82. }
  83. public int Count { get { return libraries.Count; } }
  84. }
  85. class MsbuildGenerator {
  86. static readonly string NewLine = SlnGenerator.NewLine;
  87. static XmlNamespaceManager xmlns;
  88. public const string profile_2_0 = "_2_0";
  89. public const string profile_3_5 = "_3_5";
  90. public const string profile_4_0 = "_4_0";
  91. public const string profile_4_5 = "_4_5";
  92. static void Usage ()
  93. {
  94. Console.WriteLine ("Invalid argument");
  95. }
  96. static string template;
  97. static MsbuildGenerator ()
  98. {
  99. using (var input = new StreamReader ("csproj.tmpl")) {
  100. template = input.ReadToEnd ();
  101. }
  102. xmlns = new XmlNamespaceManager (new NameTable ());
  103. xmlns.AddNamespace ("x", "http://schemas.microsoft.com/developer/msbuild/2003");
  104. }
  105. // The directory as specified in order.xml
  106. string dir;
  107. string library;
  108. string projectGuid;
  109. string fx_version;
  110. XElement xproject;
  111. public string CsprojFilename;
  112. //
  113. // Our base directory, this is relative to our exectution point mono/msvc/scripts
  114. string base_dir;
  115. string mcs_topdir;
  116. public string LibraryOutput, AbsoluteLibraryOutput;
  117. public MsbuildGenerator (XElement xproject)
  118. {
  119. this.xproject = xproject;
  120. dir = xproject.Attribute ("dir").Value;
  121. library = xproject.Attribute ("library").Value;
  122. CsprojFilename = "..\\..\\mcs\\" + dir + "\\" + library + ".csproj";
  123. LibraryOutput = xproject.Element ("library_output").Value;
  124. projectGuid = LookupOrGenerateGuid ();
  125. fx_version = xproject.Element ("fx_version").Value;
  126. Csproj = new VsCsproj () {
  127. csProjFilename = this.CsprojFilename,
  128. projectGuid = this.projectGuid,
  129. library_output = this.LibraryOutput,
  130. fx_version = double.Parse (fx_version),
  131. library = this.library
  132. };
  133. if (dir == "mcs") {
  134. mcs_topdir = "../";
  135. class_dir = "../class/";
  136. base_dir = "../../mcs/mcs";
  137. } else {
  138. mcs_topdir = "../";
  139. foreach (char c in dir) {
  140. if (c == '/')
  141. mcs_topdir = "..//" + mcs_topdir;
  142. }
  143. class_dir = mcs_topdir.Substring (3);
  144. base_dir = Path.Combine ("..", "..", "mcs", dir);
  145. }
  146. AbsoluteLibraryOutput = Path.GetFullPath (Path.Combine (base_dir, LibraryOutput));
  147. }
  148. string LookupOrGenerateGuid ()
  149. {
  150. var projectFile = NativeName (CsprojFilename);
  151. if (File.Exists (projectFile)){
  152. var doc = XDocument.Load (projectFile);
  153. return doc.XPathSelectElement ("x:Project/x:PropertyGroup/x:ProjectGuid", xmlns).Value;
  154. }
  155. return "{" + Guid.NewGuid ().ToString ().ToUpper () + "}";
  156. }
  157. // Currently used
  158. bool Unsafe = false;
  159. StringBuilder defines = new StringBuilder ();
  160. bool Optimize = true;
  161. bool want_debugging_support = false;
  162. Dictionary<string, string> embedded_resources = new Dictionary<string, string> ();
  163. List<string> warning_as_error = new List<string> ();
  164. List<int> ignore_warning = new List<int> ();
  165. bool load_default_config = true;
  166. bool StdLib = true;
  167. List<string> references = new List<string> ();
  168. List<string> libs = new List<string> ();
  169. List<string> reference_aliases = new List<string> ();
  170. bool showWarnings = false;
  171. // Currently unused
  172. #pragma warning disable 0219, 0414
  173. int WarningLevel = 4;
  174. bool Checked = false;
  175. bool WarningsAreErrors;
  176. bool VerifyClsCompliance = true;
  177. string win32IconFile;
  178. string StrongNameKeyFile;
  179. bool copyLocal = true;
  180. Target Target = Target.Exe;
  181. string TargetExt = ".exe";
  182. string OutputFile;
  183. string StrongNameKeyContainer;
  184. bool StrongNameDelaySign = false;
  185. LanguageVersion Version = LanguageVersion.Default;
  186. string CodePage;
  187. // Class directory, relative to
  188. string class_dir;
  189. #pragma warning restore 0219,414
  190. readonly char [] argument_value_separator = new char [] { ';', ',' };
  191. //
  192. // This parses the -arg and /arg options to the compiler, even if the strings
  193. // in the following text use "/arg" on the strings.
  194. //
  195. bool CSCParseOption (string option, ref string [] args)
  196. {
  197. int idx = option.IndexOf (':');
  198. string arg, value;
  199. if (idx == -1) {
  200. arg = option;
  201. value = "";
  202. } else {
  203. arg = option.Substring (0, idx);
  204. value = option.Substring (idx + 1);
  205. }
  206. switch (arg.ToLower (CultureInfo.InvariantCulture)) {
  207. case "/nologo":
  208. return true;
  209. case "/t":
  210. case "/target":
  211. switch (value) {
  212. case "exe":
  213. Target = Target.Exe;
  214. break;
  215. case "winexe":
  216. Target = Target.WinExe;
  217. break;
  218. case "library":
  219. Target = Target.Library;
  220. TargetExt = ".dll";
  221. break;
  222. case "module":
  223. Target = Target.Module;
  224. TargetExt = ".netmodule";
  225. break;
  226. default:
  227. return false;
  228. }
  229. return true;
  230. case "/out":
  231. if (value.Length == 0) {
  232. Usage ();
  233. Environment.Exit (1);
  234. }
  235. OutputFile = value;
  236. return true;
  237. case "/o":
  238. case "/o+":
  239. case "/optimize":
  240. case "/optimize+":
  241. Optimize = true;
  242. return true;
  243. case "/o-":
  244. case "/optimize-":
  245. Optimize = false;
  246. return true;
  247. case "/incremental":
  248. case "/incremental+":
  249. case "/incremental-":
  250. // nothing.
  251. return true;
  252. case "/d":
  253. case "/define": {
  254. if (value.Length == 0) {
  255. Usage ();
  256. Environment.Exit (1);
  257. }
  258. foreach (string d in value.Split (argument_value_separator)) {
  259. if (defines.Length != 0)
  260. defines.Append (";");
  261. defines.Append (d);
  262. }
  263. return true;
  264. }
  265. case "/bugreport":
  266. //
  267. // We should collect data, runtime, etc and store in the file specified
  268. //
  269. return true;
  270. case "/linkres":
  271. case "/linkresource":
  272. case "/res":
  273. case "/resource":
  274. bool embeded = arg [1] == 'r' || arg [1] == 'R';
  275. string [] s = value.Split (argument_value_separator);
  276. switch (s.Length) {
  277. case 1:
  278. if (s [0].Length == 0)
  279. goto default;
  280. embedded_resources [s [0]] = Path.GetFileName (s [0]);
  281. break;
  282. case 2:
  283. embedded_resources [s [0]] = s [1];
  284. break;
  285. case 3:
  286. Console.WriteLine ("Does not support this method yet: {0}", arg);
  287. Environment.Exit (1);
  288. break;
  289. default:
  290. Console.WriteLine ("Wrong number of arguments for option `{0}'", option);
  291. Environment.Exit (1);
  292. break;
  293. }
  294. return true;
  295. case "/recurse":
  296. Console.WriteLine ("/recurse not supported");
  297. Environment.Exit (1);
  298. return true;
  299. case "/r":
  300. case "/reference": {
  301. if (value.Length == 0) {
  302. Console.WriteLine ("-reference requires an argument");
  303. Environment.Exit (1);
  304. }
  305. string [] refs = value.Split (argument_value_separator);
  306. foreach (string r in refs) {
  307. string val = r;
  308. int index = val.IndexOf ('=');
  309. if (index > -1) {
  310. reference_aliases.Add (r);
  311. continue;
  312. }
  313. if (val.Length != 0)
  314. references.Add (val);
  315. }
  316. return true;
  317. }
  318. case "/main":
  319. case "/m":
  320. case "/addmodule":
  321. case "/win32res":
  322. case "/doc":
  323. if (showWarnings)
  324. Console.WriteLine ("{0} = not supported", arg);
  325. return true;
  326. case "/lib": {
  327. libs.Add (value);
  328. return true;
  329. }
  330. case "/win32icon": {
  331. win32IconFile = value;
  332. return true;
  333. }
  334. case "/debug-":
  335. want_debugging_support = false;
  336. return true;
  337. case "/debug":
  338. case "/debug+":
  339. want_debugging_support = true;
  340. return true;
  341. case "/checked":
  342. case "/checked+":
  343. Checked = true;
  344. return true;
  345. case "/checked-":
  346. Checked = false;
  347. return true;
  348. case "/clscheck":
  349. case "/clscheck+":
  350. return true;
  351. case "/clscheck-":
  352. VerifyClsCompliance = false;
  353. return true;
  354. case "/unsafe":
  355. case "/unsafe+":
  356. Unsafe = true;
  357. return true;
  358. case "/unsafe-":
  359. Unsafe = false;
  360. return true;
  361. case "/warnaserror":
  362. case "/warnaserror+":
  363. if (value.Length == 0) {
  364. WarningsAreErrors = true;
  365. } else {
  366. foreach (string wid in value.Split (argument_value_separator))
  367. warning_as_error.Add (wid);
  368. }
  369. return true;
  370. case "/-runtime":
  371. // Console.WriteLine ("Warning ignoring /runtime:v4");
  372. return true;
  373. case "/warnaserror-":
  374. if (value.Length == 0) {
  375. WarningsAreErrors = false;
  376. } else {
  377. foreach (string wid in value.Split (argument_value_separator))
  378. warning_as_error.Remove (wid);
  379. }
  380. return true;
  381. case "/warn":
  382. WarningLevel = Int32.Parse (value);
  383. return true;
  384. case "/nowarn": {
  385. string [] warns;
  386. if (value.Length == 0) {
  387. Console.WriteLine ("/nowarn requires an argument");
  388. Environment.Exit (1);
  389. }
  390. warns = value.Split (argument_value_separator);
  391. foreach (string wc in warns) {
  392. try {
  393. if (wc.Trim ().Length == 0)
  394. continue;
  395. int warn = Int32.Parse (wc);
  396. if (warn < 1) {
  397. throw new ArgumentOutOfRangeException ("warn");
  398. }
  399. ignore_warning.Add (warn);
  400. } catch {
  401. Console.WriteLine (String.Format ("`{0}' is not a valid warning number", wc));
  402. Environment.Exit (1);
  403. }
  404. }
  405. return true;
  406. }
  407. case "/noconfig":
  408. load_default_config = false;
  409. return true;
  410. case "/nostdlib":
  411. case "/nostdlib+":
  412. StdLib = false;
  413. return true;
  414. case "/nostdlib-":
  415. StdLib = true;
  416. return true;
  417. case "/fullpaths":
  418. return true;
  419. case "/keyfile":
  420. if (value == String.Empty) {
  421. Console.WriteLine ("{0} requires an argument", arg);
  422. Environment.Exit (1);
  423. }
  424. StrongNameKeyFile = value;
  425. return true;
  426. case "/keycontainer":
  427. if (value == String.Empty) {
  428. Console.WriteLine ("{0} requires an argument", arg);
  429. Environment.Exit (1);
  430. }
  431. StrongNameKeyContainer = value;
  432. return true;
  433. case "/delaysign+":
  434. case "/delaysign":
  435. StrongNameDelaySign = true;
  436. return true;
  437. case "/delaysign-":
  438. StrongNameDelaySign = false;
  439. return true;
  440. case "/langversion":
  441. switch (value.ToLower (CultureInfo.InvariantCulture)) {
  442. case "iso-1":
  443. Version = LanguageVersion.ISO_1;
  444. return true;
  445. case "default":
  446. Version = LanguageVersion.Default;
  447. return true;
  448. case "iso-2":
  449. Version = LanguageVersion.ISO_2;
  450. return true;
  451. case "future":
  452. Version = LanguageVersion.Future;
  453. return true;
  454. }
  455. Console.WriteLine ("Invalid option `{0}' for /langversion. It must be either `ISO-1', `ISO-2' or `Default'", value);
  456. Environment.Exit (1);
  457. return true;
  458. case "/codepage":
  459. CodePage = value;
  460. return true;
  461. }
  462. Console.WriteLine ("Failing with : {0}", arg);
  463. return false;
  464. }
  465. static string [] LoadArgs (string file)
  466. {
  467. StreamReader f;
  468. var args = new List<string> ();
  469. string line;
  470. try {
  471. f = new StreamReader (file);
  472. } catch {
  473. return null;
  474. }
  475. StringBuilder sb = new StringBuilder ();
  476. while ((line = f.ReadLine ()) != null) {
  477. int t = line.Length;
  478. for (int i = 0; i < t; i++) {
  479. char c = line [i];
  480. if (c == '"' || c == '\'') {
  481. char end = c;
  482. for (i++; i < t; i++) {
  483. c = line [i];
  484. if (c == end)
  485. break;
  486. sb.Append (c);
  487. }
  488. } else if (c == ' ') {
  489. if (sb.Length > 0) {
  490. args.Add (sb.ToString ());
  491. sb.Length = 0;
  492. }
  493. } else
  494. sb.Append (c);
  495. }
  496. if (sb.Length > 0) {
  497. args.Add (sb.ToString ());
  498. sb.Length = 0;
  499. }
  500. }
  501. string [] ret_value = new string [args.Count];
  502. args.CopyTo (ret_value, 0);
  503. return ret_value;
  504. }
  505. static string Load (string f)
  506. {
  507. var native = NativeName (f);
  508. if (File.Exists (native)) {
  509. using (var sr = new StreamReader (native)) {
  510. return sr.ReadToEnd ();
  511. }
  512. } else
  513. return "";
  514. }
  515. public static string NativeName (string path)
  516. {
  517. if (System.IO.Path.DirectorySeparatorChar == '/')
  518. return path.Replace ("\\", "/");
  519. else
  520. return path.Replace ("/", "\\");
  521. }
  522. public class VsCsproj {
  523. public string projectGuid;
  524. public string output;
  525. public string library_output;
  526. public string csProjFilename;
  527. public double fx_version;
  528. public List<VsCsproj> projReferences = new List<VsCsproj> ();
  529. public string library;
  530. }
  531. public VsCsproj Csproj;
  532. public VsCsproj Generate (Dictionary<string,MsbuildGenerator> projects, bool showWarnings = false)
  533. {
  534. var generatedProjFile = NativeName (Csproj.csProjFilename);
  535. //Console.WriteLine ("Generating: {0}", generatedProjFile);
  536. string boot, flags, output_name, built_sources, response, profile;
  537. boot = xproject.Element ("boot").Value;
  538. flags = xproject.Element ("flags").Value;
  539. output_name = xproject.Element ("output").Value;
  540. built_sources = xproject.Element ("built_sources").Value;
  541. response = xproject.Element ("response").Value;
  542. //if (library.EndsWith("-build")) fx_version = "2.0"; // otherwise problem if .NET4.5 is installed, seems. (https://github.com/nikhilk/scriptsharp/issues/156)
  543. profile = xproject.Element ("profile").Value;
  544. if (string.IsNullOrEmpty (response)) {
  545. // Address the issue where entries are missing the fx_version
  546. // Should be fixed in the Makefile or elsewhere; this is a workaround
  547. //<fx_version>basic</fx_version>
  548. //<profile>./../build/deps/mcs.exe.sources.response</profile>
  549. //<response></response>
  550. response = profile;
  551. profile = fx_version;
  552. if (response.Contains ("build") || response.Contains ("basic") || response.Contains (profile_2_0)) {
  553. fx_version = "2.0";
  554. if (response.Contains (profile_2_0)) profile = "net_2_0";
  555. } if (response.Contains ("build") || response.Contains ("basic") || response.Contains (profile_2_0)) {
  556. fx_version = "2.0";
  557. } else if (response.Contains (profile_3_5)) {
  558. fx_version = "3.5";
  559. profile = "net_3_5";
  560. } else if (response.Contains (profile_4_0)) {
  561. fx_version = "4.0";
  562. profile = "net_4_0";
  563. } else if (response.Contains (profile_4_5)) {
  564. fx_version = "4.5";
  565. profile = "net_4_5";
  566. }
  567. }
  568. //
  569. // Prebuild code, might be in inputs, check:
  570. // inputs/LIBRARY-PROFILE.pre
  571. // inputs/LIBRARY.pre
  572. //
  573. string prebuild = Load (library + ".pre");
  574. string prebuild_windows, prebuild_unix;
  575. int q = library.IndexOf ("-");
  576. if (q != -1)
  577. prebuild = prebuild + Load (library.Substring (0, q) + ".pre");
  578. if (prebuild.IndexOf ("@MONO@") != -1){
  579. prebuild_unix = prebuild.Replace ("@MONO@", "mono").Replace ("@CAT@", "cat");
  580. prebuild_windows = prebuild.Replace ("@MONO@", "").Replace ("@CAT@", "type");
  581. } else {
  582. prebuild_unix = prebuild.Replace ("jay.exe", "jay");
  583. prebuild_windows = prebuild;
  584. }
  585. const string condition_unix = "Condition=\" '$(OS)' != 'Windows_NT' \"";
  586. const string condition_windows = "Condition=\" '$(OS)' == 'Windows_NT' \"";
  587. prebuild =
  588. " <PreBuildEvent " + condition_unix + ">\n" + prebuild_unix + "\n </PreBuildEvent>\n" +
  589. " <PreBuildEvent " + condition_windows + ">\n" + prebuild_windows + "\n </PreBuildEvent>\n";
  590. var all_args = new Queue<string []> ();
  591. all_args.Enqueue (flags.Split ());
  592. while (all_args.Count > 0) {
  593. string [] f = all_args.Dequeue ();
  594. for (int i = 0; i < f.Length; i++) {
  595. if (f [i].Length > 0 && f [i][0] == '-')
  596. f [i] = "/" + f [i].Substring (1);
  597. if (f [i] [0] == '@') {
  598. string [] extra_args;
  599. string response_file = f [i].Substring (1);
  600. var resp_file_full = Path.Combine (base_dir, response_file);
  601. extra_args = LoadArgs (resp_file_full);
  602. if (extra_args == null) {
  603. Console.WriteLine ("Unable to open response file: " + resp_file_full);
  604. Environment.Exit (1);
  605. }
  606. all_args.Enqueue (extra_args);
  607. continue;
  608. }
  609. if (CSCParseOption (f [i], ref f))
  610. continue;
  611. Console.WriteLine ("Failure with {0}", f [i]);
  612. Environment.Exit (1);
  613. }
  614. }
  615. string [] source_files;
  616. //Console.WriteLine ("Base: {0} res: {1}", base_dir, response);
  617. using (var reader = new StreamReader (NativeName (base_dir + "\\" + response))) {
  618. source_files = reader.ReadToEnd ().Split ();
  619. }
  620. Array.Sort (source_files);
  621. StringBuilder sources = new StringBuilder ();
  622. foreach (string s in source_files) {
  623. if (s.Length == 0)
  624. continue;
  625. string src = s.Replace ("/", "\\");
  626. if (src.StartsWith (@"Test\..\"))
  627. src = src.Substring (8, src.Length - 8);
  628. sources.AppendFormat (" <Compile Include=\"{0}\" />" + NewLine, src);
  629. }
  630. source_files = built_sources.Split ();
  631. Array.Sort (source_files);
  632. foreach (string s in source_files) {
  633. if (s.Length == 0)
  634. continue;
  635. string src = s.Replace ("/", "\\");
  636. if (src.StartsWith (@"Test\..\"))
  637. src = src.Substring (8, src.Length - 8);
  638. sources.AppendFormat (" <Compile Include=\"{0}\" />" + NewLine, src);
  639. }
  640. sources.Remove (sources.Length - 1, 1);
  641. //if (library == "corlib-build") // otherwise, does not compile on fx_version == 4.0
  642. //{
  643. // references.Add("System.dll");
  644. // references.Add("System.Xml.dll");
  645. //}
  646. //if (library == "System.Core-build") // otherwise, slow compile. May be a transient need.
  647. //{
  648. // this.ignore_warning.Add(1685);
  649. // this.ignore_warning.Add(0436);
  650. //}
  651. var refs = new StringBuilder ();
  652. bool is_test = response.Contains ("_test_");
  653. if (is_test) {
  654. // F:\src\mono\mcs\class\lib\net_2_0\nunit.framework.dll
  655. // F:\src\mono\mcs\class\SomeProject\SomeProject_test_-net_2_0.csproj
  656. var nunitLibPath = string.Format (@"..\lib\{0}\nunit.framework.dll", profile);
  657. refs.Append (string.Format (" <Reference Include=\"{0}\" />" + NewLine, nunitLibPath));
  658. }
  659. var resources = new StringBuilder ();
  660. if (embedded_resources.Count > 0) {
  661. resources.AppendFormat (" <ItemGroup>" + NewLine);
  662. foreach (var dk in embedded_resources) {
  663. resources.AppendFormat (" <EmbeddedResource Include=\"{0}\">" + NewLine, dk.Key);
  664. resources.AppendFormat (" <LogicalName>{0}</LogicalName>" + NewLine, dk.Value);
  665. resources.AppendFormat (" </EmbeddedResource>" + NewLine);
  666. }
  667. resources.AppendFormat (" </ItemGroup>" + NewLine);
  668. }
  669. if (references.Count > 0 || reference_aliases.Count > 0) {
  670. // -r:mscorlib.dll -r:System.dll
  671. //<ProjectReference Include="..\corlib\corlib-basic.csproj">
  672. // <Project>{155aef28-c81f-405d-9072-9d52780e3e70}</Project>
  673. // <Name>corlib-basic</Name>
  674. //</ProjectReference>
  675. //<ProjectReference Include="..\System\System-basic.csproj">
  676. // <Project>{2094e859-db2f-481f-9630-f89d31d9ed48}</Project>
  677. // <Name>System-basic</Name>
  678. //</ProjectReference>
  679. var refdistinct = references.Distinct ();
  680. foreach (string r in refdistinct) {
  681. var match = GetMatchingCsproj (Path.GetFileName (r), projects);
  682. if (match != null) {
  683. AddProjectReference (refs, Csproj, match, r, null);
  684. } else {
  685. if (showWarnings){
  686. Console.WriteLine ("{0}: Could not find a matching project reference for {1}", library, Path.GetFileName (r));
  687. Console.WriteLine (" --> Adding reference with hintpath instead");
  688. }
  689. refs.Append (" <Reference Include=\"" + r + "\">" + NewLine);
  690. refs.Append (" <SpecificVersion>False</SpecificVersion>" + NewLine);
  691. refs.Append (" <HintPath>" + r + "</HintPath>" + NewLine);
  692. refs.Append (" <Private>False</Private>" + NewLine);
  693. refs.Append (" </Reference>" + NewLine);
  694. }
  695. }
  696. foreach (string r in reference_aliases) {
  697. int index = r.IndexOf ('=');
  698. string alias = r.Substring (0, index);
  699. string assembly = r.Substring (index + 1);
  700. var match = GetMatchingCsproj (assembly, projects, explicitPath: true);
  701. if (match != null) {
  702. AddProjectReference (refs, Csproj, match, r, alias);
  703. } else {
  704. throw new NotSupportedException (string.Format ("From {0}, could not find a matching project reference for {1}", library, r));
  705. refs.Append (" <Reference Include=\"" + assembly + "\">" + NewLine);
  706. refs.Append (" <SpecificVersion>False</SpecificVersion>" + NewLine);
  707. refs.Append (" <HintPath>" + r + "</HintPath>" + NewLine);
  708. refs.Append (" <Aliases>" + alias + "</Aliases>" + NewLine);
  709. refs.Append (" </Reference>" + NewLine);
  710. }
  711. }
  712. }
  713. // Possible inputs:
  714. // ../class/lib/build/tmp/System.Xml.dll [No longer possible, we should be removing this from order.xml]
  715. // /class/lib/basic/System.Core.dll
  716. // <library_output>mcs.exe</library_output>
  717. string build_output_dir;
  718. if (LibraryOutput.Contains ("/"))
  719. build_output_dir = Path.GetDirectoryName (LibraryOutput);
  720. else
  721. build_output_dir = "bin\\Debug\\" + library;
  722. string postbuild_unix = string.Empty;
  723. string postbuild_windows = string.Empty;
  724. var postbuild =
  725. " <PostBuildEvent " + condition_unix + ">\n" + postbuild_unix + "\n </PostBuildEvent>\n" +
  726. " <PostBuildEvent " + condition_windows + ">\n" + postbuild_windows + "\n </PostBuildEvent>";
  727. bool basic_or_build = (library.Contains ("-basic") || library.Contains ("-build"));
  728. //
  729. // Replace the template values
  730. //
  731. string strongNameSection = "";
  732. if (StrongNameKeyFile != null){
  733. strongNameSection = String.Format (
  734. " <PropertyGroup>\n" +
  735. " <SignAssembly>true</SignAssembly>\n" +
  736. "{1}" +
  737. " </PropertyGroup>\n" +
  738. " <PropertyGroup>\n" +
  739. " <AssemblyOriginatorKeyFile>{0}</AssemblyOriginatorKeyFile>\n" +
  740. " </PropertyGroup>", StrongNameKeyFile, StrongNameDelaySign ? " <DelaySign>true</DelaySign>\n" : "");
  741. }
  742. Csproj.output = template.
  743. Replace ("@SIGNATURE@", strongNameSection).
  744. Replace ("@PROJECTGUID@", Csproj.projectGuid).
  745. Replace ("@DEFINES@", defines.ToString ()).
  746. Replace ("@DISABLEDWARNINGS@", string.Join (",", (from i in ignore_warning select i.ToString ()).ToArray ())).
  747. //Replace("@NOSTDLIB@", (basic_or_build || (!StdLib)) ? "<NoStdLib>true</NoStdLib>" : string.Empty).
  748. Replace ("@NOSTDLIB@", "<NoStdLib>" + (!StdLib).ToString () + "</NoStdLib>").
  749. Replace ("@NOCONFIG@", "<NoConfig>" + (!load_default_config).ToString () + "</NoConfig>").
  750. Replace ("@ALLOWUNSAFE@", Unsafe ? "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>" : "").
  751. Replace ("@FX_VERSION", fx_version).
  752. Replace ("@ASSEMBLYNAME@", Path.GetFileNameWithoutExtension (output_name)).
  753. Replace ("@OUTPUTDIR@", build_output_dir).
  754. Replace ("@DEFINECONSTANTS@", defines.ToString ()).
  755. Replace ("@DEBUG@", want_debugging_support ? "true" : "false").
  756. Replace ("@DEBUGTYPE@", want_debugging_support ? "full" : "pdbonly").
  757. Replace ("@REFERENCES@", refs.ToString ()).
  758. Replace ("@PREBUILD@", prebuild).
  759. Replace ("@POSTBUILD@", postbuild).
  760. //Replace ("@ADDITIONALLIBPATHS@", String.Format ("<AdditionalLibPaths>{0}</AdditionalLibPaths>", string.Join (",", libs.ToArray ()))).
  761. Replace ("@ADDITIONALLIBPATHS@", String.Empty).
  762. Replace ("@RESOURCES@", resources.ToString ()).
  763. Replace ("@OPTIMIZE@", Optimize ? "true" : "false").
  764. Replace ("@SOURCES@", sources.ToString ());
  765. //Console.WriteLine ("Generated {0}", ofile.Replace ("\\", "/"));
  766. using (var o = new StreamWriter (generatedProjFile)) {
  767. o.WriteLine (Csproj.output);
  768. }
  769. return Csproj;
  770. }
  771. void AddProjectReference (StringBuilder refs, VsCsproj result, MsbuildGenerator match, string r, string alias)
  772. {
  773. refs.AppendFormat (" <ProjectReference Include=\"{0}\">{1}", GetRelativePath (result.csProjFilename, match.CsprojFilename), NewLine);
  774. refs.Append (" <Project>" + match.projectGuid + "</Project>" + NewLine);
  775. refs.Append (" <Name>" + Path.GetFileNameWithoutExtension (match.CsprojFilename) + "</Name>" + NewLine);
  776. if (alias != null)
  777. refs.Append (" <Aliases>" + alias + "</Aliases>");
  778. refs.Append (" </ProjectReference>" + NewLine);
  779. if (!result.projReferences.Contains (match.Csproj))
  780. result.projReferences.Add (match.Csproj);
  781. }
  782. static string GetRelativePath (string from, string to)
  783. {
  784. from = from.Replace ("\\", "/");
  785. to = to.Replace ("\\", "/");
  786. var fromUri = new Uri (Path.GetFullPath (from));
  787. var toUri = new Uri (Path.GetFullPath (to));
  788. var ret = fromUri.MakeRelativeUri (toUri).ToString ().Replace ("%5C", "\x5c");
  789. return ret;
  790. }
  791. MsbuildGenerator GetMatchingCsproj (string dllReferenceName, Dictionary<string,MsbuildGenerator> projects, bool explicitPath = false)
  792. {
  793. // libDir would be "./../../class/lib/net_4_5 for example
  794. // project
  795. if (!dllReferenceName.EndsWith (".dll"))
  796. dllReferenceName += ".dll";
  797. if (explicitPath){
  798. var probe = Path.GetFullPath (Path.Combine (base_dir, dllReferenceName));
  799. foreach (var project in projects){
  800. if (probe == project.Value.AbsoluteLibraryOutput)
  801. return project.Value;
  802. }
  803. }
  804. // not explicit, search for the library in the lib path order specified
  805. foreach (var libDir in libs) {
  806. var abs = Path.GetFullPath (Path.Combine (base_dir, libDir));
  807. foreach (var project in projects){
  808. var probe = Path.Combine (abs, dllReferenceName);
  809. if (probe == project.Value.AbsoluteLibraryOutput)
  810. return project.Value;
  811. }
  812. }
  813. Console.WriteLine ("Did not find referenced {0} with libs={1}", dllReferenceName, String.Join (", ", libs));
  814. foreach (var p in projects) {
  815. Console.WriteLine (" => {0}", p.Value.AbsoluteLibraryOutput);
  816. }
  817. return null;
  818. }
  819. }
  820. public class Driver {
  821. static IEnumerable<XElement> GetProjects ()
  822. {
  823. XDocument doc = XDocument.Load ("order.xml");
  824. foreach (XElement project in doc.Root.Elements ()) {
  825. string dir = project.Attribute ("dir").Value;
  826. string library = project.Attribute ("library").Value;
  827. var profile = project.Element ("profile").Value;
  828. //
  829. // Do only class libraries for now
  830. //
  831. if (!(dir.StartsWith ("class") || dir.StartsWith ("mcs") || dir.StartsWith ("basic")))
  832. continue;
  833. //
  834. // Do not do 2.1, it is not working yet
  835. // Do not do basic, as there is no point (requires a system mcs to be installed).
  836. //
  837. if (library.Contains ("moonlight") || library.Contains ("-basic") || library.EndsWith ("bootstrap") || library.Contains ("build"))
  838. continue;
  839. // The next ones are to make debugging easier for now
  840. if (profile == "basic")
  841. continue;
  842. if (profile != "net_4_5" || library.Contains ("tests"))
  843. continue;
  844. yield return project;
  845. }
  846. }
  847. static void Main (string [] args)
  848. {
  849. if (!File.Exists ("genproj.cs")) {
  850. Console.WriteLine ("This command must be executed from mono/msvc/scripts");
  851. Environment.Exit (1);
  852. }
  853. if (args.Length == 1 && args [0].ToLower ().Contains ("-h")) {
  854. Console.WriteLine ("Usage:");
  855. Console.WriteLine ("genproj.exe [visual_studio_release] [output_full_solutions]");
  856. Console.WriteLine ("If output_full_solutions is false, only the main System*.dll");
  857. Console.WriteLine (" assemblies (and dependencies) is included in the solution.");
  858. Console.WriteLine ("Example:");
  859. Console.WriteLine ("genproj.exe 2012 false");
  860. Console.WriteLine ("genproj.exe with no arguments is equivalent to 'genproj.exe 2012 true'");
  861. Environment.Exit (0);
  862. }
  863. var slnVersion = (args.Length > 0) ? args [0] : "2012";
  864. bool fullSolutions = (args.Length > 1) ? bool.Parse (args [1]) : true;
  865. var sln_gen = new SlnGenerator (slnVersion);
  866. var two_sln_gen = new SlnGenerator (slnVersion);
  867. var four_sln_gen = new SlnGenerator (slnVersion);
  868. var three_five_sln_gen = new SlnGenerator (slnVersion);
  869. var four_five_sln_gen = new SlnGenerator (slnVersion);
  870. var projects = new Dictionary<string,MsbuildGenerator> ();
  871. var duplicates = new List<string> ();
  872. foreach (var project in GetProjects ()) {
  873. var library_output = project.Element ("library_output").Value;
  874. projects [library_output] = new MsbuildGenerator (project);
  875. }
  876. foreach (var project in GetProjects ()){
  877. var library_output = project.Element ("library_output").Value;
  878. var gen = projects [library_output];
  879. try {
  880. var csproj = gen.Generate (projects);
  881. var csprojFilename = csproj.csProjFilename;
  882. if (!sln_gen.ContainsProjectIdentifier (csproj.library)) {
  883. sln_gen.Add (csproj);
  884. } else {
  885. duplicates.Add (csprojFilename);
  886. }
  887. } catch (Exception e) {
  888. Console.WriteLine ("Error in {0}\n{1}", project, e);
  889. }
  890. }
  891. Func<MsbuildGenerator.VsCsproj, bool> additionalFilter;
  892. additionalFilter = fullSolutions ? (Func<MsbuildGenerator.VsCsproj, bool>)null : IsCommonLibrary;
  893. FillSolution (two_sln_gen, MsbuildGenerator.profile_2_0, projects.Values, additionalFilter);
  894. FillSolution (four_five_sln_gen, MsbuildGenerator.profile_4_5, projects.Values, additionalFilter);
  895. FillSolution (four_sln_gen, MsbuildGenerator.profile_4_0, projects.Values, additionalFilter);
  896. FillSolution (three_five_sln_gen, MsbuildGenerator.profile_3_5, projects.Values, additionalFilter);
  897. var sb = new StringBuilder ();
  898. sb.AppendLine ("WARNING: Skipped some project references, apparent duplicates in order.xml:");
  899. foreach (var item in duplicates) {
  900. sb.AppendLine (item);
  901. }
  902. Console.WriteLine (sb.ToString ());
  903. WriteSolution (two_sln_gen, MakeSolutionName (MsbuildGenerator.profile_2_0));
  904. WriteSolution (three_five_sln_gen, MakeSolutionName (MsbuildGenerator.profile_3_5));
  905. WriteSolution (four_sln_gen, MakeSolutionName (MsbuildGenerator.profile_4_0));
  906. WriteSolution (four_five_sln_gen, MakeSolutionName (MsbuildGenerator.profile_4_5));
  907. // A few other optional solutions
  908. // Solutions with 'everything' and the most common libraries used in development may be of interest
  909. //WriteSolution (sln_gen, "mcs_full.sln");
  910. //WriteSolution (small_full_sln_gen, "small_full.sln");
  911. // The following may be useful if lacking visual studio or MonoDevelop, to bootstrap mono compiler self-hosting
  912. //WriteSolution (basic_sln_gen, "mcs_basic.sln");
  913. //WriteSolution (build_sln_gen, "mcs_build.sln");
  914. }
  915. static string MakeSolutionName (string profileTag)
  916. {
  917. return "net" + profileTag + ".sln";
  918. }
  919. static void FillSolution (SlnGenerator solution, string profileString, IEnumerable<MsbuildGenerator> projects, Func<MsbuildGenerator.VsCsproj, bool> additionalFilter = null)
  920. {
  921. foreach (var generator in projects) {
  922. var vsCsproj = generator.Csproj;
  923. if (!vsCsproj.library.Contains (profileString))
  924. continue;
  925. if (additionalFilter != null && !additionalFilter (vsCsproj))
  926. continue;
  927. var csprojFilename = vsCsproj.csProjFilename;
  928. if (!solution.ContainsProjectIdentifier (vsCsproj.library)) {
  929. solution.Add (vsCsproj);
  930. RecursiveAddProj (solution, vsCsproj);
  931. }
  932. }
  933. }
  934. static void RecursiveAddProj (SlnGenerator solution, MsbuildGenerator.VsCsproj vsCsproj, int recursiveDepth = 1)
  935. {
  936. const int max_recursive = 16;
  937. if (recursiveDepth > max_recursive) throw new Exception (string.Format ("Reached {0} levels of project dependency", max_recursive));
  938. foreach (var projRef in vsCsproj.projReferences) {
  939. if (!solution.ContainsProjectIdentifier (projRef.library)) {
  940. solution.Add (projRef);
  941. RecursiveAddProj (solution, projRef, recursiveDepth + 1);
  942. }
  943. }
  944. }
  945. static void WriteSolution (SlnGenerator sln_gen, string slnfilename)
  946. {
  947. Console.WriteLine (String.Format ("Writing solution {1}, with {0} projects", sln_gen.Count, slnfilename));
  948. sln_gen.Write (slnfilename);
  949. }
  950. static bool IsCommonLibrary (MsbuildGenerator.VsCsproj proj)
  951. {
  952. var library = proj.library;
  953. //if (library.Contains ("-basic"))
  954. // return true;
  955. //if (library.Contains ("-build"))
  956. // return true;
  957. //if (library.StartsWith ("corlib"))
  958. // return true;
  959. if (library.StartsWith ("System-"))
  960. return true;
  961. if (library.StartsWith ("System.Xml"))
  962. return true;
  963. if (library.StartsWith ("System.Secu"))
  964. return true;
  965. if (library.StartsWith ("System.Configuration"))
  966. return true;
  967. if (library.StartsWith ("System.Core"))
  968. return true;
  969. //if (library.StartsWith ("Mono."))
  970. // return true;
  971. return false;
  972. }
  973. }