diff --git a/KoreBuild-dotnet/KoreBuild-dotnet.nuspec b/KoreBuild-dotnet/KoreBuild-dotnet.nuspec
new file mode 100644
index 0000000000..874c8947c3
--- /dev/null
+++ b/KoreBuild-dotnet/KoreBuild-dotnet.nuspec
@@ -0,0 +1,15 @@
+
+
+
+ KoreBuild-dotnet
+ The ProjectK build tools
+ 0.0
+ .NET Foundation
+ .NET Foundation
+ ProjectK build tooling
+ en-US
+
+
+
+
+
\ No newline at end of file
diff --git a/KoreBuild-dotnet/build/BuildEnv.shade b/KoreBuild-dotnet/build/BuildEnv.shade
new file mode 100644
index 0000000000..6876084123
--- /dev/null
+++ b/KoreBuild-dotnet/build/BuildEnv.shade
@@ -0,0 +1,36 @@
+use namespace="System"
+
+functions
+ @{
+ string CreateDayBasedVersionNumber()
+ {
+ var start = new DateTime(2015, 1, 1);
+ var now = DateTime.UtcNow;
+
+ string version = "0";
+ // If the computer date is set before the start date, then the version is 0
+ if (now >= start)
+ {
+ var yearsSinceStart = (now.Year - start.Year) + 1;
+ version = yearsSinceStart + now.ToString("MMdd");
+ }
+
+ return version;
+ }
+
+ string BuildNumber
+ {
+ get
+ {
+ return "t" + DateTime.UtcNow.ToString("yyMMddHHmmss");
+ }
+ }
+
+ bool IsBuildV2
+ {
+ get
+ {
+ return Environment.GetEnvironmentVariable("KOREBUILD_BUILD_V2") == "1";
+ }
+ }
+ }
\ No newline at end of file
diff --git a/KoreBuild-dotnet/build/Json.shade b/KoreBuild-dotnet/build/Json.shade
new file mode 100644
index 0000000000..c16cbacd17
--- /dev/null
+++ b/KoreBuild-dotnet/build/Json.shade
@@ -0,0 +1,883 @@
+use namespace='System'
+use namespace='System.Collections.Generic'
+use namespace='System.Globalization'
+use namespace='System.IO'
+use namespace='System.Text'
+
+functions @{
+ public class JsonArray : JsonValue
+ {
+ private readonly JsonValue[] _array;
+
+ public JsonArray(JsonValue[] array, int line, int column)
+ : base(line, column)
+ {
+ if (array == null)
+ {
+ throw new ArgumentNullException("array");
+ }
+
+ _array = array;
+ }
+
+ public int Length { get { return _array.Length; } }
+ public IEnumerable Values { get { return _array; }}
+ public JsonValue this[int index] { get { return _array[index]; }}
+ }
+
+ public class JsonBoolean : JsonValue
+ {
+ public JsonBoolean(JsonToken token)
+ : base(token.Line, token.Column)
+ {
+ if (token.Type == JsonTokenType.True)
+ {
+ Value = true;
+ }
+ else if (token.Type == JsonTokenType.False)
+ {
+ Value = false;
+ }
+ else
+ {
+ throw new ArgumentException("Token value should be either True or False.", "token");
+ }
+ }
+
+ public bool Value { get; private set; }
+
+ public static implicit operator bool (JsonBoolean jsonBoolean)
+ {
+ return jsonBoolean.Value;
+ }
+ }
+
+ public class JsonString : JsonValue
+ {
+ private readonly string _value;
+
+ public JsonString(string value, int line, int column)
+ : base(line, column)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ _value = value;
+ }
+
+ public string Value
+ {
+ get { return _value; }
+ }
+
+ public override string ToString()
+ {
+ return _value;
+ }
+
+ public static implicit operator string (JsonString instance)
+ {
+ if (instance == null)
+ {
+ return null;
+ }
+ else
+ {
+ return instance.Value;
+ }
+ }
+ }
+
+ public class JsonNull : JsonValue
+ {
+ public JsonNull(int line, int column)
+ : base(line, column)
+ {
+ }
+ }
+
+ public class JsonValue
+ {
+ public JsonValue(int line, int column)
+ {
+ Line = line;
+ Column = column;
+ }
+
+ public int Line { get; private set; }
+
+ public int Column { get; private set; }
+ }
+
+ public class JsonObject : JsonValue
+ {
+ private readonly IDictionary _data;
+
+ public JsonObject(IDictionary data, int line, int column)
+ : base(line, column)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ _data = data;
+ }
+
+ public ICollection Keys
+ {
+ get { return _data.Keys; }
+ }
+
+ public JsonValue Value(string key)
+ {
+ JsonValue result;
+ if (!_data.TryGetValue(key, out result))
+ {
+ result = null;
+ }
+
+ return result;
+ }
+
+ public JsonObject ValueAsJsonObject(string key)
+ {
+ return Value(key) as JsonObject;
+ }
+
+ public JsonString ValueAsString(string key)
+ {
+ return Value(key) as JsonString;
+ }
+
+ public int ValueAsInt(string key)
+ {
+ var number = Value(key) as JsonNumber;
+ if (number == null)
+ {
+ throw new FormatException();
+ }
+ return Convert.ToInt32(number.Raw);
+ }
+
+ public bool ValueAsBoolean(string key, bool defaultValue = false)
+ {
+ var boolVal = Value(key) as JsonBoolean;
+ if (boolVal != null)
+ {
+ return boolVal.Value;
+ }
+
+ return defaultValue;
+ }
+
+ public bool? ValueAsNullableBoolean(string key)
+ {
+ var boolVal = Value(key) as JsonBoolean;
+ if (boolVal != null)
+ {
+ return boolVal.Value;
+ }
+
+ return null;
+ }
+
+ public string[] ValueAsStringArray(string key)
+ {
+ var list = Value(key) as JsonArray;
+ if (list == null)
+ {
+ return null;
+ }
+
+ var result = new string[list.Length];
+
+ for (int i = 0; i < list.Length; ++i)
+ {
+ var jsonString = list[i] as JsonString;
+ if (jsonString != null)
+ {
+ result[i] = jsonString.ToString();
+ }
+ }
+
+ return result;
+ }
+
+ internal object ValueAsJsonObject(object packIncludePropertyName)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class JsonNumber : JsonValue
+ {
+ private readonly string _raw;
+ private readonly double _double;
+
+ public JsonNumber(JsonToken token)
+ : base(token.Line, token.Column)
+ {
+ try
+ {
+ _raw = token.Value;
+ _double = double.Parse(_raw, NumberStyles.Float);
+ }
+ catch (FormatException ex)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_InvalidFloatNumberFormat(_raw),
+ ex,
+ token.Line,
+ token.Column);
+ }
+ catch (OverflowException ex)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_FloatNumberOverflow(_raw),
+ ex,
+ token.Line,
+ token.Column);
+ }
+ }
+
+ public double Double
+ {
+ get { return _double; }
+ }
+
+ public string Raw
+ {
+ get { return _raw; }
+ }
+ }
+
+ public static class Json
+ {
+ public static JsonValue Deserialize(string content)
+ {
+ using (var reader = new StringReader(content))
+ {
+ return Deserialize(reader);
+ }
+ }
+
+ public static JsonValue Deserialize(TextReader reader)
+ {
+ if (reader == null)
+ {
+ throw new ArgumentNullException("reader");
+ }
+
+ var buffer = new JsonBuffer(reader);
+
+ var result = DeserializeInternal(buffer.Read(), buffer);
+
+ // There are still unprocessed char. The parsing is not finished. Error happened.
+ var nextToken = buffer.Read();
+ if (nextToken.Type != JsonTokenType.EOF)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_UnfinishedJSON(nextToken.Value),
+ nextToken);
+ }
+
+ return result;
+ }
+
+ private static JsonValue DeserializeInternal(JsonToken next, JsonBuffer buffer)
+ {
+ if (next.Type == JsonTokenType.EOF)
+ {
+ return null;
+ }
+
+ if (next.Type == JsonTokenType.LeftSquareBracket)
+ {
+ return DeserializeArray(next, buffer);
+ }
+
+ if (next.Type == JsonTokenType.LeftCurlyBracket)
+ {
+ return DeserializeObject(next, buffer);
+ }
+
+ if (next.Type == JsonTokenType.String)
+ {
+ return new JsonString(next.Value, next.Line, next.Column);
+ }
+
+ if (next.Type == JsonTokenType.True || next.Type == JsonTokenType.False)
+ {
+ return new JsonBoolean(next);
+ }
+
+ if (next.Type == JsonTokenType.Null)
+ {
+ return new JsonNull(next.Line, next.Column);
+ }
+
+ if (next.Type == JsonTokenType.Number)
+ {
+ return new JsonNumber(next);
+ }
+
+ throw new JsonDeserializerException(JsonDeserializerResource.Format_InvalidTokenExpectation(
+ next.Value, "'{', (char)'[', true, false, null, JSON string, JSON number, or the end of the file"),
+ next);
+ }
+
+ private static JsonArray DeserializeArray(JsonToken head, JsonBuffer buffer)
+ {
+ var list = new List();
+ while (true)
+ {
+ var next = buffer.Read();
+ if (next.Type == JsonTokenType.RightSquareBracket)
+ {
+ break;
+ }
+
+ list.Add(DeserializeInternal(next, buffer));
+
+ next = buffer.Read();
+ if (next.Type == JsonTokenType.EOF)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_InvalidSyntaxExpectation("JSON array", (char)']', (char)','),
+ next);
+ }
+ else if (next.Type == JsonTokenType.RightSquareBracket)
+ {
+ break;
+ }
+ else if (next.Type != JsonTokenType.Comma)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_InvalidSyntaxExpectation("JSON array", (char)','),
+ next);
+ }
+ }
+
+ return new JsonArray(list.ToArray(), head.Line, head.Column);
+ }
+
+ private static JsonObject DeserializeObject(JsonToken head, JsonBuffer buffer)
+ {
+ var dictionary = new Dictionary();
+
+ // Loop through each JSON entry in the input object
+ while (true)
+ {
+ var next = buffer.Read();
+ if (next.Type == JsonTokenType.EOF)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_InvalidSyntaxExpectation("JSON object", (char)'}'),
+ next);
+ }
+
+ if (next.Type == JsonTokenType.Colon)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_InvalidSyntaxNotExpected("JSON object", (char)':'),
+ next);
+ }
+ else if (next.Type == JsonTokenType.RightCurlyBracket)
+ {
+ break;
+ }
+ else
+ {
+ if (next.Type != JsonTokenType.String)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_InvalidSyntaxExpectation("JSON object member name", "JSON string"),
+ next);
+ }
+
+ var memberName = next.Value;
+ if (dictionary.ContainsKey(memberName))
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_DuplicateObjectMemberName(memberName),
+ next);
+ }
+
+ next = buffer.Read();
+ if (next.Type != JsonTokenType.Colon)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_InvalidSyntaxExpectation("JSON object", (char)':'),
+ next);
+ }
+
+ dictionary[memberName] = DeserializeInternal(buffer.Read(), buffer);
+
+ next = buffer.Read();
+ if (next.Type == JsonTokenType.RightCurlyBracket)
+ {
+ break;
+ }
+ else if (next.Type != JsonTokenType.Comma)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_InvalidSyntaxExpectation("JSON object", (char)',', (char)'}'),
+ next);
+ }
+ }
+ }
+
+ return new JsonObject(dictionary, head.Line, head.Column);
+ }
+ }
+
+ internal class JsonBuffer
+ {
+ public const string ValueNull = "null";
+ public const string ValueTrue = "true";
+ public const string ValueFalse = "false";
+
+ private readonly StringBuilder _buffer = new StringBuilder();
+ private readonly StringBuilder _codePointBuffer = new StringBuilder(4);
+ private readonly TextReader _reader;
+ private JsonToken _token;
+ private int _line;
+ private int _column;
+
+ public JsonBuffer(TextReader reader)
+ {
+ _reader = reader;
+ _line = 1;
+ }
+
+ public JsonToken Read()
+ {
+ int first;
+ while (true)
+ {
+ first = ReadNextChar();
+
+ if (first == -1)
+ {
+ _token.Type = JsonTokenType.EOF;
+ return _token;
+ }
+ else if (!IsWhitespace(first))
+ {
+ break;
+ }
+ }
+
+ _token.Value = ((char)first).ToString();
+ _token.Line = _line;
+ _token.Column = _column;
+
+ if (first == (char)'{')
+ {
+ _token.Type = JsonTokenType.LeftCurlyBracket;
+ }
+ else if (first == (char)'}')
+ {
+ _token.Type = JsonTokenType.RightCurlyBracket;
+ }
+ else if (first == (char)'[')
+ {
+ _token.Type = JsonTokenType.LeftSquareBracket;
+ }
+ else if (first == (char)']')
+ {
+ _token.Type = JsonTokenType.RightSquareBracket;
+ }
+ else if (first == (char)':')
+ {
+ _token.Type = JsonTokenType.Colon;
+ }
+ else if (first == (char)',')
+ {
+ _token.Type = JsonTokenType.Comma;
+ }
+ else if (first == (char)'"')
+ {
+ _token.Type = JsonTokenType.String;
+ _token.Value = ReadString();
+ }
+ else if (first == (char)'t')
+ {
+ ReadLiteral(ValueTrue);
+ _token.Type = JsonTokenType.True;
+ }
+ else if (first == (char)'f')
+ {
+ ReadLiteral(ValueFalse);
+ _token.Type = JsonTokenType.False;
+ }
+ else if (first == (char)'n')
+ {
+ ReadLiteral(ValueNull);
+ _token.Type = JsonTokenType.Null;
+ }
+ else if ((first >= (char)'0' && first <= (char)'9') || first == (char)'-')
+ {
+ _token.Type = JsonTokenType.Number;
+ _token.Value = ReadNumber(first);
+ }
+ else
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_IllegalCharacter(first),
+ _token);
+ }
+
+ // JsonToken is a value type
+ return _token;
+ }
+
+ private int ReadNextChar()
+ {
+ while (true)
+ {
+ var value = _reader.Read();
+ _column++;
+
+ if (value == -1)
+ {
+ // This is the end of file
+ return -1;
+ }
+ else if (value == (char)'\n')
+ {
+ // This is a new line. Let the next loop read the first charactor of the following line.
+ // Set position ahead of next line
+ _column = 0;
+ _line++;
+
+ continue;
+ }
+ else if (value == (char)'\r')
+ {
+ // Skip the carriage return.
+ // Let the next loop read the following char
+ }
+ else
+ {
+ // Returns the normal value
+ return value;
+ }
+ }
+ }
+
+ private string ReadNumber(int firstRead)
+ {
+ _buffer.Clear();
+ _buffer.Append((char)firstRead);
+
+ while (true)
+ {
+ var next = _reader.Peek();
+
+ if ((next >= (char)'0' && next <= (char)'9') ||
+ next == (char)'.' ||
+ next == (char)'e' ||
+ next == (char)'E')
+ {
+ _buffer.Append((char)ReadNextChar());
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return _buffer.ToString();
+ }
+
+ private void ReadLiteral(string literal)
+ {
+ for (int i = 1; i < literal.Length; ++i)
+ {
+ var next = _reader.Peek();
+ if (next != literal[i])
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_UnrecognizedLiteral(literal),
+ _line, _column);
+ }
+ else
+ {
+ ReadNextChar();
+ }
+ }
+
+ var tail = _reader.Peek();
+ if (tail != (char)'}' &&
+ tail != (char)']' &&
+ tail != (char)',' &&
+ tail != (char)'\n' &&
+ tail != -1 &&
+ !IsWhitespace(tail))
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_IllegalTrailingCharacterAfterLiteral(tail, literal),
+ _line, _column);
+ }
+ }
+
+ private string ReadString()
+ {
+ _buffer.Clear();
+ var escaped = false;
+
+ while (true)
+ {
+ var next = ReadNextChar();
+
+ if (next == -1 || next == (char)'\n')
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.JSON_OpenString,
+ _line, _column);
+ }
+ else if (escaped)
+ {
+ if ((next == (char)'"') || (next == (char)'\\') || (next == (char)'/'))
+ {
+ _buffer.Append((char)next);
+ }
+ else if (next == (char)'b')
+ {
+ // (char)'\b' backspace
+ _buffer.Append('\b');
+ }
+ else if (next == (char)'f')
+ {
+ // (char)'\f' form feed
+ _buffer.Append('\f');
+ }
+ else if (next == (char)'n')
+ {
+ // (char)'\n' line feed
+ _buffer.Append('\n');
+ }
+ else if (next == (char)'r')
+ {
+ // (char)'\r' carriage return
+ _buffer.Append('\r');
+ }
+ else if (next == (char)'t')
+ {
+ // (char)'\t' tab
+ _buffer.Append('\t');
+ }
+ else if (next == (char)'u')
+ {
+ // (char)'\uXXXX' unicode
+ var unicodeLine = _line;
+ var unicodeColumn = _column;
+
+ _codePointBuffer.Clear();
+ for (int i = 0; i < 4; ++i)
+ {
+ next = ReadNextChar();
+ if (next == -1)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.JSON_InvalidEnd,
+ unicodeLine,
+ unicodeColumn);
+ }
+ else
+ {
+ _codePointBuffer[i] = (char)next;
+ }
+ }
+
+ try
+ {
+ var unicodeValue = int.Parse(_codePointBuffer.ToString(), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+ _buffer.Append((char)unicodeValue);
+ }
+ catch (FormatException ex)
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_InvalidUnicode(_codePointBuffer.ToString()),
+ ex,
+ unicodeLine,
+ unicodeColumn);
+ }
+ }
+ else
+ {
+ throw new JsonDeserializerException(
+ JsonDeserializerResource.Format_InvalidSyntaxNotExpected("charactor escape", "\\" + next),
+ _line,
+ _column);
+ }
+
+ escaped = false;
+ }
+ else if (next == (char)'\\')
+ {
+ escaped = true;
+ }
+ else if (next == (char)'"')
+ {
+ break;
+ }
+ else
+ {
+ _buffer.Append((char)next);
+ }
+ }
+
+ return _buffer.ToString();
+ }
+
+ private static bool IsWhitespace(int value)
+ {
+ return value == (char)' ' || value == (char)'\t' || value == (char)'\r';
+ }
+ }
+
+ public enum JsonTokenType
+ {
+ LeftCurlyBracket, // [
+ LeftSquareBracket, // {
+ RightCurlyBracket, // ]
+ RightSquareBracket, // }
+ Colon, // :
+ Comma, // ,
+ Null,
+ True,
+ False,
+ Number,
+ String,
+ EOF
+ }
+
+ public struct JsonToken
+ {
+ public JsonTokenType Type;
+ public string Value;
+ public int Line;
+ public int Column;
+ }
+
+ public class JsonDeserializerException : Exception
+ {
+ public JsonDeserializerException(string message, Exception innerException, int line, int column)
+ : base(message, innerException)
+ {
+ Line = line;
+ Column = column;
+ }
+
+ public JsonDeserializerException(string message, int line, int column)
+ : base(message)
+ {
+ Line = line;
+ Column = column;
+ }
+
+ public JsonDeserializerException(string message, JsonToken nextToken)
+ : base(message)
+ {
+ Line = nextToken.Line;
+ Column = nextToken.Column;
+ }
+
+ public int Line { get; private set; }
+
+ public int Column { get; private set; }
+ }
+
+ internal class JsonDeserializerResource
+ {
+ internal static string Format_IllegalCharacter(int value)
+ {
+ return string.Format("Illegal character (char)'{0}' (Unicode hexadecimal {0:X4}).", value);
+ }
+
+ internal static string Format_IllegalTrailingCharacterAfterLiteral(int value, string literal)
+ {
+ return string.Format("Illegal character(char)'{0}'(Unicode hexadecimal { 0:X4}) after the literal name (char)'{1}'.", value, literal);
+ }
+
+ internal static string Format_UnrecognizedLiteral(string literal)
+ {
+ return string.Format("Invalid JSON literal.Expected literal(char)'{0}'.", literal);
+ }
+
+ internal static string Format_DuplicateObjectMemberName(string memberName)
+ {
+ return Format_InvalidSyntax("JSON object", string.Format("Duplicate member name(char)'{0}'", memberName));
+ }
+
+ internal static string Format_InvalidFloatNumberFormat(string raw)
+ {
+ return string.Format("Invalid float number format: {0}", raw);
+ }
+
+ internal static string Format_FloatNumberOverflow(string raw)
+ {
+ return string.Format("Float number overflow: {0}", raw);
+ }
+
+ internal static string Format_InvalidSyntax(string syntaxName, string issue)
+ {
+ return string.Format("Invalid {0}syntax. {1}.", syntaxName, issue);
+ }
+
+ internal static string Format_InvalidSyntaxNotExpected(string syntaxName, char unexpected)
+ {
+ return string.Format("Invalid {0} syntax.Unexpected(char)'{1}'.", syntaxName, unexpected);
+ }
+
+ internal static string Format_InvalidSyntaxNotExpected(string syntaxName, string unexpected)
+ {
+ return string.Format("Invalid {0} syntax.Unexpected { 1}.", syntaxName, unexpected);
+ }
+
+ internal static string Format_InvalidSyntaxExpectation(string syntaxName, char expectation)
+ {
+ return string.Format("Invalid {0} syntax.Expected(char)'{1}'.", syntaxName, expectation);
+ }
+
+ internal static string Format_InvalidSyntaxExpectation(string syntaxName, string expectation)
+ {
+ return string.Format("Invalid {0} syntax.Expected {1}.", syntaxName, expectation);
+ }
+
+ internal static string Format_InvalidSyntaxExpectation(string syntaxName, char expectation1, char expectation2)
+ {
+ return string.Format("Invalid {0} syntax.Expected(char)'{1}' or(char)'{2}'.", syntaxName, expectation1, expectation2);
+ }
+
+ internal static string Format_InvalidTokenExpectation(string tokenValue, string expectation)
+ {
+ return string.Format("Unexpected token(char)'{0}'.Expected {1}.", tokenValue, expectation);
+ }
+
+ internal static string Format_InvalidUnicode(string unicode)
+ {
+ return string.Format("Invalid Unicode[{0}]", unicode);
+ }
+
+ internal static string Format_UnfinishedJSON(string nextTokenValue)
+ {
+ return string.Format("Invalid JSON end.Unprocessed token {0}.", nextTokenValue);
+ }
+
+ internal static string JSON_OpenString
+ {
+ get { return Format_InvalidSyntaxExpectation("JSON string", (char)'\"'); }
+ }
+
+ internal static string JSON_InvalidEnd
+ {
+ get { return "Invalid JSON. Unexpected end of file."; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/KoreBuild-dotnet/build/Resources.cs b/KoreBuild-dotnet/build/Resources.cs
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/KoreBuild-dotnet/build/Resources.tt b/KoreBuild-dotnet/build/Resources.tt
new file mode 100644
index 0000000000..f6b0355d1d
--- /dev/null
+++ b/KoreBuild-dotnet/build/Resources.tt
@@ -0,0 +1,195 @@
+<#@ template debug="true" hostspecific="true" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ assembly name="System.Windows.Forms" #>
+<#@ assembly name="Microsoft.VisualStudio.Shell.Interop.8.0" #>
+<#@ assembly name="EnvDTE" #>
+<#@ assembly name="EnvDTE80" #>
+<#@ import namespace="System" #>
+<#@ import namespace="System.Collections" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ import namespace="System.IO" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Resources" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Text.RegularExpressions" #>
+<#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #>
+<#@ import namespace="EnvDTE" #>
+<#@ import namespace="EnvDTE80" #>
+<#
+ var hostServiceProvider = (IServiceProvider)Host;
+ var dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE));
+ var templateProjectItem = dte.Solution.FindProjectItem(Host.TemplateFile);
+ var projectDirectory = Path.GetDirectoryName(templateProjectItem.ContainingProject.FullName);
+ var ttDirectory = Path.Combine(projectDirectory, "Properties");
+ var projectNamespace = templateProjectItem.ContainingProject.Properties.Item("DefaultNamespace").Value;
+ var projectName = Path.GetFileName(projectDirectory.TrimEnd('/'));
+ var namedParameterMatcher = new Regex(@"\{([a-z]\w+)\}", RegexOptions.IgnoreCase);
+ var numberParameterMatcher = new Regex(@"\{(\d+)\}");
+
+ foreach (var resxFile in Directory.EnumerateFiles(projectDirectory, "*.resx", SearchOption.AllDirectories))
+ {
+ var fileName = Path.GetFileNameWithoutExtension(resxFile);
+ var resourceStrings = new List();
+
+ using (var resxReader = new ResXResourceReader(resxFile))
+ {
+ resxReader.UseResXDataNodes = true;
+
+ foreach (DictionaryEntry entry in resxReader)
+ {
+ var node = (ResXDataNode)entry.Value;
+ var value = (string)node.GetValue((System.ComponentModel.Design.ITypeResolutionService)null);
+
+ bool usingNamedArgs = true;
+ var match = namedParameterMatcher.Matches(value);
+ if (match.Count == 0)
+ {
+ usingNamedArgs = false;
+ match = numberParameterMatcher.Matches(value);
+ }
+
+ var arguments = match.Cast()
+ .Select(m => m.Groups[1].Value)
+ .Distinct();
+ if (!usingNamedArgs)
+ {
+ arguments = arguments.OrderBy(Convert.ToInt32);
+ }
+
+ resourceStrings.Add(
+ new ResourceData
+ {
+ Name = node.Name,
+ Value = value,
+ Arguments = arguments.ToList(),
+ UsingNamedArgs = usingNamedArgs
+ });
+ }
+ }
+
+ GenerationEnvironment.AppendFormat(
+@"//
+namespace {0}
+{{
+ using System.Globalization;
+ using System.Reflection;
+ using System.Resources;
+
+ internal static class {2}
+ {{
+ private static readonly ResourceManager _resourceManager
+ = new ResourceManager(""{1}.{2}"", typeof({2}).GetTypeInfo().Assembly);
+", projectNamespace, projectName, fileName);
+
+ foreach (var resourceString in resourceStrings)
+ {
+ GenerationEnvironment.AppendLine();
+ RenderHeader(GenerationEnvironment, resourceString);
+ RenderProperty(GenerationEnvironment, resourceString);
+
+ GenerationEnvironment.AppendLine();
+ RenderHeader(GenerationEnvironment, resourceString);
+ RenderFormatMethod(GenerationEnvironment, resourceString);
+ }
+
+ GenerationEnvironment.Append(@"
+ private static string GetString(string name, params string[] formatterNames)
+ {
+ var value = _resourceManager.GetString(name);
+
+ System.Diagnostics.Debug.Assert(value != null);
+
+ if (formatterNames != null)
+ {
+ for (var i = 0; i < formatterNames.Length; i++)
+ {
+ value = value.Replace(""{"" + formatterNames[i] + ""}"", ""{"" + i + ""}"");
+ }
+ }
+
+ return value;
+ }
+ }
+}
+");
+
+ var outputPath = Path.Combine(ttDirectory, fileName + ".Designer.cs");
+
+ File.WriteAllText(outputPath, GenerationEnvironment.ToString());
+ GenerationEnvironment.Length = 0;
+}
+#>
+<#+
+private static void RenderHeader(StringBuilder builder, ResourceData resourceString)
+{
+ builder.Append(" /// ")
+ .AppendLine();
+ foreach (var line in resourceString.Value.Split(new[] { Environment.NewLine }, StringSplitOptions.None))
+ {
+ builder.AppendFormat(" /// {0}", line.Replace("<", "<").Replace(">", ">"))
+ .AppendLine();
+ }
+ builder.Append(" /// ")
+ .AppendLine();
+}
+
+private static void RenderProperty(StringBuilder builder, ResourceData resourceString)
+{
+ builder.AppendFormat(" internal static string {0}", resourceString.Name)
+ .AppendLine()
+ .AppendLine(" {")
+ .AppendFormat(@" get {{ return GetString(""{0}""); }}", resourceString.Name)
+ .AppendLine()
+ .AppendLine(" }");
+}
+
+private static void RenderFormatMethod(StringBuilder builder, ResourceData resourceString)
+{
+ builder.AppendFormat(" internal static string Format{0}({1})", resourceString.Name, resourceString.Parameters)
+ .AppendLine()
+ .AppendLine(" {");
+ if(resourceString.Arguments.Count > 0)
+ {
+ builder.AppendFormat(@" return string.Format(CultureInfo.CurrentCulture, GetString(""{0}""{1}), {2});",
+ resourceString.Name,
+ resourceString.UsingNamedArgs ? ", " + resourceString.FormatArguments : null,
+ resourceString.ArgumentNames);
+ }
+ else
+ {
+ builder.AppendFormat(@" return GetString(""{0}"");", resourceString.Name);
+ }
+ builder.AppendLine()
+ .AppendLine(" }");
+}
+
+
+private class ResourceData
+{
+ public string Name { get; set; }
+ public string Value { get; set; }
+ public List Arguments { get; set; }
+
+ public bool UsingNamedArgs { get; set; }
+
+ public string FormatArguments
+ {
+ get { return string.Join(", ", Arguments.Select(a => "\"" + a + "\"")); }
+ }
+
+ public string ArgumentNames
+ {
+ get { return string.Join(", ", Arguments.Select(GetArgName)); }
+ }
+
+ public string Parameters
+ {
+ get { return string.Join(", ", Arguments.Select(a => "object " + GetArgName(a))); }
+ }
+
+ public string GetArgName(string name)
+ {
+ return UsingNamedArgs ? name : 'p' + name;
+ }
+}
+#>
\ No newline at end of file
diff --git a/KoreBuild-dotnet/build/_asmdiff.shade b/KoreBuild-dotnet/build/_asmdiff.shade
new file mode 100644
index 0000000000..6e9c492c0c
--- /dev/null
+++ b/KoreBuild-dotnet/build/_asmdiff.shade
@@ -0,0 +1,25 @@
+default ASM_DIFF='${Environment.GetEnvironmentVariable("ASM_DIFF")}'
+default outFile = "artifacts\default.html"
+@{
+ if (String.IsNullOrEmpty(ASM_DIFF))
+ {
+ Log.Warn("ASM_DIFF environment variable not set.");
+ Environment.Exit(-1);
+ return;
+ }
+}
+
+exec program='${ASM_DIFF}' commandline='${oldBinariesDir} ${newBinariesDir} -adm -out:${outFile}'
+
+@{
+ if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("TEAMCITY_VERSION")))
+ {
+ var message = File.ReadAllText(outFile)
+ .Replace("|", "||")
+ .Replace("'", "|'")
+ .Replace("\r", "|r")
+ .Replace("\n", "|n")
+ .Replace("]", "|]");
+ Log.Info("##teamcity[message text='" + message + "' status='WARNING']");
+ }
+}
\ No newline at end of file
diff --git a/KoreBuild-dotnet/build/_bower.shade b/KoreBuild-dotnet/build/_bower.shade
new file mode 100644
index 0000000000..1057204326
--- /dev/null
+++ b/KoreBuild-dotnet/build/_bower.shade
@@ -0,0 +1,19 @@
+default currentDir = '${Directory.GetCurrentDirectory()}'
+default nodeDir = '${Path.Combine(currentDir, "bin", "nodejs")}'
+var bowerLibrary = '${ Path.Combine(nodeDir, "node_modules", "bower", "bin", "bower") }'
+var bowerInstalled = '${ File.Exists(bowerLibrary) }'
+
+default bowerGloballyInstalled = '${ !bowerInstalled && TestCommand("bower", "--version --config.interactive=false") }'
+var bowerCmd = '${ bowerGloballyInstalled ? "bower" : bowerLibrary }'
+
+- // Turn off Bower's Insight reporting since this usage is scripted.
+- bowerCommand = bowerCommand + " --config.interactive=false";
+
+- // Install bower locally if not already installed either globally or locally; creates bowerLibrary file if run
+var installCommand = 'install ${E("KOREBUILD_NPM_INSTALL_OPTIONS")} --prefix "${nodeDir}" bower'
+npm npmCommand='${installCommand}' if='!(bowerGloballyInstalled || bowerInstalled)' once='installBower'
+
+- // Run bower
+exec program='cmd' commandline='/C ${bowerCmd} ${bowerCommand}' workingdir='${bowerDir}' if='bowerGloballyInstalled && !IsLinux'
+exec program='${bowerCmd}' commandline='${bowerCommand}' workingdir='${bowerDir}' if='bowerGloballyInstalled && IsLinux'
+node nodeCommand='"${bowerCmd}" ${bowerCommand}' workingdir='${bowerDir}' if='!bowerGloballyInstalled'
\ No newline at end of file
diff --git a/KoreBuild-dotnet/build/_copy.shade b/KoreBuild-dotnet/build/_copy.shade
new file mode 100644
index 0000000000..8489a60fa5
--- /dev/null
+++ b/KoreBuild-dotnet/build/_copy.shade
@@ -0,0 +1,35 @@
+use import="Files"
+
+default include='**/*.*'
+default exclude=''
+default overwrite='${ false }'
+
+@{
+ var copyFiles = Files.BasePath(Path.GetFullPath(sourceDir));
+ if (!string.IsNullOrEmpty(include))
+ {
+ copyFiles = copyFiles.Include(include);
+ }
+
+ if (!string.IsNullOrEmpty(exclude))
+ {
+ copyFiles = copyFiles.Exclude(exclude);
+ }
+
+ foreach(var copyFile in copyFiles)
+ {
+ if (!Quiet)
+ {
+ Log.Info(string.Format("Copying {0}", copyFile));
+ }
+
+ var sourceFile = Path.Combine(sourceDir, copyFile);
+ var outputFile = Path.Combine(outputDir, copyFile);
+ if (!Directory.Exists(Path.GetDirectoryName(outputFile)))
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(outputFile));
+ }
+
+ File.Copy(sourceFile, outputFile, overwrite);
+ }
+}
diff --git a/KoreBuild-dotnet/build/_dnu.shade b/KoreBuild-dotnet/build/_dnu.shade
new file mode 100644
index 0000000000..57cad3fdf9
--- /dev/null
+++ b/KoreBuild-dotnet/build/_dnu.shade
@@ -0,0 +1,23 @@
+@{/*
+
+dnu
+ Run dnu commands in your project. Executes `dnu` command.
+
+command=''
+ The `dnu` subcommand to execute.
+dnvmUse=''
+ Optional. The DNX framework to use. Suitable for a `dnvm exec` or `dnvm use` command.
+*/}
+
+default dnvmUse=''
+var dnvmPath = '${ Path.Combine(Directory.GetCurrentDirectory(), "packages", "KoreBuild", "build", "dnvm") }'
+
+exec program='cmd' commandline='/C dnu ${command}' if='!IsLinux && string.IsNullOrEmpty(dnvmUse)'
+
+var cmdCommand = '/S /C ""${dnvmPath}.cmd" use ${dnvmUse} && dnu ${command}"'
+exec program='cmd' commandline='${ cmdCommand }' if='!IsLinux && !string.IsNullOrEmpty(dnvmUse)'
+
+exec program='dnu' commandline='${command}' if='IsLinux && string.IsNullOrEmpty(dnvmUse)'
+
+var envCommand = 'bash -c "source \"${dnvmPath}.sh\" && dnvm use ${dnvmUse} && dnu ${command}"'
+exec program='/usr/bin/env' commandline='${ envCommand }' if='IsLinux && !string.IsNullOrEmpty(dnvmUse)'
diff --git a/KoreBuild-dotnet/build/_git-clone.shade b/KoreBuild-dotnet/build/_git-clone.shade
new file mode 100644
index 0000000000..13b02334e6
--- /dev/null
+++ b/KoreBuild-dotnet/build/_git-clone.shade
@@ -0,0 +1,9 @@
+
+
+
+default gitBranch=''
+
+var gitCommand='clone --quiet ${gitUri}'
+set gitCommand='${gitCommand} --branch ${gitBranch}' if='!string.IsNullOrEmpty(gitBranch)'
+
+git
diff --git a/KoreBuild-dotnet/build/_git-config.shade b/KoreBuild-dotnet/build/_git-config.shade
new file mode 100644
index 0000000000..b6d97436cb
--- /dev/null
+++ b/KoreBuild-dotnet/build/_git-config.shade
@@ -0,0 +1,4 @@
+
+var gitCommand='config ${gitOptionName} ${gitOptionValue}'
+
+git
diff --git a/KoreBuild-dotnet/build/_git-pull.shade b/KoreBuild-dotnet/build/_git-pull.shade
new file mode 100644
index 0000000000..12a11edaad
--- /dev/null
+++ b/KoreBuild-dotnet/build/_git-pull.shade
@@ -0,0 +1,8 @@
+
+
+default gitBranch=''
+
+var gitCommand='pull --quiet --ff-only ${gitUri}'
+set gitCommand='${gitCommand} ${gitBranch}:${gitBranch}' if='!string.IsNullOrEmpty(gitBranch)'
+
+git
diff --git a/KoreBuild-dotnet/build/_git.shade b/KoreBuild-dotnet/build/_git.shade
new file mode 100644
index 0000000000..eb05ca81be
--- /dev/null
+++ b/KoreBuild-dotnet/build/_git.shade
@@ -0,0 +1,7 @@
+
+default gitFolder=''
+
+-// Use cmd to invoke git so that people who have git as a 'cmd'
+exec program='cmd' commandline='/C git ${gitCommand}' workingdir='${gitFolder}' if='!IsLinux'
+exec program='git' commandline='${gitCommand}' workingdir='${gitFolder}' if='IsLinux'
+
diff --git a/KoreBuild-dotnet/build/_grunt.shade b/KoreBuild-dotnet/build/_grunt.shade
new file mode 100644
index 0000000000..7dcd815dba
--- /dev/null
+++ b/KoreBuild-dotnet/build/_grunt.shade
@@ -0,0 +1,16 @@
+default currentDir = '${Directory.GetCurrentDirectory()}'
+default nodeDir = '${Path.Combine(currentDir, "bin", "nodejs")}'
+var gruntCliLibrary = '${ Path.Combine(nodeDir, "node_modules", "grunt-cli", "bin", "grunt") }'
+var gruntCliInstalled = '${ File.Exists(gruntCliLibrary) }'
+
+default gruntCliGloballyInstalled = '${ !gruntCliInstalled && TestCommand("grunt", "--version") }'
+var gruntCmd = '${ gruntCliGloballyInstalled ? "grunt" : gruntCliLibrary }'
+
+- // Install grunt-cli locally if not already installed either globally or locally; creates gruntCliLibrary file if run
+var installCommand = 'install ${E("KOREBUILD_NPM_INSTALL_OPTIONS")} --prefix "${nodeDir}" grunt-cli'
+npm npmCommand='${installCommand}' if='!(gruntCliGloballyInstalled || gruntCliInstalled)' once='installGruntCli'
+
+-// Run grunt-cli
+exec program='cmd' commandline='/C ${gruntCmd}' workingdir='${gruntDir}' if='gruntCliGloballyInstalled && !IsLinux'
+exec program='${gruntCmd}' workingdir='${gruntDir}' if='gruntCliGloballyInstalled && IsLinux'
+node nodeCommand='"${gruntCmd}"' workingdir='${gruntDir}' if='!gruntCliGloballyInstalled'
\ No newline at end of file
diff --git a/KoreBuild-dotnet/build/_k-clean.shade b/KoreBuild-dotnet/build/_k-clean.shade
new file mode 100644
index 0000000000..a4af9d51a7
--- /dev/null
+++ b/KoreBuild-dotnet/build/_k-clean.shade
@@ -0,0 +1,13 @@
+@{/*
+
+k-clean
+ Cleans project. Downloads and executes k sdk tools.
+
+projectFile=''
+ Required. Path to the project.json to build.
+
+*/}
+
+var projectFolder='${Path.GetDirectoryName(projectFile)}'
+
+directory delete='${Path.Combine(projectFolder, "bin")}'
diff --git a/KoreBuild-dotnet/build/_k-generate-resx.shade b/KoreBuild-dotnet/build/_k-generate-resx.shade
new file mode 100644
index 0000000000..b499e6b0bc
--- /dev/null
+++ b/KoreBuild-dotnet/build/_k-generate-resx.shade
@@ -0,0 +1,177 @@
+use namespace="System"
+use namespace="System.Collections.Generic"
+use namespace="System.IO"
+use namespace="System.Linq"
+use namespace="System.Text"
+use namespace="System.Xml.Linq"
+
+default resxFile=''
+
+@{
+ var projectDir = Path.GetDirectoryName(resxFile);
+ var outDirectory = Path.Combine(projectDir, "Properties");
+ var projectName = Path.GetFileName(projectDir.TrimEnd((char)'/'));
+ var namedParameterMatcher = new Regex(@"\{([a-z]\w+)\}", RegexOptions.IgnoreCase);
+ var numberParameterMatcher = new Regex(@"\{(\d+)\}");
+ var generatingEnvironment = new StringBuilder();
+
+ var fileName = Path.GetFileNameWithoutExtension(resxFile);
+ var resourceStrings = new List();
+ var xml = XDocument.Load(resxFile);
+
+ foreach (var entry in xml.Descendants("data"))
+ {
+ var name = entry.Attribute("name").Value;
+ var value = entry.Element("value").Value;
+
+ bool usingNamedArgs = true;
+ var match = namedParameterMatcher.Matches(value);
+ if (match.Count == 0)
+ {
+ usingNamedArgs = false;
+ match = numberParameterMatcher.Matches(value);
+ }
+
+ var arguments = match.Cast()
+ .Select(m => m.Groups[1].Value)
+ .Distinct();
+ if (!usingNamedArgs)
+ {
+ arguments = arguments.OrderBy(Convert.ToInt32);
+ }
+
+ resourceStrings.Add(
+ new ResourceData
+ {
+ Name = name,
+ Value = value,
+ Arguments = arguments.ToList(),
+ UsingNamedArgs = usingNamedArgs
+ });
+ }
+
+ generatingEnvironment.AppendFormat(
+@"//
+namespace {0}
+{{
+ using System.Globalization;
+ using System.Reflection;
+ using System.Resources;
+
+ internal static class {1}
+ {{
+ private static readonly ResourceManager _resourceManager
+ = new ResourceManager(""{0}.{1}"", typeof({1}).GetTypeInfo().Assembly);
+", projectName, fileName);
+
+ foreach (var resourceString in resourceStrings)
+ {
+ generatingEnvironment.AppendLine();
+ RenderHeader(generatingEnvironment, resourceString);
+ RenderProperty(generatingEnvironment, resourceString);
+
+ generatingEnvironment.AppendLine();
+ RenderHeader(generatingEnvironment, resourceString);
+ RenderFormatMethod(generatingEnvironment, resourceString);
+ }
+
+ generatingEnvironment.Append(@"
+ private static string GetString(string name, params string[] formatterNames)
+ {
+ var value = _resourceManager.GetString(name);
+
+ System.Diagnostics.Debug.Assert(value != null);
+
+ if (formatterNames != null)
+ {
+ for (var i = 0; i < formatterNames.Length; i++)
+ {
+ value = value.Replace(""{"" + formatterNames[i] + ""}"", ""{"" + i + ""}"");
+ }
+ }
+
+ return value;
+ }
+ }
+}
+");
+
+ Directory.CreateDirectory(outDirectory);
+ var outputPath = Path.Combine(outDirectory, fileName + ".Designer.cs");
+
+ File.WriteAllText(outputPath, generatingEnvironment.ToString());
+}
+
+functions @{
+ private static void RenderHeader(StringBuilder builder, ResourceData resourceString)
+ {
+ builder.Append(" /// ")
+ .AppendLine();
+ foreach (var line in resourceString.Value.Split(new[] { '\n' }, StringSplitOptions.None))
+ {
+ builder.AppendFormat(" /// {0}", new XText(line))
+ .AppendLine();
+ }
+ builder.Append(" /// ")
+ .AppendLine();
+ }
+
+ private static void RenderProperty(StringBuilder builder, ResourceData resourceString)
+ {
+ builder.AppendFormat(" internal static string {0}", resourceString.Name)
+ .AppendLine()
+ .AppendLine(" {")
+ .AppendFormat(@" get {{ return GetString(""{0}""); }}", resourceString.Name)
+ .AppendLine()
+ .AppendLine(" }");
+ }
+
+ private static void RenderFormatMethod(StringBuilder builder, ResourceData resourceString)
+ {
+ builder.AppendFormat(" internal static string Format{0}({1})", resourceString.Name, resourceString.Parameters)
+ .AppendLine()
+ .AppendLine(" {");
+ if(resourceString.Arguments.Count > 0)
+ {
+ builder.AppendFormat(@" return string.Format(CultureInfo.CurrentCulture, GetString(""{0}""{1}), {2});",
+ resourceString.Name,
+ resourceString.UsingNamedArgs ? ", " + resourceString.FormatArguments : null,
+ resourceString.ArgumentNames);
+ }
+ else
+ {
+ builder.AppendFormat(@" return GetString(""{0}"");", resourceString.Name);
+ }
+ builder.AppendLine()
+ .AppendLine(" }");
+ }
+
+ private class ResourceData
+ {
+ public string Name { get; set; }
+ public string Value { get; set; }
+ public List Arguments { get; set; }
+
+ public bool UsingNamedArgs { get; set; }
+
+ public string FormatArguments
+ {
+ get { return string.Join(", ", Arguments.Select(a => "\"" + a + "\"")); }
+ }
+
+ public string ArgumentNames
+ {
+ get { return string.Join(", ", Arguments.Select(GetArgName)); }
+ }
+
+ public string Parameters
+ {
+ get { return string.Join(", ", Arguments.Select(a => "object " + GetArgName(a))); }
+ }
+
+ public string GetArgName(string name)
+ {
+ return UsingNamedArgs ? name : 'p' + name;
+ }
+ }
+}
\ No newline at end of file
diff --git a/KoreBuild-dotnet/build/_k-restore.shade b/KoreBuild-dotnet/build/_k-restore.shade
new file mode 100644
index 0000000000..f8bae50216
--- /dev/null
+++ b/KoreBuild-dotnet/build/_k-restore.shade
@@ -0,0 +1,19 @@
+@{/*
+
+k-restore
+ Restores nuget packages required for DNX projects. Downloads and executes DNX sdk tools.
+
+restoreDir=''
+ Optional. The directory in which to execute the dnu restore command.
+*/}
+
+default currentDir = '${ Directory.GetCurrentDirectory() }'
+default restoreDir = '${ currentDir }'
+
+-// Set KOREBUILD_DNU_RESTORE_CORECLR environment variable to any value and `dnu restore` will use Core CLR.
+var useCore = '${ E("KOREBUILD_DNU_RESTORE_CORECLR") }'
+default restoreUse='${ string.IsNullOrEmpty(useCore) ? string.Empty : "default -runtime coreclr" }'
+
+default restore_options=' ${ E("KOREBUILD_DNU_RESTORE_OPTIONS") } ${ IsLinux ? string.Empty : "--parallel" }'
+
+dnu command='restore${ restore_options }' workingDir='${ restoreDir }' dnvmUse='${ restoreUse }'
diff --git a/KoreBuild-dotnet/build/_k-standard-goals.shade b/KoreBuild-dotnet/build/_k-standard-goals.shade
new file mode 100644
index 0000000000..f233203b28
--- /dev/null
+++ b/KoreBuild-dotnet/build/_k-standard-goals.shade
@@ -0,0 +1,398 @@
+use assembly="System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+use namespace="System"
+use namespace="System.Globalization"
+use namespace="System.IO"
+use namespace="System.Linq"
+use import="BuildEnv"
+use import="Environment"
+use import="Files"
+use import="Json"
+use-teamcity
+
+default BASE_DIR='${Directory.GetCurrentDirectory()}'
+default TARGET_DIR='${Path.Combine(BASE_DIR, "artifacts")}'
+default BUILD_DIR='${Path.Combine(TARGET_DIR, "build")}'
+default TEST_DIR='${Path.Combine(TARGET_DIR, "test")}'
+default Configuration='${E("Configuration")}'
+default PACKAGELIST_JSON_FILENAME = 'NuGetPackageVerifier.json'
+default DNX_TOOLS_FEED = 'https://www.myget.org/F/dnxtools/api/v3/index.json'
+default NUGET_FEED = 'https://api.nuget.org/v3/index.json'
+
+@{
+ if (string.IsNullOrEmpty(E("DNX_BUILD_VERSION")))
+ {
+ E("DNX_BUILD_VERSION", BuildNumber);
+ }
+ if (string.IsNullOrEmpty(E("DNX_AUTHOR")))
+ {
+ E("DNX_AUTHOR", AUTHORS);
+ }
+ if (string.IsNullOrEmpty(E("DNX_ASSEMBLY_FILE_VERSION")))
+ {
+ E("DNX_ASSEMBLY_FILE_VERSION", CreateDayBasedVersionNumber());
+ }
+ if (string.IsNullOrEmpty(Configuration))
+ {
+ Configuration = "Debug";
+ E("Configuration", Configuration);
+ }
+
+ Log.Info("Build v2: " + IsBuildV2);
+}
+
+#restore-npm-modules
+ -// Find all dirs that contain a package.json file
+ var npmDirs = '${GetDirectoriesContaining(Directory.GetCurrentDirectory(), "package.json")}'
+ npm npmCommand='install ${E("KOREBUILD_NPM_INSTALL_OPTIONS")}' each='var npmDir in npmDirs'
+
+#restore-bower-components
+ -// Find all dirs that contain a bower.json file
+ var bowerDirs = '${GetDirectoriesContaining(Directory.GetCurrentDirectory(), "bower.json")}'
+ bower each='var bowerDir in bowerDirs' bowerCommand='install ${E("KOREBUILD_BOWER_INSTALL_OPTIONS")}'
+
+#run-grunt .restore-npm-modules .restore-bower-components target='initialize'
+ -// Find all dirs that contain a gruntfile.js file
+ var gruntDirs = '${GetDirectoriesContaining(Directory.GetCurrentDirectory(), "gruntfile.js")}'
+ grunt each='var gruntDir in gruntDirs'
+
+#clean-bin-folder
+ rimraf rimrafDir='bin' if='Directory.Exists("bin")'
+
+#clean-npm-modules
+ -// Find all dirs that contain a package.json file
+ var npmDirs = '${
+ GetDirectoriesContaining(Directory.GetCurrentDirectory(), "package.json")
+ .Select(directory => Path.Combine(directory, "node_modules"))
+ .Where(directory => Directory.Exists(directory))
+ }'
+ rimraf each='var rimrafDir in npmDirs'
+
+-// Target order is important because clean-npm-modules may (re)create bin folder.
+#deep-clean .clean-npm-modules .clean-bin-folder description='Clean folders that may cause problems for `git clean`.'
+
+#repo-initialize target='initialize'
+ k-restore
+
+#target-dir-clean target='clean'
+ @{
+ if (Directory.Exists(TARGET_DIR))
+ {
+ var directory = new DirectoryInfo(TARGET_DIR);
+ directory.Attributes &= ~FileAttributes.ReadOnly;
+
+ foreach (var info in directory.GetFileSystemInfos("*", SearchOption.AllDirectories))
+ {
+ info.Attributes &= ~FileAttributes.ReadOnly;
+ }
+
+ directory.Delete(true);
+ }
+ }
+
+#build-clean target='clean' if='Directory.Exists("src")'
+ k-clean each='var projectFile in Files.Include("src/**/project.json")'
+
+#ci-deep-clean .deep-clean target='clean' if='IsTeamCity'
+
+#build-compile target='compile' if='!IsBuildV2 && Directory.Exists("src")'
+ @{
+ var projectFiles = Files.Include("src/**/project.json").ToList();
+ if (ShouldRunInParallel)
+ {
+ Parallel.ForEach(projectFiles, projectFile => DnuPack(projectFile, BUILD_DIR, Configuration));
+ }
+ else
+ {
+ projectFiles.ForEach(projectFile => DnuPack(projectFile, BUILD_DIR, Configuration));
+ }
+
+ foreach (var nupkg in Files.Include(Path.Combine(BUILD_DIR, "*/*.nupkg")))
+ {
+ File.Copy(nupkg, Path.Combine(BUILD_DIR, Path.GetFileName(nupkg)), true);
+ }
+ }
+
+#build-compile target='compile' if='IsBuildV2'
+ @{
+ // If the src folder, build and create the packages
+ if (Directory.Exists("src"))
+ {
+ // Handle projects 1 to 3 levels down from src/, avoiding path too long errors.
+ DnuPack("src/*;src/*/*;src/*/*/*", BUILD_DIR, Configuration);
+
+ foreach (var nupkg in Files.Include(Path.Combine(BUILD_DIR, "*/*.nupkg")))
+ {
+ File.Copy(nupkg, Path.Combine(BUILD_DIR, Path.GetFileName(nupkg)), true);
+ }
+ }
+
+ // For test and samples only check if they compile
+ var projectsToBuild = new List();
+ if (Directory.Exists("test"))
+ {
+ // Handle projects 1 to 3 levels down from test/, avoiding path too long errors.
+ projectsToBuild.Add("test/*");
+ projectsToBuild.Add("test/*/*");
+ projectsToBuild.Add("test/*/*/*");
+ }
+ if (Directory.Exists("samples"))
+ {
+ // Handle projects 1 to 3 levels down from samples/, avoiding path too long errors.
+ projectsToBuild.Add("samples/*");
+ projectsToBuild.Add("samples/*/*");
+ projectsToBuild.Add("samples/*/*/*");
+ }
+
+ if (projectsToBuild.Any())
+ {
+ DnuBuild(
+ string.Join(";", projectsToBuild),
+ Configuration);
+ }
+ }
+
+#native-compile target='compile' if='!IsLinux && Directory.Exists(Path.Combine(BASE_DIR, "src"))'
+ var programFilesX86 = '${Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)}'
+ var nativeProjects ='${Files.Include(Path.Combine(BASE_DIR, "src", "**", "*.vcxproj"))}'
+
+ @{
+ if (nativeProjects.Any())
+ {
+ var msbuildVersions = new[] { "14.0", "12.0"};
+
+ for (var i = 0; i < msbuildVersions.Length; i++)
+ {
+ var msbuildPath = Path.Combine(programFilesX86, "MSBuild", msbuildVersions[i], "Bin", "MSBuild.exe");
+ if (File.Exists(msbuildPath))
+ {
+ var commonParameters =
+ " /p:Configuration=" + Configuration +
+ " /p:ProductVersion=1.0.0" +
+ " /p:FileRevision=" + E("DNX_ASSEMBLY_FILE_VERSION") +
+ " /p:BuildVersion=" + E("DNX_BUILD_VERSION");
+
+ foreach (var project in nativeProjects)
+ {
+ Exec(msbuildPath, project + " /p:Platform=Win32" + commonParameters);
+ Exec(msbuildPath, project + " /p:Platform=x64" + commonParameters);
+ }
+
+ break;
+ }
+
+ if (i == msbuildVersions.Length - 1)
+ {
+ Log.Warn("msbuild version 14 or 12 not found. Please ensure you have the VS 2015 or VS 2013 C++ SDK installed.");
+ Environment.Exit(1);
+ }
+ }
+ }
+ }
+
+ copy sourceDir='${Path.GetDirectoryName(project)}' include='bin/**/' outputDir='${Path.Combine(BUILD_DIR, Path.GetFileNameWithoutExtension(project))}' overwrite='${true}' each='var project in nativeProjects'
+
+#nuget-verify target='package' if='File.Exists(PACKAGELIST_JSON_FILENAME) && ShouldVerifyNupkgs' description='Verify if all the packages are generated properly'
+ var commandsDirectory = '${Path.Combine(BASE_DIR, "commands")}'
+ exec program='cmd' commandline='/C dnu commands install --source ${DNX_TOOLS_FEED} --source ${NUGET_FEED} NuGetPackageVerifier --packages "${commandsDirectory}"'
+ exec program='cmd' commandline='/C ${Path.Combine(commandsDirectory, "nugetverify")} "${BUILD_DIR}" "${Path.Combine(BASE_DIR, PACKAGELIST_JSON_FILENAME)}"'
+ @{
+ if (Directory.Exists(commandsDirectory))
+ {
+ Directory.Delete(commandsDirectory, recursive: true);
+ }
+ }
+
+#nuget-install target='install' if='Directory.Exists("src")' description='Install NuGet packages to local repo'
+ kpm-publish sourcePackagesDir='${BUILD_DIR}' targetPackagesDir='${E("PACKAGES_PUBLISH_DIR")}'
+ nuget-resilient-publish sourcePackagesDir='${BUILD_DIR}' nugetFeed='${E("NUGET_PUBLISH_FEED")}' if='!string.IsNullOrEmpty(E("NUGET_PUBLISH_FEED"))'
+
+#xunit-test target='test' if='Directory.Exists("test")'
+ @{
+ var projectFiles = Files.Include("test/**/project.json").Exclude("**/bin/*/app/project.json").ToList();
+ if (ShouldRunInParallel)
+ {
+ Parallel.ForEach(projectFiles, projectFile => DnxTest(projectFile, testParallel: true));
+ }
+ else
+ {
+ projectFiles.ForEach(projectFile => DnxTest(projectFile, testParallel: false));
+ }
+ }
+
+#build-samples target='test' if='!IsBuildV2 && Directory.Exists("samples")'
+ @{
+ var projectFiles = Files.Include("samples/**/project.json").ToList();
+ if (ShouldRunInParallel)
+ {
+ Parallel.ForEach(projectFiles, projectFile => DnuBuild(projectFile, Configuration));
+ }
+ else
+ {
+ projectFiles.ForEach(projectFile => DnuBuild(projectFile, Configuration));
+ }
+ }
+
+#make-roslyn-fast
+ ngen-roslyn
+
+#resx
+ @{
+ var cultures = CultureInfo.GetCultures(CultureTypes.NeutralCultures | CultureTypes.InstalledWin32Cultures | CultureTypes.SpecificCultures);
+ foreach (var file in Directory.EnumerateFiles(BASE_DIR, "*.resx", SearchOption.AllDirectories))
+ {
+ var splitFileName = Path.GetFileNameWithoutExtension(file).Split(new string[] { "." }, StringSplitOptions.None);
+
+ if (splitFileName.Length > 1)
+ {
+ var localeString = splitFileName.Last();
+ if (!cultures.Any(c => localeString.Equals(c.Name)))
+ {
+ UpdateResx(file);
+ }
+ }
+ else
+ {
+ UpdateResx(file);
+ }
+ }
+ }
+
+#--quiet
+ @{
+ AddToE("KOREBUILD_BOWER_INSTALL_OPTIONS", "--quiet");
+ AddToE("KOREBUILD_DNU_BUILD_OPTIONS", "--quiet");
+ AddToE("KOREBUILD_DNU_PACK_OPTIONS", "--quiet");
+ AddToE("KOREBUILD_DNU_RESTORE_OPTIONS", "--quiet");
+ AddToE("KOREBUILD_NPM_INSTALL_OPTIONS", "--quiet");
+ Quiet = true;
+ }
+
+#--parallel
+ @{
+ E("KOREBUILD_PARALLEL", "1");
+ }
+
+#--test-dnxcore
+ @{
+ E("KOREBUILD_TEST_DNXCORE", "1");
+ }
+
+#stylecop if='Directory.Exists("src")'
+ stylecop-setup
+ stylecop-run each='var projectFile in Files.Include("src/**/project.json")'
+
+functions @{
+ private static bool Quiet { get; set; }
+
+ string E(string key) { return Environment.GetEnvironmentVariable(key); }
+ void E(string key, string value) { Environment.SetEnvironmentVariable(key, value); }
+ void AddToE(string key, string append)
+ {
+ var original = E(key);
+ if (string.IsNullOrEmpty(original))
+ {
+ E(key, append);
+ }
+ else
+ {
+ E(key, original + " " + append);
+ }
+ }
+
+ IEnumerable GetDirectoriesContaining(string path, string searchPattern)
+ {
+ var sep = Path.DirectorySeparatorChar;
+ // Don't include directories that are children of a node_modules or bower_components directory
+ return Directory.GetFiles(path, searchPattern, SearchOption.AllDirectories)
+ .Where(p => p.IndexOf(sep + "node_modules" + sep) < 0 &&
+ p.IndexOf(sep + "bower_components" + sep) < 0 &&
+ p.IndexOf(sep + "wwwroot" + sep + "lib" + sep) < 0)
+ .Select(p => Path.GetDirectoryName(p))
+ .Distinct();
+ }
+
+ bool TestCommand(string program, string commandline)
+ {
+ // Tests whether a given command succeeds at the command line.
+ // Useful for testing whether a given command is installed and on the path, e.g. node
+ ProcessStartInfo processStartInfo;
+
+ if(!IsLinux)
+ {
+ processStartInfo = new ProcessStartInfo {
+ UseShellExecute = false,
+ FileName = "cmd",
+ Arguments = "/C " + program + " " + commandline,
+ };
+ } else
+ {
+ processStartInfo = new ProcessStartInfo {
+ UseShellExecute = false,
+ FileName = program,
+ Arguments = commandline,
+ };
+ }
+ try
+ {
+ Log.Info(string.Format("Testing for command: {0} {1}", program, commandline));
+ var process = Process.Start(processStartInfo);
+ process.WaitForExit();
+ if (process.ExitCode == 0)
+ {
+ Log.Info(" command found (0 exit code)");
+ return true;
+ }
+ else
+ {
+ Log.Warn(" command not found (non-0 exit code)");
+ return false;
+ }
+ }
+ catch (Exception ex)
+ {
+ Log.Warn(" command exception: " + ex.ToString());
+ Log.Warn(" command not found");
+ return false;
+ }
+ }
+
+ bool ShouldRunInParallel
+ {
+ get { return !string.IsNullOrEmpty(E("KOREBUILD_PARALLEL")); }
+ }
+
+ bool ShouldVerifyNupkgs
+ {
+ get { return E("KOREBUILD_VERIFY_NUPKGS") == "1"; }
+ }
+}
+
+macro name='Exec' program='string' commandline='string'
+ exec
+
+macro name='Dnu' command='string'
+ dnu
+
+macro name='Dnx' command='string' dnxDir='string'
+ k
+
+macro name='Dnx' command='string' dnxDir='string' dnvmUse='string'
+ k
+
+macro name="UpdateResx" resxFile='string'
+ k-generate-resx
+
+macro name="DnxTest" projectFile='string' testParallel='bool'
+ k-test
+
+macro name="DnuBuild" projectFile='string' configuration='string'
+ kpm-build
+
+macro name="DnuPack" projectFile='string' kpmPackOutputDir='string' configuration='string'
+ kpm-pack
+
+macro name="DeleteFolder" delete='string'
+ directory
+
+macro name="CopyFolder" sourceDir='string' outputDir='string' overwrite='bool'
+ copy
diff --git a/KoreBuild-dotnet/build/_k-test.shade b/KoreBuild-dotnet/build/_k-test.shade
new file mode 100644
index 0000000000..55c6e08481
--- /dev/null
+++ b/KoreBuild-dotnet/build/_k-test.shade
@@ -0,0 +1,69 @@
+use import="Json"
+use import="Environment"
+
+default NO_PARALLEL_TEST_PROJECTS='${E("NO_PARALLEL_TEST_PROJECTS")}'
+default KOREBUILD_TEST_DNXCORE='${E("KOREBUILD_TEST_DNXCORE")}'
+
+@{/*
+
+k-test
+ Run unit tests in your project.
+
+projectFile=''
+ Required. Path to the test project.json to execute
+
+*/}
+
+@{
+ var projectText = File.ReadAllText(projectFile);
+ var project = (JsonObject)Json.Deserialize(projectText);
+
+ var commands = project.ValueAsJsonObject("commands");
+
+ if (commands != null && commands.Keys.Contains("test"))
+ {
+ var projectFolder = Path.GetDirectoryName(projectFile);
+ var projectName = Path.GetFileName(projectFolder);
+
+ var noParallelTestProjects = new HashSet(StringComparer.OrdinalIgnoreCase);
+ if (!string.IsNullOrEmpty(NO_PARALLEL_TEST_PROJECTS))
+ {
+ noParallelTestProjects.UnionWith(NO_PARALLEL_TEST_PROJECTS.Split((char)','));
+ }
+
+ var configs = project.ValueAsJsonObject("frameworks");
+ IEnumerable targetFrameworks;
+ if (configs == null)
+ {
+ // Assume dnx451 only if none specified
+ targetFrameworks = new[] { "dnx451" };
+ }
+ else
+ {
+ targetFrameworks = configs.Keys;
+ }
+
+ // Currently only dnx* targets are supported. See aspnet/Universe#53
+ targetFrameworks = targetFrameworks.Where(k => k.StartsWith("dnx", StringComparison.OrdinalIgnoreCase));
+
+ foreach (var framework in targetFrameworks)
+ {
+ var testArgs = noParallelTestProjects.Contains(projectName) ? " -parallel none" : "";
+
+ if (!framework.StartsWith("dnxcore", StringComparison.OrdinalIgnoreCase))
+ {
+ if (IsLinux)
+ {
+ // Work around issue with testing in parallel on Mono.
+ testArgs = " -parallel none";
+ }
+
+ Dnx("test" + testArgs, projectFolder);
+ }
+ else if (!IsLinux || !string.IsNullOrEmpty(KOREBUILD_TEST_DNXCORE))
+ {
+ Dnx("test" + testArgs, projectFolder, "default -runtime coreclr");
+ }
+ }
+ }
+}
diff --git a/KoreBuild-dotnet/build/_k-xml-docs-test.shade b/KoreBuild-dotnet/build/_k-xml-docs-test.shade
new file mode 100644
index 0000000000..3fbc89033e
--- /dev/null
+++ b/KoreBuild-dotnet/build/_k-xml-docs-test.shade
@@ -0,0 +1,55 @@
+
+use namespace="System"
+use namespace="System.Collections.Generic"
+use namespace="System.IO"
+use import="Files"
+
+default BASE_DIR='${Directory.GetCurrentDirectory()}'
+
+@{
+ var srcDir = Path.Combine(BASE_DIR, "src");
+ foreach (var projectFile in Files.Include(Path.Combine(srcDir, "**", "project.json")))
+ {
+ var binDirectory = Path.Combine(Path.GetDirectoryName(projectFile), "bin");
+ if (Directory.Exists(binDirectory))
+ {
+ foreach (var xmlFilePath in Files.Include(Path.Combine(binDirectory, "**", "*.xml")))
+ {
+ var errors = 0;
+ var xmlLines = File.ReadAllLines(xmlFilePath);
+ for (var linesIndex = 0; linesIndex < xmlLines.Length; linesIndex++)
+ {
+ var xmlLine = xmlLines[linesIndex].Trim();
+ if (xmlLine.StartsWith("