singrdk/base/Windows/nmake_dirs/NMakeDirs.cs

196 lines
6.0 KiB
C#

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Text;
class NMakeDirs
{
const string NMakeProgram = "nmake.exe";
const string RunParallelProgram = "runparallel.exe";
const string DrainMarker = "+DRAIN";
static int Main(string[] args)
{
try
{
ArrayList dirs = new ArrayList();
int dir_count = 0; // this count excludes drain markers
bool parallel = false;
string nmake_args = "/nologo ";
for (int i = 0; i < args.Length; i++)
{
string arg = args[i];
if (arg.Length == 0)
continue;
if (arg.StartsWith("/"))
{
arg = arg.ToLower();
if (arg == "/nmake")
{
// The rest of the arguments are for NMAKE.
i++;
nmake_args = nmake_args + String.Join(" ", args, i, args.Length - i);
break;
}
else if (arg == "/p")
{
parallel = true;
}
else if (arg == "/?")
{
Usage();
return 0;
}
else
{
WriteLine("WARNING: Unrecognized switch: " + arg);
}
}
else
{
dirs.Add(arg);
if (String.Compare(arg, DrainMarker, true) != 0)
dir_count++;
}
}
if (dir_count == 0)
{
Usage();
return 1;
}
if (parallel)
{
WriteLine("Building {0} dirs in parallel.", dir_count);
using (Process process = new Process())
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.FileName = RunParallelProgram;
process.StartInfo.Arguments = "/stdin";
process.Start();
TextWriter pipe = process.StandardInput;
foreach (string dir in dirs)
{
if (String.Compare(dir, DrainMarker, true) == 0)
{
pipe.WriteLine(dir);
continue;
}
string line = String.Format("cd \"{0}\" && " + NMakeProgram + " {1}", dir, nmake_args);
// WriteLine(" cmd - " + line);
pipe.WriteLine(line);
}
pipe.Close();
process.WaitForExit();
if (process.ExitCode != 0)
{
WriteLine("RUNPARALLEL failed: " + process.ExitCode);
return process.ExitCode;
}
return 0;
}
}
else
{
WriteLine("Building {0} dirs serially.", dir_count);
string initial_directory = Environment.CurrentDirectory;
foreach (string dir in dirs)
{
if (String.Compare(dir, DrainMarker, true) == 0)
continue;
string path = Path.Combine(initial_directory, dir);
WriteLine("building dir - " + path);
using (Process process = new Process())
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = NMakeProgram;
process.StartInfo.Arguments = nmake_args;
process.StartInfo.WorkingDirectory = dir;
process.Start();
process.WaitForExit();
if (process.ExitCode != 0)
{
WriteLine("[{0} NMAKE failed: {1}", dir, process.ExitCode);
return process.ExitCode;
}
}
}
return 0;
}
}
catch (Exception ex)
{
ShowException(ex);
return 1;
}
}
static void WriteLine(string line)
{
Console.WriteLine(Prefix + line);
}
static void WriteLine(string format, params object[] args)
{
WriteLine(String.Format(format, args));
}
const string Prefix = "NMAKE_DIRS: ";
static void Usage()
{
Console.WriteLine("Usage: nmake_dirs [/p] dir1 dir2 ... dirN [/nmake args to nmake.exe]");
Console.WriteLine();
Console.WriteLine(" /p Enables parallel builds of subdirectories.");
Console.WriteLine(" /nmake All args following /nmake are passed to nmake.exe.");
}
static void ShowException(Exception chain)
{
for (Exception ex = chain; ex != null; ex = ex.InnerException)
{
Console.WriteLine(ex.GetType().FullName + ": " + ex.Message);
}
}
static string RemoveQuotes(string str)
{
str = str.Trim();
if (str.StartsWith("\"") && str.EndsWith("\""))
return str.Substring(1, str.Length - 2);
return str;
}
}