aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jeremy Wall <jeremy@marzhillstudios.com>2015-11-09 18:44:26 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2015-11-10 10:23:14 +0000
commitd00e3a1ef2c6678ffc24eb9ffbc6561ba85338c4 (patch)
tree65141853f2eaa52cfd5fcde608f89a14548b3428
parent15099239d94f5fb94504e33f670adf71dacff48a (diff)
Add dotnet csharp support to bazel.
Adds rules for csharp_binary, csharp_library, and csharp_nunit_test. -- Change-Id: I51e448a399c535554353b3f40bf090bb602f647f Reviewed-on: https://bazel-review.googlesource.com/#/c/2270/ MOS_MIGRATED_REVID=107399181
-rw-r--r--WORKSPACE8
-rw-r--r--examples/dotnet/example_binary/BUILD12
-rw-r--r--examples/dotnet/example_binary/Program.cs14
-rw-r--r--examples/dotnet/example_binary/Properties/AssemblyInfo.cs27
-rw-r--r--examples/dotnet/example_lib/BUILD13
-rw-r--r--examples/dotnet/example_lib/MyClass.cs19
-rw-r--r--examples/dotnet/example_lib/Properties/AssemblyInfo.cs27
-rw-r--r--examples/dotnet/example_test/BUILD11
-rw-r--r--examples/dotnet/example_test/MyTest.cs24
-rw-r--r--examples/dotnet/example_transitive_lib/BUILD10
-rw-r--r--examples/dotnet/example_transitive_lib/Properties/AssemblyInfo.cs27
-rw-r--r--examples/dotnet/example_transitive_lib/TransitiveClass.cs14
-rw-r--r--tools/build_defs/dotnet/BUILD17
-rw-r--r--tools/build_defs/dotnet/README.md77
-rw-r--r--tools/build_defs/dotnet/csharp.bzl291
-rw-r--r--tools/build_defs/dotnet/dotnet.WORKSPACE7
-rw-r--r--tools/build_defs/dotnet/nunit.BUILD17
17 files changed, 615 insertions, 0 deletions
diff --git a/WORKSPACE b/WORKSPACE
index 5255429f79..5e57bc4d52 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -98,3 +98,11 @@ new_http_archive(
sha256 = "2593132ca490b9ee17509d65ee2cd078441ff544899f6afb97a03d08c25524e7",
url = "https://storage.googleapis.com/golang/go1.5.1.linux-amd64.tar.gz",
)
+
+new_http_archive(
+ name = "nunit",
+ build_file = "tools/build_defs/dotnet/nunit.BUILD",
+ sha256 = "1bd925514f31e7729ccde40a38a512c2accd86895f93465f3dfe6d0b593d7170",
+ type = "zip",
+ url = "https://github.com/nunit/nunitv2/releases/download/2.6.4/NUnit-2.6.4.zip",
+)
diff --git a/examples/dotnet/example_binary/BUILD b/examples/dotnet/example_binary/BUILD
new file mode 100644
index 0000000000..04c126a31e
--- /dev/null
+++ b/examples/dotnet/example_binary/BUILD
@@ -0,0 +1,12 @@
+load("/tools/build_defs/dotnet/csharp", "csharp_binary")
+
+csharp_binary(
+ name = "hello",
+ srcs = [
+ "Program.cs",
+ "Properties/AssemblyInfo.cs",
+ ],
+ deps = [
+ "//examples/dotnet/example_lib:MyClass",
+ ],
+)
diff --git a/examples/dotnet/example_binary/Program.cs b/examples/dotnet/example_binary/Program.cs
new file mode 100644
index 0000000000..7780823347
--- /dev/null
+++ b/examples/dotnet/example_binary/Program.cs
@@ -0,0 +1,14 @@
+using System;
+using example_lib;
+
+namespace example_binary
+{
+ class MainClass
+ {
+ public static void Main(string[] args)
+ {
+ var mc = new MyClass();
+ Console.WriteLine(mc.Message);
+ }
+ }
+}
diff --git a/examples/dotnet/example_binary/Properties/AssemblyInfo.cs b/examples/dotnet/example_binary/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..d7700ef2b3
--- /dev/null
+++ b/examples/dotnet/example_binary/Properties/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("example_binary")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("VAE Inc")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
diff --git a/examples/dotnet/example_lib/BUILD b/examples/dotnet/example_lib/BUILD
new file mode 100644
index 0000000000..0ec2cd7dab
--- /dev/null
+++ b/examples/dotnet/example_lib/BUILD
@@ -0,0 +1,13 @@
+load("/tools/build_defs/dotnet/csharp", "csharp_library")
+
+csharp_library(
+ name = "MyClass",
+ srcs = [
+ "MyClass.cs",
+ "Properties/AssemblyInfo.cs",
+ ],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//examples/dotnet/example_transitive_lib:TransitiveClass",
+ ],
+)
diff --git a/examples/dotnet/example_lib/MyClass.cs b/examples/dotnet/example_lib/MyClass.cs
new file mode 100644
index 0000000000..8ff7c18d56
--- /dev/null
+++ b/examples/dotnet/example_lib/MyClass.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Runtime.Remoting.Messaging;
+
+using example_transitive_lib;
+
+namespace example_lib
+{
+ public class MyClass
+ {
+ public string Message
+ {
+ get { return example_transitive_lib.TransitiveClass.Message; }
+ }
+
+ public MyClass()
+ {
+ }
+ }
+}
diff --git a/examples/dotnet/example_lib/Properties/AssemblyInfo.cs b/examples/dotnet/example_lib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..1e8e2dd20e
--- /dev/null
+++ b/examples/dotnet/example_lib/Properties/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("example_lib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
diff --git a/examples/dotnet/example_test/BUILD b/examples/dotnet/example_test/BUILD
new file mode 100644
index 0000000000..06461ca3c5
--- /dev/null
+++ b/examples/dotnet/example_test/BUILD
@@ -0,0 +1,11 @@
+load("/tools/build_defs/dotnet/csharp", "csharp_nunit_test")
+
+csharp_nunit_test(
+ name = "MyTest",
+ srcs = [
+ "MyTest.cs",
+ ],
+ deps = [
+ "//examples/dotnet/example_lib:MyClass",
+ ],
+)
diff --git a/examples/dotnet/example_test/MyTest.cs b/examples/dotnet/example_test/MyTest.cs
new file mode 100644
index 0000000000..d5d5d3e5c7
--- /dev/null
+++ b/examples/dotnet/example_test/MyTest.cs
@@ -0,0 +1,24 @@
+using System;
+
+using NUnit.Framework;
+
+using example_lib;
+
+namespace example_test
+{
+ [TestFixture]
+ public class MyTest
+ {
+ [Test]
+ public void MyTest1()
+ {
+ Assert.That("foo", Is.EqualTo("Foo"));
+ }
+
+ [Test]
+ public void MyTest2()
+ {
+ Assert.That("bar", Is.EqualTo("bar"));
+ }
+ }
+} \ No newline at end of file
diff --git a/examples/dotnet/example_transitive_lib/BUILD b/examples/dotnet/example_transitive_lib/BUILD
new file mode 100644
index 0000000000..c6535d781c
--- /dev/null
+++ b/examples/dotnet/example_transitive_lib/BUILD
@@ -0,0 +1,10 @@
+load("/tools/build_defs/dotnet/csharp", "csharp_library")
+
+csharp_library(
+ name = "TransitiveClass",
+ srcs = [
+ "Properties/AssemblyInfo.cs",
+ "TransitiveClass.cs",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/examples/dotnet/example_transitive_lib/Properties/AssemblyInfo.cs b/examples/dotnet/example_transitive_lib/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..ebc927a51e
--- /dev/null
+++ b/examples/dotnet/example_transitive_lib/Properties/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("example_transitive_lib")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
diff --git a/examples/dotnet/example_transitive_lib/TransitiveClass.cs b/examples/dotnet/example_transitive_lib/TransitiveClass.cs
new file mode 100644
index 0000000000..948fadb589
--- /dev/null
+++ b/examples/dotnet/example_transitive_lib/TransitiveClass.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Runtime.Remoting.Messaging;
+
+namespace example_transitive_lib
+{
+ public class TransitiveClass
+ {
+ public static string Message
+ {
+ get { return "Hello World!"; }
+ }
+ }
+}
+
diff --git a/tools/build_defs/dotnet/BUILD b/tools/build_defs/dotnet/BUILD
new file mode 100644
index 0000000000..0622f058b9
--- /dev/null
+++ b/tools/build_defs/dotnet/BUILD
@@ -0,0 +1,17 @@
+# Detect our platform,
+# mac os x
+config_setting(
+ name = "darwin",
+ values = {"host_cpu": "darwin"},
+)
+
+# linux amd64
+config_setting(
+ name = "linux",
+ values = {"host_cpu": "k8"},
+)
+
+config_setting(
+ name = "debug",
+ values = {"compilation_mode": "dbg"},
+)
diff --git a/tools/build_defs/dotnet/README.md b/tools/build_defs/dotnet/README.md
new file mode 100644
index 0000000000..0f8dd9ec7e
--- /dev/null
+++ b/tools/build_defs/dotnet/README.md
@@ -0,0 +1,77 @@
+Intro
+=====
+
+This is a minimal viable set of C# bindings for building csharp code with
+mono. It's still pretty rough but it works as a proof of concept that could
+grow into something more. If windows support ever happens for Bazel then this
+might become especially valuable.
+
+Rules
+=====
+
+* csharp\_library
+
+ csharp_library(
+ name="MyLib",
+ srcs=["MyLib.cs"],
+ deps=["//my/dependency:SomeLib"],
+ )
+
+* csharp\_binary
+
+ csharp_binary(
+ name="MyApp",
+ main="MyApp", # optional name of the main class.
+ srcs=["MyApp.cs"],
+ deps=["//my/dependency:MyLib"],
+ )
+
+* csharp\_nunit\_test
+
+ csharp_nunit_test(
+ name="MyApp",
+ srcs=["MyApp.cs"],
+ deps=["//my/dependency:MyLib"],
+ )
+
+Shared attributes for all csharp rules
+--------------------------------------
+
+<table class=table table-condensed table-bordered table-params">
+<colgroup>
+ <col class="col-param" />
+ <col class="param-description" />
+</colgroup>
+<thead>
+ <tr>
+ <th colspan="2">Attributes</th>
+ </tr>
+</thead>
+<tbody>
+<tr><td>name</td>string<td><td>Unique name for this rule</td></td>Required</td></tr>
+<tr><td>srcs</td>List of Labels<td><td>Csharp .cs or .resx files.</td></td>Required</td></tr>
+<tr><td>deps</td>List of Labels<td><td>Dependencies for this rule.</td></td>Optional</td></tr>
+<tr><td>warn</td>Int<td><td>Compiler warn level for this library. (Defaults to 4.)</td></td>optional</td></tr>
+<tr><td>csc</td>string<td><td>Override the default csharp compiler.</td></td>Optional</td></tr>
+</tbody>
+</table>
+
+Usage
+=====
+
+Copy the contents of the dotnet.WORKSPACE file into your WORKSPACE file.
+
+Things still missing:
+=====================
+
+- Handle .resx files correctly.
+- .Net Modules
+- building documentation.
+- Pulling Mono in through a mono.WORKSPACE file.
+
+Future nice to haves:
+=====================
+
+- building csproj and sln files for VS and MonoDevelop.
+- Nuget Packaging
+- Windows .Net framwork support
diff --git a/tools/build_defs/dotnet/csharp.bzl b/tools/build_defs/dotnet/csharp.bzl
new file mode 100644
index 0000000000..297ca60303
--- /dev/null
+++ b/tools/build_defs/dotnet/csharp.bzl
@@ -0,0 +1,291 @@
+# Copyright 2015 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""CSharp bazel rules"""
+
+_MONO_UNIX_CSC = "/usr/local/bin/mcs"
+
+# TODO(jeremy): Windows when it's available.
+
+def _make_csc_flag(flag_start, flag_name, flag_value=None):
+ return flag_start + flag_name + (":" + flag_value if flag_value else "")
+
+def _make_csc_deps(deps, extra_files=[]):
+ dlls = set()
+ refs = set()
+ transitive_dlls = set()
+ for dep in deps:
+ if hasattr(dep, "target_type"):
+ dep_type = getattr(dep, "target_type")
+ if dep_type == "exe":
+ fail("You can't use a binary target as a dependency")
+ if dep_type == "library":
+ dlls += [dep.out]
+ refs += [dep.name]
+ if dep.transitive_dlls:
+ transitive_dlls += dep.transitive_dlls
+ return struct(
+ dlls = dlls + set(extra_files),
+ refs = refs,
+ transitive_dlls = transitive_dlls,
+ )
+
+def _get_libdirs(dlls, libdirs=[]):
+ return [dep.dirname for dep in dlls] + libdirs
+
+def _make_csc_arglist(ctx, output, depinfo, extra_refs=[]):
+ flag_start = ctx.attr._flag_start
+ args = [
+ # /out:<file>
+ _make_csc_flag(flag_start, "out", output.path),
+ # /target (exe for binary, library for lib, module for module)
+ _make_csc_flag(flag_start, "target", ctx.attr._target_type),
+ # /fullpaths
+ _make_csc_flag(flag_start, "fullpaths"),
+ # /warn
+ _make_csc_flag(flag_start, "warn", str(ctx.attr.warn)),
+ # /nologo
+ _make_csc_flag(flag_start, "nologo"),
+ ]
+
+ # /modulename:<string> only used for modules
+ libdirs = _get_libdirs(depinfo.dlls)
+ libdirs = _get_libdirs(depinfo.transitive_dlls, libdirs)
+ # /lib:dir1,[dir1]
+ args += [_make_csc_flag(flag_start, "lib", ",".join(list(libdirs)))] if libdirs else []
+ # /reference:filename[,filename2]
+ args += [_make_csc_flag(flag_start, "reference", ",".join(list(depinfo.refs + extra_refs)))] if depinfo.refs else extra_refs
+
+ # /doc
+ args += [_make_csc_flag(flag_start, "doc", ctx.outputs.doc_xml.path)] if hasattr(ctx.outputs, "doc_xml") else []
+ # /debug
+ debug = ctx.var.get("BINMODE", "") == "-dbg"
+ args += [_make_csc_flag(flag_start, "debug")] if debug else []
+ # /warnaserror
+ # TODO(jeremy): /define:name[;name2]
+ # TODO(jeremy): /resource:filename[,identifier[,accesibility-modifier]]
+ # /main:class
+ if hasattr(ctx.attr, "main_class") and ctx.attr.main_class:
+ args += [_make_csc_flag(flag_start, "main", ctx.attr.main_class)]
+ # TODO(jwall): /parallel
+ return args
+
+def _make_nunit_launcher(ctx, depinfo, output):
+ content = """#!/bin/bash
+cd $0.runfiles
+# TODO(jeremy): This is a gross and fragile hack.
+# We should be able to do better than this.
+for l in {libs}; do
+ ln -s -f $l $(basename $l)
+done
+/usr/local/bin/mono {nunit_exe} {libs} "$@"
+
+"""
+ libs = [d.short_path for d in depinfo.dlls]
+ libs += [d.short_path for d in depinfo.transitive_dlls]
+
+ content = content.format(
+ nunit_exe=ctx.files._nunit_exe[0].path,
+ libs=" ".join(libs),
+ )
+
+ ctx.file_action(
+ output=ctx.outputs.executable,
+ content=content,
+ )
+
+def _make_launcher(ctx, depinfo, output):
+ content = """#!/bin/bash
+cd $0.runfiles
+# TODO(jeremy): This is a gross and fragile hack.
+# We should be able to do better than this.
+ln -s -f {exe} $(basename {exe})
+for l in {libs}; do
+ ln -s -f $l $(basename $l)
+done
+/usr/local/bin/mono $(basename {exe}) "$@"
+"""
+ libs = [d.short_path for d in depinfo.dlls]
+ libs += [d.short_path for d in depinfo.transitive_dlls]
+
+ content = content.format(
+ exe=output.short_path,
+ libs=" ".join(libs),
+ )
+
+ ctx.file_action(
+ output=ctx.outputs.executable,
+ content=content,
+ )
+
+def _csc_get_output(ctx):
+ output = None
+ if hasattr(ctx.outputs, "csc_lib"):
+ output = ctx.outputs.csc_lib
+ elif hasattr(ctx.outputs, "csc_exe"):
+ output = ctx.outputs.csc_exe
+ else:
+ fail("You must supply one of csc_lib or csc_exe")
+ return output
+
+def _csc_collect_inputs(ctx, extra_files=[]):
+ depinfo = _make_csc_deps(ctx.attr.deps, extra_files=extra_files)
+ inputs = set(ctx.files.srcs) + depinfo.dlls + depinfo.transitive_dlls
+ srcs = [src.path for src in ctx.files.srcs]
+ return struct(
+ depinfo=depinfo,
+ inputs=inputs,
+ srcs=srcs,
+ )
+
+def _csc_compile_action(ctx, assembly, all_outputs, collected_inputs, extra_refs=[]):
+ csc_args = _make_csc_arglist(ctx, assembly, collected_inputs.depinfo, extra_refs=extra_refs)
+ command_script = " ".join([ctx.attr.csc] + csc_args + collected_inputs.srcs)
+
+ ctx.action(
+ inputs = list(collected_inputs.inputs),
+ outputs = all_outputs,
+ command = command_script,
+ arguments = csc_args,
+ progress_message = ("Compiling " +
+ ctx.label.package + ":" +
+ ctx.label.name))
+ return
+
+def _cs_runfiles(ctx, outputs, depinfo):
+ return ctx.runfiles(
+ files = outputs,
+ transitive_files = set(depinfo.dlls + depinfo.transitive_dlls) or None,
+ )
+
+
+def _csc_compile_impl(ctx):
+ if hasattr(ctx.outputs, "csc_lib") and hasattr(ctx.outputs, "csc_exe"):
+ fail("exactly one of csc_lib and csc_exe must be defined")
+
+ output = _csc_get_output(ctx)
+ outputs = [output] + ([ctx.outputs.doc_xml] if hasattr(ctx.outputs, "doc_xml") else [])
+
+ collected = _csc_collect_inputs(ctx)
+
+ depinfo = collected.depinfo
+ inputs = collected.inputs
+ srcs = collected.srcs
+
+ runfiles = _cs_runfiles(ctx, outputs, depinfo)
+
+ _csc_compile_action(ctx, output, outputs, collected)
+
+ if hasattr(ctx.outputs, "csc_exe"):
+ _make_launcher(ctx, depinfo, output)
+
+ return struct(name= ctx.label.name,
+ srcs = srcs,
+ target_type=ctx.attr._target_type,
+ out = output,
+ dlls = set([output]),
+ transitive_dlls = depinfo.dlls,
+ runfiles=runfiles)
+
+def _cs_nunit_run_impl(ctx):
+ if hasattr(ctx.outputs, "csc_lib") and hasattr(ctx.outputs, "csc_exe"):
+ fail("exactly one of csc_lib and csc_exe must be defined")
+
+ output = _csc_get_output(ctx)
+ outputs = [output] + ([ctx.outputs.doc_xml] if hasattr(ctx.outputs, "doc_xml") else [])
+ outputs = outputs
+
+ collected_inputs = _csc_collect_inputs(ctx, ctx.files._nunit_framework)
+
+ depinfo = collected_inputs.depinfo
+ inputs = collected_inputs.inputs
+ srcs = collected_inputs.srcs
+
+ runfiles = _cs_runfiles(ctx, outputs + ctx.files._nunit_exe + ctx.files._nunit_exe_libs, depinfo)
+
+ _csc_compile_action(ctx, output, outputs, collected_inputs, extra_refs=["Nunit.Framework"])
+
+ _make_nunit_launcher(ctx, depinfo, output)
+
+ return struct(name=ctx.label.name,
+ srcs=srcs,
+ target_type=ctx.attr._target_type,
+ out=output,
+ dlls = set([output]) if hasattr(ctx.outputs, "csc_lib") else None,
+ transitive_dlls = depinfo.dlls,
+ runfiles=runfiles)
+
+_COMMON_ATTRS={
+ # configuration fragment that specifies
+ "_flag_start": attr.string(default="-"),
+ # where the csharp compiler is.
+ "csc": attr.string(default=_MONO_UNIX_CSC),
+ # code dependencies for this rule.
+ # all dependencies must provide an out field.
+ "deps": attr.label_list(providers=["out", "target_type"]),
+ # source files for this target.
+ "srcs": attr.label_list(allow_files = FileType([".cs", ".resx"])),
+ # resources to use as dependencies.
+ # TODO(jeremy): "resources_deps": attr.label_list(allow_files=True),
+ #TODO(jeremy): # name of the module if you are creating a module.
+ #TODO(jeremy): "modulename": attri.string(),
+ # warn level to use
+ "warn": attr.int(default=4),
+ # define preprocessor symbols.
+ #TODO(jeremy): "define": attr.string_list(),
+ }
+
+_LIB_ATTRS={"_target_type": attr.string(default="library")}
+
+_EXE_ATTRS={
+ "_target_type": attr.string(default="exe"),
+ # main class to use as entry point.
+ "main_class": attr.string(),
+}
+
+_NUNIT_ATTRS={
+ "_nunit_exe": attr.label(default=Label("@nunit//:nunit_exe"),
+ single_file=True),
+ "_nunit_framework": attr.label(default=Label("@nunit//:nunit_framework")),
+ "_nunit_exe_libs": attr.label(default=Label("@nunit//:nunit_exe_libs")),
+}
+
+_LIB_OUTPUTS={
+ "csc_lib": "%{name}.dll",
+ "doc_xml": "%{name}.xml",
+}
+
+_BIN_OUTPUTS={
+ "csc_exe": "%{name}.exe",
+}
+
+csharp_library = rule(
+ implementation=_csc_compile_impl,
+ attrs=_COMMON_ATTRS + _LIB_ATTRS,
+ outputs = _LIB_OUTPUTS,
+)
+
+csharp_binary = rule(
+ implementation=_csc_compile_impl,
+ attrs=_COMMON_ATTRS + _EXE_ATTRS,
+ outputs = _BIN_OUTPUTS,
+ executable=True)
+
+csharp_nunit_test = rule(
+ implementation=_cs_nunit_run_impl,
+ executable=True,
+ attrs=_COMMON_ATTRS + _LIB_ATTRS +_NUNIT_ATTRS,
+ outputs = _LIB_OUTPUTS,
+ test=True
+)
diff --git a/tools/build_defs/dotnet/dotnet.WORKSPACE b/tools/build_defs/dotnet/dotnet.WORKSPACE
new file mode 100644
index 0000000000..e2ffd93881
--- /dev/null
+++ b/tools/build_defs/dotnet/dotnet.WORKSPACE
@@ -0,0 +1,7 @@
+new_http_archive(
+ name = "nunit",
+ build_file = "tools/build_defs/dotnet/BUILD.nunit",
+ sha256 = "1bd925514f31e7729ccde40a38a512c2accd86895f93465f3dfe6d0b593d7170",
+ type = "zip",
+ url = "https://github.com/nunit/nunitv2/releases/download/2.6.4/NUnit-2.6.4.zip",
+)
diff --git a/tools/build_defs/dotnet/nunit.BUILD b/tools/build_defs/dotnet/nunit.BUILD
new file mode 100644
index 0000000000..30be9c259e
--- /dev/null
+++ b/tools/build_defs/dotnet/nunit.BUILD
@@ -0,0 +1,17 @@
+filegroup(
+ name = "nunit_exe",
+ srcs = ["NUnit-2.6.4/bin/nunit-console.exe"],
+ visibility = ["//visibility:public"],
+)
+
+filegroup(
+ name = "nunit_exe_libs",
+ srcs = glob(["NUnit-2.6.4/bin/lib/*.dll"]),
+ visibility = ["//visibility:public"],
+)
+
+filegroup(
+ name = "nunit_framework",
+ srcs = glob(["NUnit-2.6.4/bin/framework/*.dll"]),
+ visibility = ["//visibility:public"],
+)