[Mono-list] Write & Compile

Scott Blomfield scott.blomfield@fstcredit.com
Fri, 7 Feb 2003 12:30:24 -0600


This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

------_=_NextPart_000_01C2CED6.FB002890
Content-Type: text/plain

>> > How can I compile a vb.net solution in mono?
>>
>> Some weeks ago, someone contributed a package that would convert the 
>> solution.
>> 
>
>Do you mean convert it to C#? In that case where can I get this package?
>
>Regards,
> - Levi

I think he was referring to the 01/03/2003 email from Jarek about converting
VS.NET solutions to makefiles. Original email below. File attached.



Original Email
--------
From: Jaroslaw Kowalski [jarek@atm.com.pl]
To: mono-list@ximian.com
Date: 01/03/2003
Subject: Re: Dealing with csproj files was Re: [mono-list] Compiling C#
cc...

I have created a tool (attached) that converts VS.NET solutions to
Makefiles. It's quick and dirty, definitely not finished but works for me by
generating Windows makefiles from SLN (solution) files. Unix makefiles
should work too. Windows makefiles are for nmake and unix makefiles are for
GNU make.

You feed it with the name of solution file (.sln) and some options and it
prints out the makefile to stdout.

The options are:

-u    generate Unix version of the makefile (slashes instead of backslashes)
-w    generate Windows version
-c    don't generate "all" and "clean" targets
-t    don't generate project targets (i.e. targets named after project
names)
-f    don't generate default values for CSC and CSCFLAGS.

For each project in the solution it generates the following (so you need to
specify TARGET) when making:

PROJECT_NAME_EXE=$(TARGET)/ProjectName.exe
PROJECT_NAME_PDB=$(TARGET)/ProjectName.pdb
PROJECT_NAME_SRC=... source files that make up the project

plus the rule to compile it using $(CSC) as the compiler with $(CSCFLAGS) as
options to it. The rule contains dependencies on other DLLs in the solution.
Dependencies on DLLs not found in the solution are not written out. They are
instead just referenced.

The whole idea is to have the generated makefile included from some other
makefile, so you can just emit the rules to build projects, but nothing
else. Or you can just invoke make like this:

"make -f generated_makefile.mak CSC=mcs CSCFLAGS=--optimize TARGET=/tmp"

Feel free to work on this tool, make it a full-blown application. You may
also include it in mono/mcs if you like. The license is kind of BSD one.

Jarek


------_=_NextPart_000_01C2CED6.FB002890
Content-Type: application/octet-stream;
	name="Maker.cs"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="Maker.cs"

/*

This file is a part of SLNToMake.

Copyright (c) 2002, 2003 Jaroslaw Kowalski <jaak@polbox.com>
All rights reserved.

Redistribution and use in source and binary forms, with or without=20
modification, are permitted provided that the following conditions=20
are met:

* Redistributions of source code must retain the above copyright =
notice,=20
this list of conditions and the following disclaimer.=20

* Redistributions in binary form must reproduce the above copyright =
notice,
this list of conditions and the following disclaimer in the =
documentation
and/or other materials provided with the distribution.=20

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS =
IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
THE=20
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
PURPOSE=20
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS =
BE=20
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR=20
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR =
BUSINESS=20
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN =

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) =

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF=20
THE POSSIBILITY OF SUCH DAMAGE.
*/

using System;
using System.Xml;
using System.Collections;
using System.IO;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Reflection;

namespace SlnToMake
{
	class ProjectInfo
	{
		public readonly string name;
		public readonly string guid;
		public readonly string csprojpath;
		public string makename;
		public string makename_ext;
		public XmlDocument doc;
		public string assembly_name;
		public string src;

		public string ext_refs =3D "";
		public string switches =3D "";

		public ProjectInfo(string name, string guid, string csprojpath)
		{
			this.name =3D name;
			this.guid =3D guid;
			this.csprojpath =3D csprojpath;

			makename =3D name.Replace('.','_').ToUpper();
			makename_ext =3D makename + "_EXT";

			// convert backslashes to slashes
		=09
			csprojpath =3D csprojpath.Replace("\\", "/");

			doc =3D new XmlDocument();
			doc.Load(csprojpath);

			XmlElement settingsNode =3D =
(XmlElement)doc.SelectSingleNode("VisualStudioProject/CSHARP/Build/Setti=
ngs");

			switch (settingsNode.GetAttribute("OutputType"))
			{
				case "Library":
					makename_ext =3D makename + "_DLL";
					assembly_name =3D settingsNode.GetAttribute("AssemblyName") + =
".dll";
					switches +=3D " /target:library";
					break;

				case "Exe":
					makename_ext =3D makename + "_EXE";
					assembly_name =3D settingsNode.GetAttribute("AssemblyName") + =
".exe";
					switches +=3D " /target:exe";
					break;

				case "WinExe":
					makename_ext =3D makename + "_EXE";
					assembly_name =3D settingsNode.GetAttribute("AssemblyName") + =
".exe";
					switches +=3D " /target:winexe";
					break;

				default:
					throw new NotSupportedException("Unsupported OutputType: " + =
settingsNode.GetAttribute("OutputType"));
			=09
			}

			src =3D "";

			string basePath =3D Path.GetDirectoryName(csprojpath);

			foreach (XmlElement el in =
doc.SelectNodes("VisualStudioProject/CSHARP/Files/Include/File[@BuildAct=
ion=3D'Compile']"))
			{
				if (src !=3D "")
				{
					src +=3D " \\\n\t";
				};
				string s =3D String.Format(@"{0}{1}{2}", basePath, Maker.slash, =
el.GetAttribute("RelPath"));
				s =3D s.Replace("\\", "/");
				if (Maker.slash !=3D "/")
					s =3D s.Replace("/", Maker.slash);
				src +=3D s;
			=09
			}
		}
	}

	public class Maker
	{
		static Hashtable projNameInfo =3D new Hashtable();
		static Hashtable projGuidInfo =3D new Hashtable();
		public static string slash;
		public static bool unixMode =3D false;

		static void ParseSolution(string fname)
		{
			FileStream fis =3D new FileStream(fname,FileMode.Open, =
FileAccess.Read, FileShare.Read);
			StreamReader reader =3D new StreamReader(fis);
			Regex regex =3D new Regex(@"Project\(""\{(.*)\}""\) =3D ""(.*)"", =
""(.*)"", ""(\{.*\})""");

			while (true)
			{
				string s =3D reader.ReadLine();
				Match match;

				match =3D regex.Match(s);
				if (match.Success)
				{
					string projectName =3D match.Groups[2].Value;
					string csprojPath =3D match.Groups[3].Value;
					string projectGuid =3D match.Groups[4].Value;

					if (csprojPath.EndsWith(".csproj") && =
!csprojPath.StartsWith("http://"))
					{
						ProjectInfo pi =3D new ProjectInfo(projectName, projectGuid, =
csprojPath);

						projNameInfo[projectName] =3D pi;
						projGuidInfo[projectGuid] =3D pi;
					}
				};

				if (s.StartsWith("Global"))
				{
					break;
				};
			}
		}

		static int Usage()
		{
			Console.WriteLine("USAGE: SlnToMake.exe [-u (unix mode)|-w (windows =
mode)] [-t (no project targets)] filename.sln");
			return 1;
		}

		static int Main(string[] args)
		{
			int i =3D 0;
			bool noCommonTargets =3D false;
			bool noProjectTargets =3D false;
			bool noFlags =3D false;

			while (i < args.Length && args[i].StartsWith("-"))
			{
				switch (args[i][1])
				{
					case 'u':
						unixMode =3D true;
						i++;
						break;

					case 'w':
						unixMode =3D false;
						i++;
						break;

					case 'c':
						noCommonTargets =3D true;
						i++;
						break;

					case 't':
						noProjectTargets =3D true;
						i++;
						break;

					case 'f':
						noFlags =3D true;
						i++;
						break;

					default:
						return Usage();
				}
			}

			if (unixMode)
			{
				slash =3D "/";
			}
			else
			{
				slash =3D "\\";
			}

			if (i >=3D args.Length)
				return Usage();

			string sln =3D args[i];
			TextWriter makefile =3D null;

			makefile =3D Console.Out;

			try
			{
				string d =3D Path.GetDirectoryName(sln);
				if (d !=3D "")
					Directory.SetCurrentDirectory(d);
				ParseSolution(sln);

				if (unixMode)
				{
					makefile.WriteLine("ifndef TARGET");
					makefile.WriteLine("\terror You must provide TARGET when making");
					makefile.WriteLine("endif");
				}
				else
				{
					makefile.WriteLine("!if !defined(TARGET)");
					makefile.WriteLine("!error You must provide TARGET when making");
					makefile.WriteLine("!endif");
				}
				makefile.WriteLine();

				if (!noFlags)
				{
					if (unixMode)
					{
					}
					else
					{
						makefile.WriteLine("CSC=3Dcsc");
						makefile.WriteLine("CSCFLAGS=3D/nologo");
						makefile.WriteLine();
						makefile.WriteLine("!if defined(RELEASE)");
						makefile.WriteLine("CSCFLAGS=3D$(CSCFLAGS) /optimize+ /d:TRACE");
						makefile.WriteLine("!else");
						makefile.WriteLine("CSCFLAGS=3D$(CSCFLAGS) /debug+ =
/d:TRACE,DEBUG");
						makefile.WriteLine("!endif");
					}
					makefile.WriteLine();
				}
				else
				{
					makefile.WriteLine("!if !defined(CSC)");
					makefile.WriteLine("!error You must provide CSC when making");
					makefile.WriteLine("!endif");
					makefile.WriteLine();
				}

				foreach (ProjectInfo pi in projNameInfo.Values)
				{
					makefile.WriteLine("{0}=3D$(TARGET){1}{2}", pi.makename_ext, =
slash, pi.assembly_name);
					makefile.WriteLine("{0}_PDB=3D$(TARGET){1}{2}", pi.makename, =
slash, pi.assembly_name.Replace(".dll",".pdb"));
					makefile.WriteLine("{0}_SRC=3D{1}", pi.makename, pi.src);
					makefile.WriteLine();
				}

				foreach (ProjectInfo pi in projNameInfo.Values)
				{
					string refs =3D "";
					string deps =3D "";
					=09
					foreach (XmlElement el in =
pi.doc.SelectNodes("VisualStudioProject/CSHARP/Build/References/Referenc=
e"))
					{
						if (el.GetAttribute("Package") =3D=3D "")
						{
							if (refs !=3D "")
								refs +=3D " ";

							string assemblyName =3D el.GetAttribute("AssemblyName");

							// HACK - under Unix filenames are case sensitive
							// Under Windows there's no agreement on Xml vs XML ;-)
						=09
							if (0 =3D=3D String.Compare(assemblyName, "System.Xml", true))
							{
								assemblyName =3D "System.Xml";
							}
							refs +=3D "/r:" + assemblyName + ".dll";
						}
						else
						{
							ProjectInfo pi2 =3D =
(ProjectInfo)projGuidInfo[el.GetAttribute("Project")];

							if (refs !=3D "")
								refs +=3D " ";

							if (deps !=3D "")
								deps +=3D " ";

							refs +=3D "/r:$(" + pi2.makename_ext + ")";
							deps +=3D "$(" + pi2.makename_ext + ")";
						}
					}

					makefile.WriteLine("$({0}): $({1}_SRC) {2}", pi.makename_ext, =
pi.makename, deps);
					makefile.WriteLine("\t$(CSC) $(CSCFLAGS) {2}{3} /out:$({0}) =
$({1}_SRC)", pi.makename_ext, pi.makename, refs, pi.switches);
					makefile.WriteLine();
				}

				if (!noCommonTargets)
				{
					makefile.WriteLine();
					makefile.WriteLine("# common targets");
					makefile.WriteLine();
					makefile.Write("all:\t");

					bool first =3D true;

					foreach (ProjectInfo pi in projNameInfo.Values)
					{
						if (!first)
						{
							makefile.Write(" \\\n\t");
						};
						makefile.Write("$({0})", pi.makename_ext);
						first =3D false;
					}
					makefile.WriteLine();
					makefile.WriteLine();

					makefile.WriteLine("clean:");

					foreach (ProjectInfo pi in projNameInfo.Values)
					{
						if (unixMode)
						{
							makefile.WriteLine("\t-rm -f \"$({0})\" 2> /dev/null", =
pi.makename_ext);
							makefile.WriteLine("\t-rm -f \"$({0}_PDB)\" 2> /dev/null", =
pi.makename);
						}
						else
						{
							makefile.WriteLine("\t-del \"$({0})\" 2> nul", pi.makename_ext);
							makefile.WriteLine("\t-del \"$({0}_PDB)\" 2> nul", pi.makename);
						}
					}
					makefile.WriteLine();
				}

				if (!noProjectTargets)
				{
					makefile.WriteLine();
					makefile.WriteLine("# project names as targets");
					makefile.WriteLine();
					foreach (ProjectInfo pi in projNameInfo.Values)
					{
						makefile.WriteLine("{0}: $({1})", pi.name, pi.makename_ext);
					}
				}
				return 0;
			}
			catch (Exception e)
			{
				Console.WriteLine("EXCEPTION: {0}", e);
				return 1;
			};
		}
	}
}

------_=_NextPart_000_01C2CED6.FB002890--