diff --git a/.gitignore b/.gitignore
index 828c4b638b034f..601a6a232949b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,7 @@
/bazel-out
/bazel-rules_dotnet
/bazel-testlogs
+.vscode
+_build
+_static
+_templates
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000000000..3ba794aab30bd0
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,85 @@
+# trusty beta image has jdk8, gcc4.8.4
+dist: trusty
+sudo: required
+# xcode8 has jdk8
+osx_image: xcode8.3
+# Not technically required but suppresses 'Ruby' in Job status message.
+language: java
+
+os:
+ - linux
+ - osx
+
+env:
+ # TODO(bazelbuild/continuous-integration#95): re-enable HEAD builds with stable URL
+ # - V=HEAD
+ - V=0.10.0
+
+before_install:
+ - |
+ if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
+ OS=darwin
+ brew install mono
+ else
+ sysctl kernel.unprivileged_userns_clone=1
+ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
+ sudo apt install apt-transport-https
+ echo "deb https://download.mono-project.com/repo/ubuntu stable-trusty main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list
+ sudo apt update
+ sudo apt install mono-devel
+ export RULES_DOTNET_USE_LOCAL_MONO=true
+ OS=linux
+ fi
+ if [[ "${V}" == "HEAD" ]]; then
+ # Determine last successful build number. This may change while we are
+ # downloading, so it's important to determine ahead of time, in case
+ # we need to resume the download.
+ CI_BASE="http://ci.bazel.io/view/Bazel%20bootstrap%20and%20maintenance/job/Bazel/PLATFORM_NAME=${OS}-x86_64/"
+ CI_INDEX_URL="${CI_BASE}/lastSuccessfulBuild/"
+ wget -q -O build-index.html "${CI_INDEX_URL}"
+ CI_BUILD=$(grep '
' build-index.html | sed -e 's/^.*#\([0-9]*\).*$/\1/')
+ # Determine the artifact name. This is normally, bazel--installer.sh,
+ # but it may be, for example, bazel-0.5rc2-installer.sh before a release.
+ CI_ARTIFACT=$(grep -o 'bazel-[^\"-]*-installer.sh' build-index.html | head -n 1)
+ URL="${CI_BASE}/${CI_BUILD}/artifact/output/ci/${CI_ARTIFACT}"
+ rm build-index.html
+ else
+ URL="https://github.com/bazelbuild/bazel/releases/download/${V}/bazel-${V}-installer-${OS}-x86_64.sh"
+ fi
+ wget -O install.sh "${URL}"
+ chmod +x install.sh
+ ./install.sh --user
+ rm -f install.sh
+
+script:
+ - |
+ bazel \
+ --batch \
+ --host_jvm_args=-Xmx500m \
+ --host_jvm_args=-Xms500m \
+ build \
+ -s \
+ --local_resources=400,1,1.0 \
+ //...
+ - |
+ bazel \
+ --batch \
+ --host_jvm_args=-Xmx500m \
+ --host_jvm_args=-Xms500m \
+ run \
+ -s \
+ --local_resources=400,1,1.0 \
+ //tests/examples/example_binary:hello
+ - |
+ bazel \
+ --batch \
+ --host_jvm_args=-Xmx500m \
+ --host_jvm_args=-Xms500m \
+ test \
+ -s \
+ --local_resources=400,1,1.0 \
+ --test_summary=detailed \
+ --test_output=all \
+ //...
+notifications:
+ email: false
\ No newline at end of file
diff --git a/BUILD b/BUILD
new file mode 100644
index 00000000000000..f11861d445ebdf
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,8 @@
+load("@io_bazel_rules_dotnet//dotnet/private:context.bzl", "dotnet_context_data")
+
+dotnet_context_data(
+ name = "dotnet_context_data",
+ visibility = ["//visibility:public"],
+)
+
+exports_files(["AUTHORS"])
diff --git a/README.md b/README.md
deleted file mode 100644
index e7eb0081edf11f..00000000000000
--- a/README.md
+++ /dev/null
@@ -1,478 +0,0 @@
-# C# Rules
-
-| Bazel CI |
-| :---: |
-| [![Build Status](https://ci.bazel.build/buildStatus/icon?job=rules_dotnet)](https://ci.bazel.build/job/rules_dotnet/) |
-
-## Rules
-
-* [csharp_library](#csharp_library)
-* [csharp_binary](#csharp_library)
-* [csharp_nunit_test](#csharp_nunit_test)
-* [nuget_package](#nuget_package)
-* [new_nuget_package](#new_nuget_package)
-* [dll_import](#dll_import)
-
-## Overview
-
-This is a minimal viable set of C# bindings for building C# code with
-[Mono](http://www.mono-project.com/). It's still pretty rough but it
-works as a proof of concept that could grow into something more.
-
-## Caveats
-
-These rules are not compatible with
-[sandboxing](https://bazel.io/blog/2015/09/11/sandboxing.html).
-
-These rules do not currently support Windows and the.NET Framework.
-Issue [#54](https://github.com/bazelbuild/rules_dotnet/issues/54)
-tracks the necessary work. Bazel support for Windows is currently in
-[beta](https://blog.bazel.build/2017/10/16/windows-retrospect.html).
-
-These rules do not currently support .NET Core/Standard built with
-the official compiler on any platform.
-
-## Setup
-
-Add the following to your `WORKSPACE` file to add the external repositories:
-
-```python
-# A newer version should be fine
-http_archive(
- name = "bazel_skylib",
- url = "https://github.com/bazelbuild/bazel-skylib/archive/ff23a62c57d2912c3073a69c12f42c3d6e58a957.zip",
- strip_prefix = "bazel-skylib-ff23a62c57d2912c3073a69c12f42c3d6e58a957",
- sha256 = "ccf83f162e4a265b3aa09445c84fbc470215e392b250c86f0ce00536c99d5c17",
-)
-
-git_repository(
- name = "io_bazel_rules_dotnet",
- remote = "https://github.com/bazelbuild/rules_dotnet.git",
- tag = "0.0.3",
-)
-
-load(
- "@io_bazel_rules_dotnet//dotnet:csharp.bzl",
- "csharp_repositories",
- "nuget_package",
-)
-
-csharp_repositories(use_local_mono = True)
-
-nuget_package(
- name = "Netwonsoft.Json",
- package = "Newtonsoft.Json",
- version = "10.0.3",
-)
-```
-
-The `csharp_repositories` rule fetches external dependencies, namely
-the mono repository, the nuget binary, and the nunit binary. Setting
-the environment variable `RULES_DOTNET_USE_LOCAL_MONO=1` or the rule
-argument `use_local_mono` to `True` will use your installed mono
-framework instead of downloading one. If you are on OS X you can set
-`use_local_mono` to `False` and mono will be downloaded for you by
-bazel.
-
-Support for downloading mono on Linux is coming soon.
-
-## Examples
-
-### csharp_library
-
-```python
-csharp_library(
- name = "MyLib",
- srcs = ["MyLib.cs"],
- deps = ["//my/dependency:SomeLib"],
-)
-```
-
-### csharp_binary
-
-```python
-csharp_binary(
- name = "MyApp",
- main = "MyApp", # optional name of the main class.
- srcs = ["MyApp.cs"],
- deps = ["//my/dependency:MyLib"],
-)
-```
-
-### csharp\_nunit\_test
-
-```python
-csharp_nunit_test(
- name = "MyApp",
- srcs = ["MyApp.cs"],
- deps = ["//my/dependency:MyLib"],
-)
-```
-
-### nuget\_package
-
-In the `WORKSPACE` file for your project record a nuget dependency like so.
-This is a repository rule so it will not work unless it is in a workspace
-file.
-
-```python
-nuget_package(
- name = "ndesk_options",
- package = "NDesk.Options",
- version = "0.2.1",
-)
-```
-
-Now, in a `BUILD` file, you can add the package to your `deps`:
-
-```
-csharp_binary(
- name = "MyApp",
- srcs = ["MyApp.cs"],
- deps = ["@ndesk_options//:dylibs"],
-)
-```
-
-
-
-### new\_nuget\_package
-
-This repository rule accepts either a `BUILD` file label or
-`build_file_content` string. Typically the build content will include
-`dll_import` rules that expose the correct set of libraries to the
-project. For example:
-
-```python
-
-new_nuget_package(
- name = "nuget_grpc",
- package = "Grpc",
- version = "1.0.0",
- build_file_content =
-"""
-load("@io_bazel_rules_dotnet//dotnet:csharp.bzl", "dll_import")
-dll_import(
- name = "system_interactive_async",
- srcs = glob(["System.Interactive.Async.3.0.0/lib/net45/**/*.dll"]),
- visibility = ["//visibility:public"],
-)
-dll_import(
- name = "core",
- srcs = glob(["Grpc.Core.1.0.0/lib/net45/**/*.dll"]),
- visibility = ["//visibility:public"],
-)
-"""
-)
-```
-
-The structure of the nuget_grpc external workspace can be examined
-once downloaded and extracted via `cd $(bazel info
-output_base)/external/nuget_grpc`.
-
-### dll\_import
-
-Add a collection of dotnet assembly dll's to be used as a dependency.
-
-```python
-dll_import(
- name="some_lib",
- srcs=[
- "Some.dll"
- "Some.Other.dll",
- ]
-)
-```
-
-## Things still missing:
-
-- Handle .resx files correctly. See issue [#51](https://github.com/bazelbuild/rules_dotnet/issues/51).
-- .Net Modules
-- Conditionally building documentation.
-- Pulling Mono in through a mono.WORKSPACE file.
- - Still need to implement this for linux.
-- Multiple target framework support for nuget packages.
-
-## Future nice to haves:
-
-- nuget_packages repository rule that will handle multiple different nuget packages in one rule.
-- Building csproj and sln files for VS and MonoDevelop.
-
-
-## csharp_library
-
-```python
-csharp_library(name, srcs, deps, warn=4, csc)
-```
-
-Builds a C# .NET library and its corresponding documentation.
-
-
-
-
-
-
-
-
- Attributes |
-
-
-
-
- name |
-
- Name, required
- Unique name for this rule
- |
-
-
- srcs |
-
- List of Labels; required
- Csharp .cs or .resx files.
- |
-
-
- deps |
-
- List of Labels; optional
- Dependencies for this rule.
- |
-
-
- warn |
-
- Int; optional; default is 4
- Compiler warn level for this library. (Defaults to 4.)
- |
-
-
- csc |
-
- string; optional
- Override the default csharp compiler.
-
- Note: This attribute may removed in future
- versions.
-
- |
-
-
-
-
-
-## csharp_binary
-
-```python
-csharp_binary(name, srcs, deps, main_class, warn=4, csc)
-```
-
-Builds a C# .NET binary.
-
-
-
-
-
-
-
-
- Attributes |
-
-
-
-
- name |
-
- Name, required
- Unique name for this rule
- |
-
-
- srcs |
-
- List of Labels; required
- Csharp .cs or .resx files.
- |
-
-
- deps |
-
- List of Labels; optional
- Dependencies for this rule.
- |
-
-
- main_class |
-
- String; optional
-
Name of class with main() method to use as entry point.
- |
-
-
- warn |
-
- Int; optional; default is 4
- Compiler warn level for this binary. (Defaults to 4.)
- |
-
-
- csc |
-
- string; optional
- Override the default csharp compiler.
-
- Note: This attribute may removed in future
- versions.
-
- |
-
-
-
-
-
-## csharp\_nunit\_test
-
-```python
-csharp_nunit_test(name, srcs, deps, warn=4, csc)
-```
-
-Builds a C# .NET test binary that uses the [NUnit](http://www.nunit.org/) unit
-testing framework.
-
-
-
-
-
-
-
-
- Attributes |
-
-
-
-
- name |
-
- Name, required
- Unique name for this rule
- |
-
-
- srcs |
-
- List of Labels; required
- Csharp .cs or .resx files.
- |
-
-
- deps |
-
- List of Labels; optional
- Dependencies for this rule.
- |
-
-
- warn |
-
- Int; optional; default is 4
- Compiler warn level for this test. (Defaults to 4.)
- |
-
-
- csc |
-
- string; optional
- Override the default csharp compiler.
-
- Note: This attribute may removed in future
- versions.
-
- |
-
-
-
-
-
-## nuget\_package
-
-```python
-nuget_package(name, package, version, package_sources)
-```
-
-A repository_rule that adds a nuget package dependency for the Workspace.
-
-
-
-
-
-
-
-
-
- Attributes |
-
-
-
-
- name |
-
- Name, required
- Unique name for this rule
- |
-
- package |
-
- String, Required
- Name of the nuget package.
- |
-
-
- version |
-
- String, Required
- Version of the nuget package to install.
- |
-
-
- package\_sources |
-
- List of strings, optional
- Sources to pull nuget packages from. Either url or path.
- |
-
-
-
-
-```python
-dll_import(name, srcs)
-```
-
-A repository_rule that adds a nuget package dependency for the Workspace.
-
-
-
-
-
-
-
-
-
- Attributes |
-
-
-
-
- name |
-
- Name, required
- Unique name for this rule
- |
-
-
- srcs |
-
- Labels, required
- List of dotnet dll assemblies to use.
- |
-
-
-
diff --git a/README.rst b/README.rst
new file mode 100644
index 00000000000000..ec7093b4b9ab34
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,207 @@
+C# Rules for Bazel_
+===================
+
+.. All external links are here
+.. _Bazel: https://bazel.build/
+.. |travis| image:: https://travis-ci.org/tomaszstrejczek/rules_dotnet.svg?branch=toolchain
+ :target: https://travis-ci.org/tomaszstrejczek/rules_dotnet
+.. |appvey| image:: https://ci.appveyor.com/api/projects/status/4wlsdo9kgwvt8b97/branch/toolchain?svg=true
+ :target: https://ci.appveyor.com/project/tomaszstrejczek/rules-dotnet/branch/toolchain
+.. _Mono: http://www.mono-project.com/
+.. _sandboxing: https://bazel.io/blog/2015/09/11/sandboxing.html
+.. _dotnet_library: dotnet/core.rst#dotnet_library
+.. _dotnet_binary: dotnet/core.rst#dotnet_binary
+.. _dotnet_nunit_test: dotnet/core.rst#dotnet_nunit_test
+.. _dotnet_resx: dotnet/core.rst#dotnet_resx
+.. _dotnet_import_library: dotnet/core.rst#dotnet_import_library
+.. _dotnet_repositories: dotnet/workspace.rst#dotnet_repositories
+.. _dotnet_register_toolchains: dotnet/toolchains.rst#dotnet_register_toolchains
+.. _dotnet_nuget_new: dotnet/workspace.rst#dotnet_nuget_new
+.. ;;
+
+======== ========
+Travis Appveyor
+======== ========
+|travis| |appvey|
+======== ========
+
+.. contents::
+ :depth: 2
+
+
+Documentation
+~~~~~~~~~~~~~
+
+* `Core API `_
+
+ * `dotnet_library`_
+ * `dotnet_binary`_
+ * `dotnet_nunit_test`_
+ * `dotnet_resx`_
+ * `dotnet_import_library`_
+
+* `Workspace rules `_
+
+* `Toolchains `_
+
+
+Overview
+~~~~~~~~
+
+This is a minimal viable set of C# bindings for building C# code with
+Mono_. It's still pretty rough but it works as a proof of concept that
+could grow into something more.
+
+Caveats
+~~~~~~~
+
+These rules are not compatible with sandboxing_.
+
+These rules do not currently support the .NET Framework.
+
+These rules do not currently support .NET Core/Standard built with
+the official compiler on any platform.
+
+Downloading Mono currently does not work.
+
+Due to Windows short path limit (260) of cl compiler TMP env variable should be
+set to something short (like X:\ or c:\TEMP).
+
+Setup
+~~~~~
+
+* Add the following to your `WORKSPACE` file to add the external repositories:
+
+ .. code:: python
+
+ # A newer version should be fine
+ git_repository(
+ name = "io_bazel_rules_dotnet",
+ remote = "https://github.com/tomek1909/rules_dotnet",
+ tag = "0.0.1",
+ )
+
+ load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_register_toolchains", "dotnet_repositories")
+
+ dotnet_register_toolchains("host")
+
+ dotnet_repositories()
+
+ The dotnet_repositories_ rule fetches external dependencies, namely the nuget binary.
+ The dotnet_register_toolchains_ tries to locate mono binaries and configure toolchains to use it.
+ Support for downloading mono is coming soon.
+
+* Add a file named ``BUILD.bazel`` in the root directory of your
+ project. In general, you need one of these files in every directory
+ with dotnet code.
+ At the top of the file used rules should be imported:
+
+ .. code:: python
+
+ load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_library", "dotnet_binary")
+
+
+Examples
+~~~~~~~~
+
+* dotnet_library_
+
+ .. code:: python
+
+ dotnet_library(
+ name = "foo_bar",
+ srcs = [
+ "foo.cs",
+ "bar.cs",
+ ],
+ deps = [
+ "//examples/example_lib:MyClass",
+ "@npgsql//:npgsqllib",
+ ],
+ visibility = ["//visibility:public"],
+ )
+
+* dotnet_binary_
+
+ .. code:: python
+
+ dotnet_binary(
+ name = "foo_bar",
+ srcs = [
+ "foo.cs",
+ "bar.cs",
+ ],
+ deps = [
+ "//examples/example_lib:MyClass",
+ "@npgsql//:npgsqllib",
+ ],
+ visibility = ["//visibility:public"],
+ )
+
+* dotnet_nunit_test_
+
+ .. code:: python
+
+ dotnet_nunit_test(
+ name = "MyTest",
+ srcs = [
+ "MyTest.cs",
+ ],
+ deps = [
+ "//examples/example_lib:MyClass",
+ "//dotnet/externals/nunit2:nunit.framework",
+ ],
+ )
+
+* dotnet_resx_
+
+ .. code:: python
+
+ dotnet_resx(
+ name = "Transform",
+ src = "//dotnet/externals/nunit2/nunitv2:src/ClientUtilities/util/Transform.resx",
+ )
+
+
+* dotnet_nuget_new_
+
+ In the `WORKSPACE` file for your project record a nuget dependency like so.
+ This is a repository rule so it will not work unless it is in a workspace
+ file.
+
+ .. code:: python
+
+ dotnet_nuget_new(
+ name = "npgsql",
+ package="Npgsql",
+ version="3.2.7",
+ sha256="fa3e0cfbb2caa9946d2ce3d8174031a06320aad2c9e69a60f7739b9ddf19f172",
+ build_file_content = """
+ package(default_visibility = [ "//visibility:public" ])
+ load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_import_library")
+
+ dotnet_import_library(
+ name = "npgsqllib",
+ src = "lib/net451/Npgsql.dll"
+ )
+ """
+ )
+
+ Now, in a `BUILD` file, you can add the package to your `deps`:
+
+ .. code:: python
+
+ dotnet_binary(
+ name = "foo_bar",
+ srcs = [
+ "foo.cs",
+ "bar.cs",
+ ],
+ deps = [
+ "//examples/example_lib:MyClass",
+ "@npgsql//:npgsqllib",
+ ],
+ visibility = ["//visibility:public"],
+ )
+
+
diff --git a/WORKSPACE b/WORKSPACE
index 5b823ed3c1853c..b6d91038e08fa1 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,11 +1,27 @@
workspace(name = "io_bazel_rules_dotnet")
-http_archive(
- name = "bazel_skylib",
- url = "https://github.com/bazelbuild/bazel-skylib/archive/ff23a62c57d2912c3073a69c12f42c3d6e58a957.zip",
- strip_prefix = "bazel-skylib-ff23a62c57d2912c3073a69c12f42c3d6e58a957",
- sha256 = "ccf83f162e4a265b3aa09445c84fbc470215e392b250c86f0ce00536c99d5c17",
+load("//dotnet:defs.bzl", "dotnet_register_toolchains", "dotnet_repositories", "dotnet_nuget_new")
+
+dotnet_repositories()
+dotnet_register_toolchains("host")
+
+dotnet_nuget_new(
+ name = "npgsql",
+ package="Npgsql",
+ version="3.2.7",
+ sha256="fa3e0cfbb2caa9946d2ce3d8174031a06320aad2c9e69a60f7739b9ddf19f172",
+ build_file_content = """
+package(default_visibility = [ "//visibility:public" ])
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_import_library")
+
+dotnet_import_library(
+ name = "npgsqllib",
+ src = "lib/net451/Npgsql.dll"
+)
+ """
)
-load("//dotnet:csharp.bzl", "csharp_repositories")
-csharp_repositories()
+
+load("@io_bazel_rules_dotnet//tests:bazel_tests.bzl", "test_environment")
+
+test_environment()
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 00000000000000..41794a84b65497
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,36 @@
+version: 1.0.{build}
+
+# Maximum number of concurrent jobs for the project
+max_jobs: 1
+
+#---------------------------------#
+# environment configuration #
+#---------------------------------#
+
+# Build worker image (VM template)
+image: Visual Studio 2017
+
+# scripts that are called at very beginning, before repo cloning
+init:
+ - git config --global core.autocrlf input
+
+clone_script:
+- cmd: git clone -q --branch=%APPVEYOR_REPO_BRANCH% https://github.com/%APPVEYOR_REPO_NAME%.git %APPVEYOR_BUILD_FOLDER%
+- cmd: cd %APPVEYOR_BUILD_FOLDER%
+- cmd: git checkout -qf %APPVEYOR_REPO_COMMIT%
+- cmd: git submodule update --init --recursive
+
+install:
+ - choco install mono
+ - choco install bazel
+
+build_script:
+ - ver
+ - bazel --batch --host_jvm_args=-Xmx500m --host_jvm_args=-Xms500m build -s --local_resources=400,1,1.0 //...
+ - bazel --batch --host_jvm_args=-Xmx500m --host_jvm_args=-Xms500m run -s --local_resources=400,1,1.0 //tests/examples/example_binary:hello
+ - bazel --batch --host_jvm_args=-Xmx500m --host_jvm_args=-Xms500m test --test_summary=detailed --test_output=all -s --local_resources=400,1,1.0 //...
+
+test: off
+
+deploy: off
+
diff --git a/conf.py b/conf.py
new file mode 100644
index 00000000000000..c3456dbd8abb0c
--- /dev/null
+++ b/conf.py
@@ -0,0 +1,164 @@
+# -*- coding: utf-8 -*-
+#
+# Configuration file for the Sphinx documentation builder.
+#
+# This file does only contain a selection of the most common options. For a
+# full list see the documentation:
+# http://www.sphinx-doc.org/en/master/config
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+
+# -- Project information -----------------------------------------------------
+
+project = u'rules_dotnet'
+copyright = u'2018, Tomek Strejczek'
+author = u'Tomek Strejczek'
+
+# The short X.Y version
+version = u''
+# The full version, including alpha/beta/rc tags
+release = u'0.0.1'
+
+
+# -- General configuration ---------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'sphinx.ext.todo',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path .
+exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'alabaster'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#
+# html_theme_options = {}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Custom sidebar templates, must be a dictionary that maps document names
+# to template names.
+#
+# The default sidebars (for documents that don't match any pattern) are
+# defined by theme itself. Builtin themes are using these templates by
+# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
+# 'searchbox.html']``.
+#
+# html_sidebars = {}
+
+
+# -- Options for HTMLHelp output ---------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'rules_dotnetdoc'
+
+
+# -- Options for LaTeX output ------------------------------------------------
+
+latex_elements = {
+ # The paper size ('letterpaper' or 'a4paper').
+ #
+ # 'papersize': 'letterpaper',
+
+ # The font size ('10pt', '11pt' or '12pt').
+ #
+ # 'pointsize': '10pt',
+
+ # Additional stuff for the LaTeX preamble.
+ #
+ # 'preamble': '',
+
+ # Latex figure (float) alignment
+ #
+ # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ (master_doc, 'rules_dotnet.tex', u'rules\\_dotnet Documentation',
+ u'Tomek Strejczek', 'manual'),
+]
+
+
+# -- Options for manual page output ------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ (master_doc, 'rules_dotnet', u'rules_dotnet Documentation',
+ [author], 1)
+]
+
+
+# -- Options for Texinfo output ----------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ (master_doc, 'rules_dotnet', u'rules_dotnet Documentation',
+ author, 'rules_dotnet', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+
+# -- Extension configuration -------------------------------------------------
+
+# -- Options for todo extension ----------------------------------------------
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = True
\ No newline at end of file
diff --git a/dotnet/BUILD b/dotnet/BUILD
index 0622f058b90dd0..0bc9afca3f47c9 100644
--- a/dotnet/BUILD
+++ b/dotnet/BUILD
@@ -1,17 +1,5 @@
-# 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"},
+filegroup(
+ name = "all_rules",
+ srcs = glob(["*.bzl"]) + ["//dotnet/private:all_rules"],
+ visibility = ["//visibility:public"],
)
diff --git a/dotnet/NUGET_BUILD.tpl b/dotnet/NUGET_BUILD.tpl
deleted file mode 100644
index e352e165cabdbe..00000000000000
--- a/dotnet/NUGET_BUILD.tpl
+++ /dev/null
@@ -1,7 +0,0 @@
-load("@io_bazel_rules_dotnet//dotnet:csharp.bzl", "dll_import")
-
-dll_import(
- name = "dylibs",
- srcs = glob(["**/*.dll"]),
- visibility = ["//visibility:public"],
-)
diff --git a/dotnet/core.rst b/dotnet/core.rst
new file mode 100644
index 00000000000000..c3c4db16f8b509
--- /dev/null
+++ b/dotnet/core.rst
@@ -0,0 +1,309 @@
+Core dotnet rules
+=================
+
+.. _test_filter: https://docs.bazel.build/versions/master/user-manual.html#flag--test_filter
+.. _test_arg: https://docs.bazel.build/versions/master/user-manual.html#flag--test_arg
+.. _DotnetLibrary: providers.rst#DotnetLibrary
+.. _DotnetResource: providers.rst#DotnetResource
+.. _"Make variable": https://docs.bazel.build/versions/master/be/make-variables.html
+.. _Bourne shell tokenization: https://docs.bazel.build/versions/master/be/common-definitions.html#sh-tokenization
+.. _data dependencies: https://docs.bazel.build/versions/master/build-ref.html#data
+.. _shard_count: https://docs.bazel.build/versions/master/be/common-definitions.html#test.shard_count
+.. _build constraints: https://golang.org/pkg/go/build/#hdr-Build_Constraints
+.. _select: https://docs.bazel.build/versions/master/be/functions.html#select
+.. _config_setting: https://docs.bazel.build/versions/master/be/general.html#config_setting
+.. _dotnet_nuget_new: workspace.rst#dotnet_nuget_new
+
+.. role:: param(kbd)
+.. role:: type(emphasis)
+.. role:: value(code)
+.. |mandatory| replace:: **mandatory value**
+
+These are the core dotnet rules, required for basic operation.
+The intent is that theses rules are sufficient to match the capabilities of the normal dotnet tools.
+
+.. contents:: :depth: 2
+
+-----
+
+API
+---
+
+dotnet_library
+~~~~~~~~~~~~~~
+
+This builds a dotnet assembly from a set of source files.
+
+Providers
+^^^^^^^^^
+
+* DotnetLibrary_
+* DotnetResource_
+
+Attributes
+^^^^^^^^^^
+
++----------------------------+-----------------------------+---------------------------------------+
+| **Name** | **Type** | **Default value** |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+---------------------------------------+
+| A unique name for this rule. |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`deps` | :type:`label_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The direct dependencies of this library. |
+| These may be dotnet_library rules or compatible rules with the DotnetLibrary_ provider. |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`resources` | :type:`label_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The list of resources to compile with. Usually provided via reference to dotnet_resx_ |
+| or the rules compatible with DotnetResource_ provider |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`srcs` | :type:`label_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The list of .cs source files that are compiled to create the assembly. |
+| Only :value:`.cs` files are permitted |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`out` | :type:`string` | :value:`""` |
++----------------------------+-----------------------------+---------------------------------------+
+| An alternative name of the output file |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`defines` | :type:`string_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The list of defines passed via /define compiler option |
++----------------------------+-----------------------------+---------------------------------------+
+
+Example
+^^^^^^^
+
+.. code:: python
+
+ dotnet_library(
+ name = "foo_bar",
+ srcs = [
+ "foo.cs",
+ "bar.cs",
+ ],
+ deps = [
+ "//examples/example_lib:MyClass",
+ "@npgsql//:npgsqllib",
+ ],
+ visibility = ["//visibility:public"],
+ )
+
+dotnet_binary
+~~~~~~~~~~~~~
+
+This builds an executable from a set of source files.
+You can run the binary with ``bazel run``, or you can
+build it with ``bazel build`` and run it directly.
+
+Providers
+^^^^^^^^^
+
+* DotnetLibrary_
+* DotnetResource_
+
+Attributes
+^^^^^^^^^^
+
++----------------------------+-----------------------------+---------------------------------------+
+| **Name** | **Type** | **Default value** |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+---------------------------------------+
+| A unique name for this rule. |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`deps` | :type:`label_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The direct dependencies of this library. |
+| These may be dotnet_library rules or compatible rules with the DotnetLibrary_ provider. |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`resources` | :type:`label_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The list of resources to compile with. Usually provided via reference to dotnet_resx_ |
+| or the rules compatible with DotnetResource_ provider |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`srcs` | :type:`label_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The list of .cs source files that are compiled to create the assembly. |
+| Only :value:`.cs` files are permitted |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`out` | :type:`string` | :value:`""` |
++----------------------------+-----------------------------+---------------------------------------+
+| An alternative name of the output file |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`defines` | :type:`string_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The list of defines passed via /define compiler option |
++----------------------------+-----------------------------+---------------------------------------+
+
+Example
+^^^^^^^
+
+.. code:: python
+
+ dotnet_binary(
+ name = "foo_bar",
+ srcs = [
+ "foo.cs",
+ "bar.cs",
+ ],
+ deps = [
+ "//examples/example_lib:MyClass",
+ "@npgsql//:npgsqllib",
+ ],
+ visibility = ["//visibility:public"],
+ )
+
+dotnet_nunit_test
+~~~~~~~~~~~~~~~~~
+
+This builds a set of tests that can be run with ``bazel test``.
+Currently it uses nunit2.
+
+To run all tests in the workspace, and print output on failure, run
+
+::
+
+ bazel test --test_output=errors //...
+
+You can run specific tests by passing the `--test_filter=pattern `_ argument to Bazel.
+You can pass arguments to tests by passing `--test_arg=arg `_ arguments to Bazel.
+
+
+Attributes
+^^^^^^^^^^
+
++----------------------------+-----------------------------+---------------------------------------+
+| **Name** | **Type** | **Default value** |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+---------------------------------------+
+| A unique name for this rule. |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`deps` | :type:`label_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The direct dependencies of this library. |
+| These may be dotnet_library rules or compatible rules with the DotnetLibrary_ provider. |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`resources` | :type:`label_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The list of resources to compile with. Usually provided via reference to dotnet_resx_ |
+| or the rules compatible with DotnetResource_ provider |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`srcs` | :type:`label_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The list of .cs source files that are compiled to create the assembly. |
+| Only :value:`.cs` files are permitted |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`out` | :type:`string` | :value:`""` |
++----------------------------+-----------------------------+---------------------------------------+
+| An alternative name of the output file |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`defines` | :type:`string_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The list of defines passed via /define compiler option |
++----------------------------+-----------------------------+---------------------------------------+
+
+
+Test example
+^^^^^^^^^^^^
+
+.. code:: python
+
+ dotnet_nunit_test(
+ name = "MyTest",
+ srcs = [
+ "MyTest.cs",
+ ],
+ deps = [
+ "//examples/example_lib:MyClass",
+ "@nunit2//:nunit.framework",
+ ],
+ )
+
+
+dotnet_resx
+~~~~~~~~~~~
+
+This builds a dotnet .resources file from a single .resx file.
+
+Providers
+^^^^^^^^^
+
+* DotnetResource_
+
+Attributes
+^^^^^^^^^^
+
++----------------------------+-----------------------------+---------------------------------------+
+| **Name** | **Type** | **Default value** |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+---------------------------------------+
+| A unique name for this rule. |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`src` | :type:`label` | |mandatory| |
++----------------------------+-----------------------------+---------------------------------------+
+| The .resx source file that is transformed into .resources file. |
+| Only :value:`.resx` files are permitted |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`identifer` | :type:`string` | :value:`""` |
++----------------------------+-----------------------------+---------------------------------------+
+| The logical name for the resource; the name that is used to load the resource. |
+| The default is the basename of the file name (no subfolder). |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`out` | :type:`string` | :value:`""` |
++----------------------------+-----------------------------+---------------------------------------+
+| An alternative name of the output file |
++----------------------------+-----------------------------+---------------------------------------+
+
+Example
+^^^^^^^
+
+.. code:: python
+
+ dotnet_resx(
+ name = "Transform",
+ src = ":src/ClientUtilities/util/Transform.resx",
+ )
+
+
+dotnet_import_library
+~~~~~~~~~~~~~~~~~~~~~
+
+This imports an external dll and transforms it into DotnetLibrary_ so it can be referenced
+as dependency by other rules. Often used with dotnet_nuget_new_.
+
+Providers
+^^^^^^^^^
+
+* DotnetLibrary_
+
+Attributes
+^^^^^^^^^^
+
++----------------------------+-----------------------------+---------------------------------------+
+| **Name** | **Type** | **Default value** |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+---------------------------------------+
+| A unique name for this rule. |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`deps` | :type:`label_list` | :value:`None` |
++----------------------------+-----------------------------+---------------------------------------+
+| The direct dependencies of this dll. |
+| These may be dotnet_library rules or compatible rules with the DotnetLibrary_ provider. |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`src` | :type:`label` | |mandatory| |
++----------------------------+-----------------------------+---------------------------------------+
+| The file to be transformed into DotnetLibrary_ provider |
++----------------------------+-----------------------------+---------------------------------------+
+
+Example
+^^^^^^^
+See dotnet_nuget_new_.
+
+
diff --git a/dotnet/csharp.bzl b/dotnet/csharp.bzl
deleted file mode 100644
index 69e9dd961f040a..00000000000000
--- a/dotnet/csharp.bzl
+++ /dev/null
@@ -1,615 +0,0 @@
-# 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"""
-
-load("@bazel_skylib//lib:dicts.bzl", "dicts")
-
-_MONO_UNIX_BIN = "/usr/local/bin/mono"
-
-# TODO(jeremy): Windows when it's available.
-
-def _make_csc_deps(deps, extra_files=[]):
- dlls = depset()
- refs = depset()
- transitive_dlls = depset()
- 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", "deps")
- if dep_type == "library":
- dlls += [dep.out]
- refs += [dep.name]
- if dep_type == "library_set":
- dlls += dep.out
- refs += [d.basename for d in dep.out]
- if dep.transitive_dlls:
- transitive_dlls += dep.transitive_dlls
-
- return struct(
- dlls = dlls + depset(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=[]):
- args = ctx.actions.args()
-
- # /out:
- args.add(format="/out:%s", value=output.path)
-
- # /target (exe for binary, library for lib, module for module)
- args.add(format="/target:%s", value=ctx.attr._target_type)
-
- # /fullpaths
- args.add("/fullpaths")
-
- # /warn
- args.add(format="/warn:%s", value=str(ctx.attr.warn))
-
- # /nologo
- args.add("/nologo")
-
- # /modulename: only used for modules
- libdirs = _get_libdirs(depinfo.dlls)
- libdirs = _get_libdirs(depinfo.transitive_dlls, libdirs)
-
- # /lib:dir1,[dir1]
- if libdirs:
- args.add(format="/lib:%s", value=libdirs)
-
- # /reference:filename[,filename2]
- if depinfo.refs or extra_refs:
- args.add(format="/reference:%s", value=depinfo.refs + extra_refs)
- else:
- args.add(extra_refs)
-
- # /doc
- if hasattr(ctx.outputs, "doc_xml"):
- args.add(format="/doc:%s", value=ctx.outputs.doc_xml.path)
-
- # /debug
- debug = ctx.var.get("BINMODE", "") == "-dbg"
- if debug:
- args.add("/debug")
-
- # /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.add(format="/main:%s", value=ctx.attr.main_class)
-
- args.add(format="/resource:%s", value=ctx.files.resources)
-
- # TODO(jwall): /parallel
-
- return args
-
-_NUNIT_LAUNCHER_SCRIPT = """\
-#!/bin/bash
-
-if [[ -e "$0.runfiles" ]]; then
- cd $0.runfiles/{workspace}
-fi
-
-# Create top-level symlinks for lib files.
-# TODO(jeremy): This is a gross and fragile hack.
-# We should be able to do better than this.
-for l in {libs}; do
- if [[ ! -e $(basename $l) ]]; then
- # Note: -f required because the symlink may exist
- # even though its current target does not exist.
- ln -s -f $l $(basename $l)
- fi
-done
-
-{mono_exe} {nunit_exe} {libs} "$@"
-"""
-
-def _make_nunit_launcher(ctx, depinfo, output):
- libs = ([d.short_path for d in depinfo.dlls] +
- [d.short_path for d in depinfo.transitive_dlls])
-
- content = _NUNIT_LAUNCHER_SCRIPT.format(
- mono_exe=ctx.file.mono.short_path,
- nunit_exe=ctx.files._nunit_exe[0].short_path,
- libs=" ".join({lib: None for lib in libs}.keys()),
- workspace=ctx.workspace_name)
-
- ctx.file_action(output=ctx.outputs.executable, content=content)
-
-_LAUNCHER_SCRIPT = """\
-#!/bin/bash
-
-set -e
-
-RUNFILES=$0.runfiles/{workspace}
-
-pushd $RUNFILES
-
-# Create top-level symlinks for .exe and lib files.
-# TODO(jeremy): This is a gross and fragile hack.
-# We should be able to do better than this.
-if [[ ! -e $(basename {exe}) ]]; then
- # Note: -f required because the symlink may exist
- # even though its current target does not exist.
- ln -s -f {exe} $(basename {exe})
-fi
-for l in {libs}; do
- if [[ ! -e $(basename {workspace}/$l) ]]; then
- ln -s -f $l $(basename {workspace}/$l)
- fi
-done
-
-popd
-
-$RUNFILES/{mono_exe} $RUNFILES/$(basename {exe}) "$@"
-"""
-
-def _make_launcher(ctx, depinfo, output):
- libs = ([d.short_path for d in depinfo.dlls] +
- [d.short_path for d in depinfo.transitive_dlls])
-
- content = _LAUNCHER_SCRIPT.format(mono_exe=ctx.file.mono.path,
- workspace=ctx.workspace_name,
- 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 = (depset(ctx.files.srcs) + depset(ctx.files.resources) + depinfo.dlls
- + depinfo.transitive_dlls + [ctx.file.csc])
- 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)
-
- csc_args.add(collected_inputs.srcs)
-
- csc_args.set_param_file_format("multiline")
-
- # Use a "response file" to pass arguments to csc.
- # Windows has a max command-line length of around 32k bytes. The default for
- # Args is to spill to param files if the length of the executable, params
- # and spaces between them sum to that number. Unfortunately the math doesn't
- # work out exactly like that on Windows (e.g. there is also a null
- # terminator, escaping.) For now, setting use_always to True is the
- # conservative option. Long command lines are probable with C# due to
- # organizing files by namespace.
- csc_args.use_param_file("@%s", use_always=True)
-
- ctx.actions.run(
- inputs = list(collected_inputs.inputs),
- outputs = all_outputs,
- executable = ctx.file.csc.path,
- arguments = [csc_args],
- progress_message = (
- "Compiling " + ctx.label.package + ":" + ctx.label.name))
-
-def _cs_runfiles(ctx, outputs, depinfo, add_mono=False):
- mono_file = []
- if add_mono:
- mono_file = [ctx.file.mono]
-
- return ctx.runfiles(
- files = outputs,
- transitive_files = depset(depinfo.dlls + depinfo.transitive_dlls + mono_file) 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, add_mono=True)
-
- _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 = depset([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,
- add_mono=True)
-
- _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 = (depset([output])
- if hasattr(ctx.outputs, "csc_lib") else None),
- transitive_dlls = depinfo.dlls,
- runfiles=runfiles)
-
-def _find_and_symlink(repository_ctx, binary, env_variable):
- #repository_ctx.file("bin/empty")
- if env_variable in repository_ctx.os.environ:
- return repository_ctx.path(repository_ctx.os.environ[env_variable])
- else:
- found_binary = repository_ctx.which(binary)
- if found_binary == None:
- fail("Cannot find %s. Either correct your path or set the " % binary +
- "%s environment variable." % env_variable)
- repository_ctx.symlink(found_binary, "bin/%s" % binary)
-
-def _csharp_autoconf(repository_ctx):
- _find_and_symlink(repository_ctx, "mono", "MONO")
- _find_and_symlink(repository_ctx, "mcs", "CSC")
- toolchain_build = """\
-package(default_visibility = ["//visibility:public"])
-exports_files(["mono", "mcs"])
-"""
- repository_ctx.file("bin/BUILD", toolchain_build)
-
-_COMMON_ATTRS = {
- # 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.
- "resources": 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(),
- # The mono binary and csharp compiler.
- "mono": attr.label(
- default = Label("@mono//bin:mono"),
- allow_files = True,
- single_file = True,
- executable = True,
- cfg = "host",
- ),
- "csc": attr.label(
- default = Label("@mono//bin:mcs"),
- allow_files = True,
- single_file = True,
- executable = True,
- cfg = "host",
- ),
-}
-
-_LIB_ATTRS = {
- "_target_type": attr.string(default="library")
-}
-
-_NUGET_ATTRS = {
- "srcs": attr.label_list(allow_files = FileType([".dll"])),
- "_target_type": attr.string(default="library_set")
-}
-
-_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 = dict(_COMMON_ATTRS.items() + _LIB_ATTRS.items()),
- outputs = _LIB_OUTPUTS,
-)
-"""Builds a C# .NET library and its corresponding documentation.
-
-Args:
- name: A unique name for this rule.
- srcs: C# `.cs` or `.resx` files.
- deps: Dependencies for this rule
- warn: Compiler warning level for this library. (Defaults to 4).
- csc: Override the default C# compiler.
-
- **Note:** This attribute may be removed in future versions.
-"""
-
-csharp_binary = rule(
- implementation = _csc_compile_impl,
- attrs = dict(_COMMON_ATTRS.items() + _EXE_ATTRS.items()),
- outputs = _BIN_OUTPUTS,
- executable = True,
-)
-"""Builds a C# .NET binary.
-
-Args:
- name: A unique name for this rule.
- srcs: C# `.cs` or `.resx` files.
- deps: Dependencies for this rule
- main_class: Name of class with `main()` method to use as entry point.
- warn: Compiler warning level for this library. (Defaults to 4).
- csc: Override the default C# compiler.
-
- **Note:** This attribute may be removed in future versions.
-"""
-
-csharp_nunit_test = rule(
- implementation = _cs_nunit_run_impl,
- executable = True,
- attrs = dict(_COMMON_ATTRS.items() + _LIB_ATTRS.items() +
- _NUNIT_ATTRS.items()),
- outputs = _LIB_OUTPUTS,
- test = True,
-)
-"""Builds a C# .NET test binary that uses the [NUnit](http://nunit.org) unit
-testing framework.
-
-Args:
- name: A unique name for this rule.
- srcs: C# `.cs` or `.resx` files.
- deps: Dependencies for this rule
- warn: Compiler warning level for this library. (Defaults to 4).
- csc: Override the default C# compiler.
-
- **Note:** This attribute may be removed in future versions.
-"""
-
-def _dll_import_impl(ctx):
- inputs = depset(ctx.files.srcs)
- return struct(
- name = ctx.label.name,
- target_type = ctx.attr._target_type,
- out = inputs,
- dlls = inputs,
- transitive_dlls = depset(),
- )
-
-dll_import = rule(
- implementation = _dll_import_impl,
- attrs = _NUGET_ATTRS,
-)
-
-def _nuget_package_impl(repository_ctx,
- build_file = None,
- build_file_content = None):
- # figure out the output_path
- package = repository_ctx.attr.package
- output_dir = repository_ctx.path("")
-
- mono = repository_ctx.path(repository_ctx.attr.mono_exe)
- nuget = repository_ctx.path(repository_ctx.attr.nuget_exe)
-
- # assemble our nuget command
- nuget_cmd = [
- mono,
- "--config", "%s/../etc/mono/config" % mono.dirname,
- nuget,
- "install",
- "-Version", repository_ctx.attr.version,
- "-OutputDirectory", output_dir,
- ]
- # add the sources from our source list to the command
- for source in repository_ctx.attr.package_sources:
- nuget_cmd += ["-Source", source]
-
- # Lastly we add the nuget package name.
- nuget_cmd += [repository_ctx.attr.package]
- # execute nuget download.
- result = repository_ctx.execute(nuget_cmd)
- if result.return_code:
- fail("Nuget command failed: %s (%s)" % (result.stderr, " ".join(nuget_cmd)))
-
- if build_file_content:
- repository_ctx.file("BUILD", build_file_content)
- elif build_file:
- repository_ctx.symlink(repository_ctx.path(build_file), "BUILD")
- else:
- tpl_file = Label("//dotnet:NUGET_BUILD.tpl")
- # add the BUILD file
- repository_ctx.template(
- "BUILD",
- tpl_file,
- {"%{package}": repository_ctx.name,
- "%{output_dir}": "%s" % output_dir})
-
-_nuget_package_attrs = {
- # Sources to download the nuget packages from
- "package_sources":attr.string_list(),
- # The name of the nuget package
- "package":attr.string(mandatory=True),
- # The version of the nuget package
- "version":attr.string(mandatory=True),
- # Reference to the mono binary
- "mono_exe":attr.label(
- executable=True,
- default=Label("@mono//bin:mono"),
- cfg="host",
- ),
- # Reference to the nuget.exe file
- "nuget_exe":attr.label(
- default=Label("@nuget//:nuget.exe"),
- ),
-}
-
-nuget_package = repository_rule(
- implementation=_nuget_package_impl,
- attrs=_nuget_package_attrs,
-)
-"""Fetches a nuget package as an external dependency.
-
-Args:
- package_sources: list of sources to use for nuget package feeds.
- package: name of the nuget package.
- version: version of the nuget package (e.g. 0.1.2)
- mono_exe: optional label to the mono executable.
- nuget_exe: optional label to the nuget.exe file.
-"""
-
-def _new_nuget_package_impl(repository_ctx):
- build_file = repository_ctx.attr.build_file
- build_file_content = repository_ctx.attr.build_file_content
- if not (build_file_content or build_file):
- fail("build_file or build_file_content is required")
- _nuget_package_impl(repository_ctx, build_file, build_file_content)
-
-new_nuget_package = repository_rule(
- implementation=_new_nuget_package_impl,
- attrs=dicts.add(_nuget_package_attrs, {
- "build_file": attr.label(
- allow_files = True,
- ),
- "build_file_content": attr.string(),
- }))
-"""Fetches a nuget package as an external dependency with custom BUILD content.
-
-Args:
- package_sources: list of sources to use for nuget package feeds.
- package: name of the nuget package.
- version: version of the nuget package (e.g. 0.1.2)
- mono_exe: optional label to the mono executable.
- nuget_exe: optional label to the nuget.exe file.
- build_file: label to the BUILD file.
- build_file_content: content for the BUILD file.
-"""
-
-csharp_autoconf = repository_rule(
- implementation = _csharp_autoconf,
- local = True,
-)
-
-def _mono_osx_repository_impl(repository_ctx):
- download_output = repository_ctx.path("")
- # download the package
- repository_ctx.download_and_extract(
- "http://bazel-mirror.storage.googleapis.com/download.mono-project.com/archive/4.2.3/macos-10-x86/MonoFramework-MDK-4.2.3.4.macos10.xamarin.x86.tar.gz",
- download_output,
- "a7afb92d4a81f17664a040c8f36147e57a46bb3c33314b73ec737ad73608e08b",
- "", "mono")
-
- # now we create the build file.
- toolchain_build = """
-package(default_visibility = ["//visibility:public"])
-exports_files(["mono", "mcs"])
-"""
- repository_ctx.file("bin/BUILD", toolchain_build)
-
-def _mono_repository_impl(repository_ctx):
- use_local = repository_ctx.os.environ.get(
- "RULES_DOTNET_USE_LOCAL_MONO", repository_ctx.attr.use_local)
- if use_local:
- _csharp_autoconf(repository_ctx)
- elif repository_ctx.os.name.find("mac") != -1:
- _mono_osx_repository_impl(repository_ctx)
- else:
- fail("Unsupported operating system: %s" % repository_ctx.os.name)
-
-mono_package = repository_rule(
- implementation = _mono_repository_impl,
- attrs = {
- "use_local": attr.bool(default=False),
- },
- local = True,
-)
-
-def csharp_repositories(use_local_mono=False):
- """Adds the repository rules needed for using the C# rules."""
-
- native.new_http_archive(
- name = "nunit",
- url = "http://bazel-mirror.storage.googleapis.com/github.com/nunit/nunitv2/releases/download/2.6.4/NUnit-2.6.4.zip",
- sha256 = "1bd925514f31e7729ccde40a38a512c2accd86895f93465f3dfe6d0b593d7170",
- type = "zip",
- # This is a little weird but is necessary for the build file reference to
- # work when Workspaces import this using a repository rule.
- build_file = str(Label("//dotnet:nunit.BUILD")),
- )
-
- native.new_http_archive(
- name = "nuget",
- url = "https://github.com/mono/nuget-binary/archive/0811ba888a80aaff66a93a4c98567ce904ab2663.zip", # Sept 6, 2016
- sha256 = "28323d23b7e6e02d3ba8892f525a1457ad23adb7e3a48908d37c1b5ae37519f6",
- strip_prefix = "nuget-binary-0811ba888a80aaff66a93a4c98567ce904ab2663",
- type = "zip",
- build_file_content = """
- package(default_visibility = ["//visibility:public"])
- exports_files(["nuget.exe"])
- """
- )
-
- mono_package(name="mono", use_local=use_local_mono)
diff --git a/dotnet/defs.bzl b/dotnet/defs.bzl
new file mode 100644
index 00000000000000..9eeb4001706348
--- /dev/null
+++ b/dotnet/defs.bzl
@@ -0,0 +1,53 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:context.bzl",
+ dotnet_context = "dotnet_context",
+)
+load(
+ "@io_bazel_rules_dotnet//dotnet/toolchain:toolchains.bzl",
+ "dotnet_register_toolchains",
+)
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:sdk.bzl",
+ dotnet_download_sdk = "dotnet_download_sdk",
+ dotnet_host_sdk = "dotnet_host_sdk",
+ dotnet_local_sdk = "dotnet_local_sdk",
+)
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:dotnet_toolchain.bzl",
+ dotnet_toolchain = "dotnet_toolchain",
+)
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:repositories.bzl",
+ dotnet_repositories = "dotnet_repositories",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:rules/binary.bzl",
+ dotnet_binary = "dotnet_binary"
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:rules/library.bzl",
+ dotnet_library = "dotnet_library"
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:rules/resx.bzl",
+ dotnet_resx = "dotnet_resx"
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:rules/test.bzl",
+ dotnet_nunit_test = "dotnet_nunit_test"
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:rules/nuget.bzl",
+ dotnet_nuget = "dotnet_nuget",
+ dotnet_nuget_new = "dotnet_nuget_new"
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:rules/import.bzl",
+ dotnet_import_library = "dotnet_import_library"
+)
diff --git a/dotnet/externals/BUILD b/dotnet/externals/BUILD
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/dotnet/externals/BUILD.nunit2 b/dotnet/externals/BUILD.nunit2
new file mode 100644
index 00000000000000..aaaf53ec0b3741
--- /dev/null
+++ b/dotnet/externals/BUILD.nunit2
@@ -0,0 +1,494 @@
+package(default_visibility = ["//visibility:public"])
+
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_library", "dotnet_binary", "dotnet_resx")
+
+dotnet_library(
+ name = "nunit.core.interfaces",
+ srcs = [":NUnitCore_Interfaces_files"],
+ defines = ["CLR_4_0"],
+ visibility = ["//visibility:public"],
+ deps = ["@io_bazel_rules_dotnet//dotnet/stdlib:System.dll"]
+)
+
+dotnet_library(
+ name = "nunit.framework",
+ srcs = [":NUnitFramework_framework_files"],
+ defines = ["CLR_4_0"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.dll",
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.Data.dll",
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.Xml.dll",
+ ]
+)
+
+dotnet_library(
+ name = "nunit.core",
+ srcs = [":NUnitCore_core_files"],
+ defines = ["CLR_4_0"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.dll",
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.Configuration.dll",
+ ":nunit.core.interfaces",
+ ]
+)
+
+dotnet_library(
+ name = "nunit.util",
+ srcs = [":ClientUtilities_util_files"],
+ resources = [":Transform"],
+ defines = ["CLR_4_0"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.dll",
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.Configuration.dll",
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.Runtime.Remoting.dll",
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.Drawing.dll",
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.Xml.dll",
+ ":nunit.core.interfaces",
+ ":nunit.core",
+ ]
+)
+
+dotnet_resx(
+ name = "Transform",
+ src = ":src/ClientUtilities/util/Transform.resx",
+)
+
+dotnet_library(
+ name = "nunit-console-runner",
+ srcs = [":ConsoleRunner_nunit_console_files"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.dll",
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.Xml.dll",
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.Drawing.dll",
+ ":nunit.core.interfaces",
+ ":nunit.core",
+ ":nunit.util",
+ ]
+)
+
+dotnet_binary(
+ name = "nunit-console-runner-exe",
+ srcs = [":ConsoleRunner_nunit_console_exe_files"],
+ deps = [
+ "@io_bazel_rules_dotnet//dotnet/stdlib:System.dll",
+ ":nunit-console-runner",
+ ":nunit.core",
+ ":nunit.util",
+ ]
+)
+
+
+filegroup(
+ name = "common_assembly_info_files",
+ srcs = [":src/CommonAssemblyInfo.cs"],
+)
+
+filegroup(
+ name = "NUnitCore_Interfaces_files",
+ srcs = [":common_assembly_info_files",
+ ":src/NUnitFramework/framework/ITestCaseData.cs",
+ ":src/NUnitCore/interfaces/EventListener.cs",
+ ":src/NUnitCore/interfaces/IAgency.cs",
+ ":src/NUnitCore/interfaces/IService.cs",
+ ":src/NUnitCore/interfaces/ITest.cs",
+ ":src/NUnitCore/interfaces/ITestFilter.cs",
+ ":src/NUnitCore/interfaces/LoggingThreshold.cs",
+ ":src/NUnitCore/interfaces/OSPlatform.cs",
+ ":src/NUnitCore/interfaces/PropertyNames.cs",
+ ":src/NUnitCore/interfaces/ResultState.cs",
+ ":src/NUnitCore/interfaces/RunState.cs",
+ ":src/NUnitCore/interfaces/RuntimeFramework.cs",
+ ":src/NUnitCore/interfaces/Test.cs",
+ ":src/NUnitCore/interfaces/TestAgent.cs",
+ ":src/NUnitCore/interfaces/TestAssemblyInfo.cs",
+ ":src/NUnitCore/interfaces/TestFilter.cs",
+ ":src/NUnitCore/interfaces/TestID.cs",
+ ":src/NUnitCore/interfaces/TestInfo.cs",
+ ":src/NUnitCore/interfaces/TestName.cs",
+ ":src/NUnitCore/interfaces/TestNode.cs",
+ ":src/NUnitCore/interfaces/TestOutput.cs",
+ ":src/NUnitCore/interfaces/TestPackage.cs",
+ ":src/NUnitCore/interfaces/TestResult.cs",
+ ":src/NUnitCore/interfaces/TestRunner.cs",
+ ":src/NUnitCore/interfaces/Extensibility/Addin.cs",
+ ":src/NUnitCore/interfaces/Extensibility/AddinStatus.cs",
+ ":src/NUnitCore/interfaces/Extensibility/ExtensionType.cs",
+ ":src/NUnitCore/interfaces/Extensibility/IAddin.cs",
+ ":src/NUnitCore/interfaces/Extensibility/IAddinRegistry.cs",
+ ":src/NUnitCore/interfaces/Extensibility/IDataPointProvider.cs",
+ ":src/NUnitCore/interfaces/Extensibility/IExtensionHost.cs",
+ ":src/NUnitCore/interfaces/Extensibility/IExtensionPoint.cs",
+ ":src/NUnitCore/interfaces/Extensibility/IFrameworkRegistry.cs",
+ ":src/NUnitCore/interfaces/Extensibility/ISuiteBuilder.cs",
+ ":src/NUnitCore/interfaces/Extensibility/ITestCaseBuilder.cs",
+ ":src/NUnitCore/interfaces/Extensibility/ITestCaseProvider.cs",
+ ":src/NUnitCore/interfaces/Extensibility/ITestDecorator.cs",
+ ":src/NUnitCore/interfaces/Extensibility/NUnitAddinAttribute.cs",
+ ":src/NUnitCore/interfaces/Extensibility/ParameterSet.cs",
+ ":src/NUnitCore/interfaces/Extensibility/TestFramework.cs",
+ ":src/NUnitCore/interfaces/Filters/AndFilter.cs",
+ ":src/NUnitCore/interfaces/Filters/CategoryFilter.cs",
+ ":src/NUnitCore/interfaces/Filters/NameFilter.cs",
+ ":src/NUnitCore/interfaces/Filters/NotFilter.cs",
+ ":src/NUnitCore/interfaces/Filters/OrFilter.cs",
+ ":src/NUnitCore/interfaces/Filters/SimpleNameFilter.cs",
+ ]
+)
+
+filegroup(
+ name = "NUnitFramework_framework_files",
+ srcs = [":common_assembly_info_files",
+ ":src/NUnitFramework/framework/AsyncSynchronizationContext.cs",
+ ":src/NUnitFramework/framework/AsyncInvocationRegion.cs",
+ ":src/NUnitFramework/framework/Attributes/CategoryAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/DatapointAttributes.cs",
+ ":src/NUnitFramework/framework/Attributes/DescriptionAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/ExpectedExceptionAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/ExplicitAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/IgnoreAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/IncludeExcludeAttributes.cs",
+ ":src/NUnitFramework/framework/Attributes/JoinTypeAttributes.cs",
+ ":src/NUnitFramework/framework/Attributes/MaxTimeAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/PropertyAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/RandomAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/RangeAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/RepeatAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/RequiredAddinAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/SetCultureAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/SetUICultureAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/SetUpAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/SetUpFixtureAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/SuiteAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/TearDownAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/TestActionAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/TestAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/TestCaseAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/TestCaseSourceAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/TestFixtureAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/TestFixtureSetUpAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/TestFixtureTearDownAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/TheoryAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/ThreadingAttributes.cs",
+ ":src/NUnitFramework/framework/Attributes/ValuesAttribute.cs",
+ ":src/NUnitFramework/framework/Attributes/ValueSourceAttribute.cs",
+ ":src/NUnitFramework/framework/Exceptions/AssertionException.cs",
+ ":src/NUnitFramework/framework/Exceptions/IgnoreException.cs",
+ ":src/NUnitFramework/framework/Exceptions/InconclusiveException.cs",
+ ":src/NUnitFramework/framework/Exceptions/SuccessException.cs",
+ ":src/NUnitFramework/framework/Interfaces/INUnitEqualityComparer.cs",
+ ":src/NUnitFramework/framework/Interfaces/ITestAction.cs",
+ ":src/NUnitFramework/framework/ActionTargets.cs",
+ ":src/NUnitFramework/framework/Assert.cs",
+ ":src/NUnitFramework/framework/AssertionHelper.cs",
+ ":src/NUnitFramework/framework/Assume.cs",
+ ":src/NUnitFramework/framework/CollectionAssert.cs",
+ ":src/NUnitFramework/framework/Contains.cs",
+ ":src/NUnitFramework/framework/DirectoryAssert.cs",
+ ":src/NUnitFramework/framework/FileAssert.cs",
+ ":src/NUnitFramework/framework/GlobalSettings.cs",
+ ":src/NUnitFramework/framework/Guard.cs",
+ ":src/NUnitFramework/framework/Has.cs",
+ ":src/NUnitFramework/framework/IExpectException.cs",
+ ":src/NUnitFramework/framework/Is.cs",
+ ":src/NUnitFramework/framework/Iz.cs",
+ ":src/NUnitFramework/framework/ITestCaseData.cs",
+ ":src/NUnitFramework/framework/List.cs",
+ ":src/NUnitFramework/framework/ListMapper.cs",
+ ":src/NUnitFramework/framework/Randomizer.cs",
+ ":src/NUnitFramework/framework/SpecialValue.cs",
+ ":src/NUnitFramework/framework/StringAssert.cs",
+ ":src/NUnitFramework/framework/TestCaseData.cs",
+ ":src/NUnitFramework/framework/TestContext.cs",
+ ":src/NUnitFramework/framework/TestDetails.cs",
+ ":src/NUnitFramework/framework/TestState.cs",
+ ":src/NUnitFramework/framework/TestStatus.cs",
+ ":src/NUnitFramework/framework/Text.cs",
+ ":src/NUnitFramework/framework/TextMessageWriter.cs",
+ ":src/NUnitFramework/framework/Throws.cs",
+ ":src/NUnitFramework/framework/Constraints/AllItemsConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/AndConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/AssignableFromConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/AssignableToConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/AttributeConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/AttributeExistsConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/BasicConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/BinaryConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/BinarySerializableConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/CollectionConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/CollectionContainsConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/CollectionEquivalentConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/CollectionItemsEqualConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/CollectionOrderedConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/CollectionSubsetConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/CollectionTally.cs",
+ ":src/NUnitFramework/framework/Constraints/ComparisonAdapter.cs",
+ ":src/NUnitFramework/framework/Constraints/ComparisonConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/Constraint.cs",
+ ":src/NUnitFramework/framework/Constraints/ConstraintBuilder.cs",
+ ":src/NUnitFramework/framework/Constraints/ConstraintExpression.cs",
+ ":src/NUnitFramework/framework/Constraints/ConstraintExpressionBase.cs",
+ ":src/NUnitFramework/framework/Constraints/ConstraintFactory.cs",
+ ":src/NUnitFramework/framework/Constraints/ContainsConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/DelayedConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/EmptyCollectionConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/EmptyConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/EmptyDirectoryConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/EmptyStringConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/EndsWithConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/EqualConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/EqualityAdapter.cs",
+ ":src/NUnitFramework/framework/Constraints/ExactCountConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/ExactTypeConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/ExceptionTypeConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/FailurePoint.cs",
+ ":src/NUnitFramework/framework/Constraints/FalseConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/FloatingPointNumerics.cs",
+ ":src/NUnitFramework/framework/Constraints/GreaterThanConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/GreaterThanOrEqualConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/IResolveConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/InstanceOfTypeConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/LessThanConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/LessThanOrEqualConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/MessageWriter.cs",
+ ":src/NUnitFramework/framework/Constraints/MsgUtils.cs",
+ ":src/NUnitFramework/framework/Constraints/NUnitComparer.cs",
+ ":src/NUnitFramework/framework/Constraints/NUnitEqualityComparer.cs",
+ ":src/NUnitFramework/framework/Constraints/NaNConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/NoItemConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/NotConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/NullConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/NullOrEmptyStringConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/Numerics.cs",
+ ":src/NUnitFramework/framework/Constraints/OrConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/PathConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/PredicateConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/PrefixConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/PropertyConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/PropertyExistsConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/RangeConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/RegexConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/ResolvableConstraintExpression.cs",
+ ":src/NUnitFramework/framework/Constraints/ReusableConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/SameAsConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/SamePathConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/SamePathOrUnderConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/SomeItemsConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/StartsWithConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/StringConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/SubPathConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/SubstringConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/ThrowsConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/ThrowsNothingConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/Tolerance.cs",
+ ":src/NUnitFramework/framework/Constraints/ToleranceMode.cs",
+ ":src/NUnitFramework/framework/Constraints/TrueConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/TypeConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/UniqueItemsConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/XmlSerializableConstraint.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/AllOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/AndOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/AttributeOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/BinaryOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/CollectionOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/ConstraintOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/ExactCountOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/NoneOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/NotOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/OrOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/PrefixOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/PropOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/SelfResolvingOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/SomeOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/ThrowsOperator.cs",
+ ":src/NUnitFramework/framework/Constraints/Operators/WithOperator.cs",
+ ]
+)
+
+filegroup(
+ name = "NUnitCore_core_files",
+ srcs = [":common_assembly_info_files",
+ ":src/NUnitFramework/framework/AsyncSynchronizationContext.cs",
+ ":src/NUnitFramework/framework/AsyncInvocationRegion.cs",
+ ":src/NUnitCore/core/AbstractTestCaseDecoration.cs",
+ ":src/NUnitCore/core/AssemblyHelper.cs",
+ ":src/NUnitCore/core/AssemblyReader.cs",
+ ":src/NUnitCore/core/AssemblyResolver.cs",
+ ":src/NUnitCore/core/ActionsHelper.cs",
+ ":src/NUnitCore/core/Builders/CombinatorialStrategy.cs",
+ ":src/NUnitCore/core/Builders/CombinatorialTestCaseProvider.cs",
+ ":src/NUnitCore/core/Builders/CombiningStrategy.cs",
+ ":src/NUnitCore/core/Builders/DatapointProvider.cs",
+ ":src/NUnitCore/core/Builders/InlineDataPointProvider.cs",
+ ":src/NUnitCore/core/Builders/LegacySuiteBuilder.cs",
+ ":src/NUnitCore/core/Builders/NUnitTestCaseBuilder.cs",
+ ":src/NUnitCore/core/Builders/NUnitTestFixtureBuilder.cs",
+ ":src/NUnitCore/core/Builders/PairwiseStrategy.cs",
+ ":src/NUnitCore/core/Builders/ProviderCache.cs",
+ ":src/NUnitCore/core/Builders/ProviderInfo.cs",
+ ":src/NUnitCore/core/Builders/SequentialStrategy.cs",
+ ":src/NUnitCore/core/Builders/SetUpFixtureBuilder.cs",
+ ":src/NUnitCore/core/Builders/TestAssemblyBuilder.cs",
+ ":src/NUnitCore/core/Builders/TestCaseParameterProvider.cs",
+ ":src/NUnitCore/core/Builders/TestCaseSourceProvider.cs",
+ ":src/NUnitCore/core/UnsupportedFrameworkException.cs",
+ ":src/NUnitCore/core/Builders/ValueSourceProvider.cs",
+ ":src/NUnitCore/core/ContextDictionary.cs",
+ ":src/NUnitCore/core/CoreExtensions.cs",
+ ":src/NUnitCore/core/CultureDetector.cs",
+ ":src/NUnitCore/core/DirectorySwapper.cs",
+ ":src/NUnitCore/core/DomainAgent.cs",
+ ":src/NUnitCore/core/EventListenerTextWriter.cs",
+ ":src/NUnitCore/core/EventPump.cs",
+ ":src/NUnitCore/core/EventQueue.cs",
+ ":src/NUnitCore/core/ExpectedExceptionProcessor.cs",
+ ":src/NUnitCore/core/Extensibility/DataPointProviders.cs",
+ ":src/NUnitCore/core/Extensibility/EventListenerCollection.cs",
+ ":src/NUnitCore/core/Extensibility/FrameworkRegistry.cs",
+ ":src/NUnitCore/core/Extensibility/SuiteBuilderCollection.cs",
+ ":src/NUnitCore/core/Extensibility/TestCaseBuilderCollection.cs",
+ ":src/NUnitCore/core/Extensibility/TestCaseProviders.cs",
+ ":src/NUnitCore/core/Extensibility/TestDecoratorCollection.cs",
+ ":src/NUnitCore/core/ExtensionHost.cs",
+ ":src/NUnitCore/core/ExtensionPoint.cs",
+ ":src/NUnitCore/core/IgnoreDecorator.cs",
+ ":src/NUnitCore/core/InternalTrace.cs",
+ ":src/NUnitCore/core/InternalTraceWriter.cs",
+ ":src/NUnitCore/core/InvalidSuiteException.cs",
+ ":src/NUnitCore/core/InvalidTestFixtureException.cs",
+ ":src/NUnitCore/core/LegacySuite.cs",
+ ":src/NUnitCore/core/Log4NetCapture.cs",
+ ":src/NUnitCore/core/Logger.cs",
+ ":src/NUnitCore/core/MethodHelper.cs",
+ ":src/NUnitCore/core/NamespaceSuite.cs",
+ ":src/NUnitCore/core/NamespaceTreeBuilder.cs",
+ ":src/NUnitCore/core/NoTestFixturesException.cs",
+ ":src/NUnitCore/core/NullListener.cs",
+ ":src/NUnitCore/core/NUnitAsyncTestMethod.cs",
+ ":src/NUnitCore/core/NUnitConfiguration.cs",
+ ":src/NUnitCore/core/NUnitException.cs",
+ ":src/NUnitCore/core/NUnitFramework.cs",
+ ":src/NUnitCore/core/NUnitTestFixture.cs",
+ ":src/NUnitCore/core/NUnitTestMethod.cs",
+ ":src/NUnitCore/core/ParameterizedFixtureSuite.cs",
+ ":src/NUnitCore/core/ParameterizedTestMethodSuite.cs",
+ ":src/NUnitCore/core/PlatformHelper.cs",
+ ":src/NUnitCore/core/ProjectRootSuite.cs",
+ ":src/NUnitCore/core/ProxyTestRunner.cs",
+ ":src/NUnitCore/core/QueuingEventListener.cs",
+ ":src/NUnitCore/core/Reflect.cs",
+ ":src/NUnitCore/core/RemoteTestRunner.cs",
+ ":src/NUnitCore/core/SetUpFixture.cs",
+ ":src/NUnitCore/core/SimpleTestRunner.cs",
+ ":src/NUnitCore/core/StringTextWriter.cs",
+ ":src/NUnitCore/core/SuiteBuilderAttribute.cs",
+ ":src/NUnitCore/core/TestAction.cs",
+ ":src/NUnitCore/core/TestAssembly.cs",
+ ":src/NUnitCore/core/TestBuilderAttribute.cs",
+ ":src/NUnitCore/core/TestCaseBuilderAttribute.cs",
+ ":src/NUnitCore/core/TestDecoratorAttribute.cs",
+ ":src/NUnitCore/core/TestExecutionContext.cs",
+ ":src/NUnitCore/core/TestFixture.cs",
+ ":src/NUnitCore/core/TestFixtureBuilder.cs",
+ ":src/NUnitCore/core/TestMethod.cs",
+ ":src/NUnitCore/core/TestRunnerThread.cs",
+ ":src/NUnitCore/core/TestSuite.cs",
+ ":src/NUnitCore/core/TestSuiteBuilder.cs",
+ ":src/NUnitCore/core/TestThread.cs",
+ ":src/NUnitCore/core/TextCapture.cs",
+ ":src/NUnitCore/core/ThreadedTestRunner.cs",
+ ":src/NUnitCore/core/ThreadUtility.cs",
+ ":src/NUnitCore/core/TypeHelper.cs",
+ ]
+)
+
+filegroup(
+ name = "ClientUtilities_util_files",
+ srcs = [":common_assembly_info_files",
+ ":src/ClientUtilities/util/AggregatingTestRunner.cs",
+ ":src/ClientUtilities/util/AssemblyList.cs",
+ ":src/ClientUtilities/util/AssemblyWatcher.cs",
+ ":src/ClientUtilities/util/CategoryExpression.cs",
+ ":src/ClientUtilities/util/CategoryManager.cs",
+ ":src/ClientUtilities/util/CommandLineOptions.cs",
+ ":src/ClientUtilities/util/ConsoleWriter.cs",
+ ":src/ClientUtilities/util/DefaultTestRunnerFactory.cs",
+ ":src/ClientUtilities/util/FileWatcher.cs",
+ ":src/ClientUtilities/util/Guard.cs",
+ ":src/ClientUtilities/util/IAssemblyWatcher.cs",
+ ":src/ClientUtilities/util/InProcessTestRunnerFactory.cs",
+ ":src/ClientUtilities/util/MemorySettingsStorage.cs",
+ ":src/ClientUtilities/util/NUnitProject.cs",
+ ":src/ClientUtilities/util/NUnitRegistry.cs",
+ ":src/ClientUtilities/util/PathUtils.cs",
+ ":src/ClientUtilities/util/ProcessRunner.cs",
+ ":src/ClientUtilities/util/ProjectConfig.cs",
+ ":src/ClientUtilities/util/ProjectConfigCollection.cs",
+ ":src/ClientUtilities/util/ProjectFormatException.cs",
+ ":src/ClientUtilities/util/RecentFileEntry.cs",
+ ":src/ClientUtilities/util/RecentFiles.cs",
+ ":src/ClientUtilities/util/RecentFilesCollection.cs",
+ ":src/ClientUtilities/util/RegistrySettingsStorage.cs",
+ ":src/ClientUtilities/util/RemoteTestAgent.cs",
+ ":src/ClientUtilities/util/ResultSummarizer.cs",
+ ":src/ClientUtilities/util/RuntimeFrameworkSelector.cs",
+ ":src/ClientUtilities/util/ServerBase.cs",
+ ":src/ClientUtilities/util/ServerUtilities.cs",
+ ":src/ClientUtilities/util/Services.cs",
+ ":src/ClientUtilities/util/SettingsGroup.cs",
+ ":src/ClientUtilities/util/SettingsStorage.cs",
+ ":src/ClientUtilities/util/StackTraceFilter.cs",
+ ":src/ClientUtilities/util/TestDomain.cs",
+ ":src/ClientUtilities/util/TestEventArgs.cs",
+ ":src/ClientUtilities/util/TestEventDispatcher.cs",
+ ":src/ClientUtilities/util/TestExceptionHandler.cs",
+ ":src/ClientUtilities/util/TestLabelLevel.cs",
+ ":src/ClientUtilities/util/TestLoader.cs",
+ ":src/ClientUtilities/util/TestObserver.cs",
+ ":src/ClientUtilities/util/TestResultItem.cs",
+ ":src/ClientUtilities/util/TestServer.cs",
+ ":src/ClientUtilities/util/VSProject.cs",
+ ":src/ClientUtilities/util/VSProjectConfig.cs",
+ ":src/ClientUtilities/util/VSProjectConfigCollection.cs",
+ ":src/ClientUtilities/util/XmlResultTransform.cs",
+ ":src/ClientUtilities/util/XmlResultWriter.cs",
+ ":src/ClientUtilities/util/XmlSettingsStorage.cs",
+ ":src/ClientUtilities/util/Extensibility/IProjectConverter.cs",
+ ":src/ClientUtilities/util/Extensibility/ProjectConverterCollection.cs",
+ ":src/ClientUtilities/util/Interfaces/IRuntimeFrameworkSelector.cs",
+ ":src/ClientUtilities/util/Interfaces/ISettings.cs",
+ ":src/ClientUtilities/util/Interfaces/ITestEvents.cs",
+ ":src/ClientUtilities/util/Interfaces/ITestLoader.cs",
+ ":src/ClientUtilities/util/Interfaces/ITestRunnerFactory.cs",
+ ":src/ClientUtilities/util/ProjectConverters/VisualStudioConverter.cs",
+ ":src/ClientUtilities/util/Services/AddinManager.cs",
+ ":src/ClientUtilities/util/Services/AddinRegistry.cs",
+ ":src/ClientUtilities/util/Services/DomainManager.cs",
+ ":src/ClientUtilities/util/Services/ProjectService.cs",
+ ":src/ClientUtilities/util/Services/RecentFilesService.cs",
+ ":src/ClientUtilities/util/Services/ServiceManager.cs",
+ ":src/ClientUtilities/util/Services/SettingsService.cs",
+ ":src/ClientUtilities/util/Services/TestAgency.cs",
+ ]
+)
+
+filegroup(
+ name = "ConsoleRunner_nunit_console_files",
+ srcs = [":common_assembly_info_files",
+ ":src/ConsoleRunner/nunit-console/ConsoleOptions.cs",
+ ":src/ConsoleRunner/nunit-console/ConsoleUi.cs",
+ ":src/ConsoleRunner/nunit-console/EventCollector.cs",
+ ":src/ConsoleRunner/nunit-console/Runner.cs",
+ ":src/ConsoleRunner/nunit-console/TestNameParser.cs",
+ ]
+)
+
+filegroup(
+ name = "ConsoleRunner_nunit_console_exe_files",
+ srcs = [":common_assembly_info_files",
+ ":src/ConsoleRunner/nunit-console-exe/Class1.cs",
+ ]
+)
diff --git a/dotnet/platform/BUILD b/dotnet/platform/BUILD
new file mode 100644
index 00000000000000..d5e37e854017fc
--- /dev/null
+++ b/dotnet/platform/BUILD
@@ -0,0 +1,13 @@
+# This file declares a config_setting for each platform supported by the
+# Dotnet. These rules follow a os_arch naming convention, for example,
+# //dotnet/platform:linux_amd64
+#
+# These can be used in select expressions to choose platform-specifc
+# sources and dependencies.
+
+package(default_visibility = ["//visibility:public"])
+
+load(":list.bzl", "declare_config_settings")
+
+declare_config_settings()
+
diff --git a/dotnet/platform/list.bzl b/dotnet/platform/list.bzl
new file mode 100644
index 00000000000000..75fcb06a341ada
--- /dev/null
+++ b/dotnet/platform/list.bzl
@@ -0,0 +1,48 @@
+DOTNETIMPL = {
+ "mono": None,
+}
+
+DOTNETOS = {
+ "darwin": "@bazel_tools//platforms:osx",
+ "linux": "@bazel_tools//platforms:linux",
+ "windows": "@bazel_tools//platforms:windows",
+}
+
+DOTNETARCH = {
+ "amd64": "@bazel_tools//platforms:x86_64",
+}
+
+DOTNETIMPL_OS_ARCH = (
+ ("mono", "darwin", "amd64"),
+ ("mono", "linux", "amd64"),
+ ("mono", "windows", "amd64"),
+)
+
+def declare_config_settings():
+ for impl in DOTNETIMPL:
+ native.config_setting(
+ name = impl,
+ #constraint_values = ["//dotnet/toolchain:" + impl],
+ values = {
+ "compilation_mode": impl
+ }
+ )
+ for os in DOTNETOS:
+ native.config_setting(
+ name = os,
+ constraint_values = ["//dotnet/toolchain:" + os],
+ )
+ for arch in DOTNETARCH:
+ native.config_setting(
+ name = arch,
+ constraint_values = ["//dotnet/toolchain:" + arch],
+ )
+ for arch, os, arch in DOTNETIMPL_OS_ARCH:
+ native.config_setting(
+ name = arch + "_" + os + "_" + arch,
+ constraint_values = [
+ "//dotnet/toolchain:" + os,
+ "//dotnet/toolchain:" + arch,
+ "//dotnet/toolchain:" + impl,
+ ],
+ )
diff --git a/dotnet/private/BUILD b/dotnet/private/BUILD
new file mode 100644
index 00000000000000..307f7845ee61d3
--- /dev/null
+++ b/dotnet/private/BUILD
@@ -0,0 +1,7 @@
+
+filegroup(
+ name = "all_rules",
+ srcs = glob(["**/*.bzl"]),
+ visibility = ["//visibility:public"],
+)
+
diff --git a/dotnet/private/BUILD.nuget.bazel b/dotnet/private/BUILD.nuget.bazel
new file mode 100644
index 00000000000000..890f810ea75500
--- /dev/null
+++ b/dotnet/private/BUILD.nuget.bazel
@@ -0,0 +1,8 @@
+package(default_visibility = [ "//visibility:public" ])
+
+filegroup(
+ name = "files",
+ srcs = glob([
+ "**/*.dll",
+ ]),
+)
diff --git a/dotnet/private/BUILD.sdk.bazel b/dotnet/private/BUILD.sdk.bazel
new file mode 100644
index 00000000000000..04daea87b1a35b
--- /dev/null
+++ b/dotnet/private/BUILD.sdk.bazel
@@ -0,0 +1,22 @@
+package(default_visibility = [ "//visibility:public" ])
+
+filegroup(
+ name = "mcs_bin",
+ srcs = glob([
+ "mcs_bin/*",
+ ]),
+)
+
+filegroup(
+ name = "mono_bin",
+ srcs = glob([
+ "mono_bin/*",
+ ]),
+)
+
+filegroup(
+ name = "lib",
+ srcs = glob([
+ "lib/**/*",
+ ]),
+)
diff --git a/dotnet/private/actions/assembly.bzl b/dotnet/private/actions/assembly.bzl
new file mode 100644
index 00000000000000..3e81ffb802c9b1
--- /dev/null
+++ b/dotnet/private/actions/assembly.bzl
@@ -0,0 +1,144 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:common.bzl",
+ "as_iterable",
+ "sets"
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:providers.bzl",
+ "DotnetLibrary",
+ "DotnetResource",
+)
+
+
+def _map_dep(deps):
+ return [d[DotnetLibrary].result for d in deps]
+
+def _map_resource(resources):
+ return [d[DotnetResource].result.path + "," + d[DotnetResource].identifier for d in resources]
+
+def _make_runner_arglist(dotnet, deps, resources, output, executable, defines):
+ args = dotnet.actions.args()
+
+ # /out:
+ args.add(format="/out:%s", value=output.path)
+
+ if executable:
+ target = "exe"
+ else:
+ target = "library"
+
+ # /target (exe for binary, library for lib, module for module)
+ args.add(format="/target:%s", value=target)
+
+ args.add("/fullpaths")
+ args.add("/noconfig")
+ args.add("/nostdlib")
+
+ # /warn
+ #args.add(format="/warn:%s", value=str(ctx.attr.warn))
+
+ # /nologo
+ args.add("/nologo")
+
+ # /modulename: only used for modules
+ #libdirs = _get_libdirs(depinfo.dlls)
+ #libdirs = _get_libdirs(depinfo.transitive_dlls, libdirs)
+
+ # /lib:dir1,[dir1]
+ #if libdirs:
+ # args.add(format="/lib:%s", value=libdirs)
+
+ if deps and len(deps)>0:
+ args.add(format="/reference:%s", value=deps, map_fn=_map_dep)
+
+ args.add(format="/reference:%s", value=dotnet.stdlib)
+
+ if defines and len(defines)>0:
+ args.add(format="/define:%s", value=defines)
+
+ # /debug
+ #debug = ctx.var.get("BINMODE", "") == "-dbg"
+ #if debug:
+ # args.add("/debug")
+
+ # /warnaserror
+ # TODO(jeremy): /define:name[;name2]
+
+ if resources and len(resources)>0:
+ args.add(format="/resource:%s", value=resources, map_fn=_map_resource)
+
+ # TODO(jeremy): /resource:filename[,identifier[,accesibility-modifier]]
+
+ # /main:class
+ #if hasattr(ctx.attr, "main_class") and ctx.attr.main_class:
+ # args.add(format="/main:%s", value=ctx.attr.main_class)
+
+ #args.add(format="/resource:%s", value=ctx.files.resources)
+
+ # TODO(jwall): /parallel
+
+ return args
+
+def emit_assembly(dotnet,
+ name = "",
+ srcs = None,
+ deps = None,
+ out = None,
+ resources = None,
+ executable = True,
+ defines = None):
+ """See dotnet/toolchains.rst#binary for full documentation."""
+
+ if name == "" and out == None:
+ fail("either name or out must be set")
+
+ if not out:
+ if executable:
+ extension = ".exe"
+ else:
+ extension = ".dll"
+ result = dotnet.declare_file(dotnet, path=name+extension)
+ else:
+ result = dotnet.declare_file(dotnet, path=out)
+ extension = ""
+
+ runner_args = _make_runner_arglist(dotnet, deps, resources, result, executable, defines)
+
+ attr_srcs = [f for t in srcs for f in as_iterable(t.files)]
+ runner_args.add(attr_srcs)
+
+ runner_args.set_param_file_format("multiline")
+
+ # Use a "response file" to pass arguments to csc.
+ # Windows has a max command-line length of around 32k bytes. The default for
+ # Args is to spill to param files if the length of the executable, params
+ # and spaces between them sum to that number. Unfortunately the math doesn't
+ # work out exactly like that on Windows (e.g. there is also a null
+ # terminator, escaping.) For now, setting use_always to True is the
+ # conservative option. Long command lines are probable with C# due to
+ # organizing files by namespace.
+ paramfilepath = name+extension+".param"
+ paramfile = dotnet.declare_file(dotnet, path=paramfilepath)
+
+ dotnet.actions.write(output = paramfile, content = runner_args)
+
+ deps_files = _map_dep(deps)
+ dotnet.actions.run(
+ inputs = attr_srcs + [paramfile] + deps_files + [dotnet.stdlib] + [r[DotnetResource].result for r in resources],
+ outputs = [result],
+ executable = dotnet.runner,
+ arguments = [dotnet.mcs.path, "@"+paramfile.path],
+ progress_message = (
+ "Compiling " + dotnet.label.package + ":" + dotnet.label.name))
+
+ deps_libraries = [d[DotnetLibrary] for d in deps]
+ transitive = sets.union(deps_libraries, *[a[DotnetLibrary].transitive for a in deps])
+
+ return dotnet.new_library(
+ dotnet = dotnet,
+ name = name,
+ deps = deps,
+ transitive = transitive,
+ result = result)
+
diff --git a/dotnet/private/actions/binary.bzl b/dotnet/private/actions/binary.bzl
new file mode 100644
index 00000000000000..6c0a3cb01cf8e8
--- /dev/null
+++ b/dotnet/private/actions/binary.bzl
@@ -0,0 +1,23 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:actions/assembly.bzl",
+ "emit_assembly",
+)
+
+def emit_binary(dotnet,
+ name = "",
+ srcs = None,
+ deps = None,
+ resources = None,
+ out = None,
+ defines = None):
+
+ return emit_assembly(
+ dotnet = dotnet,
+ name = name,
+ srcs = srcs,
+ deps = deps,
+ resources = resources,
+ out = out,
+ executable = True,
+ defines = defines,
+ )
diff --git a/dotnet/private/actions/library.bzl b/dotnet/private/actions/library.bzl
new file mode 100644
index 00000000000000..14f6836cfc5baa
--- /dev/null
+++ b/dotnet/private/actions/library.bzl
@@ -0,0 +1,23 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:actions/assembly.bzl",
+ "emit_assembly",
+)
+
+def emit_library(dotnet,
+ name = "",
+ srcs = None,
+ deps = None,
+ resources = None,
+ out = None,
+ defines = None):
+
+ return emit_assembly(
+ dotnet = dotnet,
+ name = name,
+ srcs = srcs,
+ deps = deps,
+ resources = resources,
+ out = out,
+ executable = False,
+ defines = defines,
+ )
diff --git a/dotnet/private/actions/resx.bzl b/dotnet/private/actions/resx.bzl
new file mode 100644
index 00000000000000..105657139046ff
--- /dev/null
+++ b/dotnet/private/actions/resx.bzl
@@ -0,0 +1,65 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:common.bzl",
+ "as_iterable",
+ "sets"
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:providers.bzl",
+ "DotnetLibrary",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:common.bzl",
+ "paths",
+)
+
+
+def _make_runner_arglist(dotnet, source, output):
+ args = dotnet.actions.args()
+
+ args.add(dotnet.resgen.path)
+ args.add(format = "%s", value = source.files)
+
+ return args
+
+def emit_resx(dotnet,
+ name = "",
+ src = None,
+ identifier = None,
+ out = None):
+
+ if name == "" and out == None:
+ fail("either name or out must be set")
+
+ if not out:
+ result = dotnet.declare_file(dotnet, path=name+".resources")
+ else:
+ result = dotnet.declare_file(dotnet, path=out)
+
+ # Unfortunately, resgen always produces the output in the same directory as the input file
+ # Therefore we have to copy the source file to the target directory
+ copied_source = dotnet.declare_file(dotnet, path=paths.replace_extension(result.basename, ".resx"))
+
+ dotnet.actions.run_shell(
+ inputs = src.files,
+ outputs = [copied_source],
+ command = "cp {} {}".format(src.files.to_list()[0].path, copied_source.path),
+ )
+
+ args = _make_runner_arglist(dotnet, src, result)
+
+ dotnet.actions.run(
+ inputs = [copied_source],
+ outputs = [result],
+ executable = dotnet.runner,
+ arguments = [dotnet.resgen.path, copied_source.path],
+ progress_message = (
+ "Compiling resoources" + dotnet.label.package + ":" + dotnet.label.name))
+
+ return dotnet.new_resource(
+ dotnet = dotnet,
+ name = name,
+ result = result,
+ identifier = identifier)
+
diff --git a/dotnet/private/common.bzl b/dotnet/private/common.bzl
new file mode 100644
index 00000000000000..7aaaaf436a6ee5
--- /dev/null
+++ b/dotnet/private/common.bzl
@@ -0,0 +1,44 @@
+load("//dotnet/private:skylib/lib/paths.bzl", "paths")
+load("//dotnet/private:skylib/lib/sets.bzl", "sets")
+
+
+def executable_extension(ctx):
+ extension = ""
+ if ctx.os.name.startswith('windows'):
+ extension = ".exe"
+ return extension
+
+def bat_extension(ctx):
+ extension = ""
+ if ctx.os.name.startswith('windows'):
+ extension = ".bat"
+ return extension
+
+def as_iterable(v):
+ if type(v) == "list":
+ return v
+ if type(v) == "tuple":
+ return v
+ if type(v) == "depset":
+ return v.to_list()
+ fail("as_iterator failed on {}".format(v))
+
+def env_execute(ctx, arguments, environment = {}, **kwargs):
+ """env_executes a command in a repository context. It prepends "env -i"
+ to "arguments" before calling "ctx.execute".
+
+ Variables that aren't explicitly mentioned in "environment"
+ are removed from the environment. This should be preferred to "ctx.execut"e
+ in most situations.
+ """
+ if ctx.os.name.startswith('windows'):
+ return ctx.execute(arguments, environment=environment, **kwargs)
+ env_args = ["env", "-i"]
+ environment = dict(environment)
+ for var in ["TMP", "TMPDIR"]:
+ if var in ctx.os.environ and not var in environment:
+ environment[var] = ctx.os.environ[var]
+ for k, v in environment.items():
+ env_args.append("%s=%s" % (k, v))
+ arguments = env_args + arguments
+ return ctx.execute(arguments, **kwargs)
diff --git a/dotnet/private/context.bzl b/dotnet/private/context.bzl
new file mode 100644
index 00000000000000..73c22059da9fa8
--- /dev/null
+++ b/dotnet/private/context.bzl
@@ -0,0 +1,153 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:providers.bzl",
+ "DotnetLibrary",
+ "DotnetResource",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:common.bzl",
+ "paths",
+)
+
+
+DotnetContext = provider()
+
+def _get_dotnet_runner(context_data, ext):
+ for f in context_data._mono_bin.files:
+ basename = paths.basename(f.path)
+ if basename != "mono" + ext:
+ continue
+ return f
+ fail("Could not find mono executable in dotnet_sdk (mono_bin)")
+
+def _get_dotnet_mcs(context_data):
+ for f in context_data._mcs_bin.files:
+ basename = paths.basename(f.path)
+ if basename != "mcs.exe":
+ continue
+ return f
+
+ for f in context_data._lib.files:
+ basename = paths.basename(f.path)
+ if basename != "mcs.exe":
+ continue
+ return f
+ fail("Could not find mcs.exe in dotnet_sdk (mcs_bin, lib)")
+
+def _get_dotnet_resgen(context_data):
+ for f in context_data._mcs_bin.files:
+ basename = paths.basename(f.path)
+ if basename != "resgen.exe":
+ continue
+ return f
+
+ for f in context_data._lib.files:
+ basename = paths.basename(f.path)
+ if basename != "resgen.exe":
+ continue
+ return f
+
+ fail("Could not find resgen.exe in dotnet_sdk (mcs_bin, lib)")
+
+def _get_dotnet_stdlib(context_data):
+ for f in context_data._lib.files:
+ basename = paths.basename(f.path)
+ if basename != "mscorlib.dll":
+ continue
+ dirname = paths.dirname(f.path)
+ if dirname.find(context_data._libVersion)==-1:
+ continue
+ return f
+ fail("Could not find mscorlib in dotnet_sdk (lib, %s)" % context_data._libVersion)
+
+def _declare_file(dotnet, path = None, ext = None):
+ result = path if path else dotnet._ctx.label.name
+ if ext:
+ result += ext
+ return dotnet.actions.declare_file(result)
+
+
+def _new_library(dotnet, name=None, deps=None, transitive=None, **kwargs):
+ return DotnetLibrary(
+ name = dotnet.label.name if not name else name,
+ label = dotnet.label,
+ deps = deps,
+ transitive = transitive,
+ **kwargs
+ )
+
+def _new_resource(dotnet, name, result, identifier=None, **kwargs):
+ return DotnetResource(
+ name = name,
+ label = dotnet.label,
+ result = result,
+ identifier = result.basename if not identifier else identifier,
+ **kwargs
+ )
+
+def dotnet_context(ctx, attr=None):
+ toolchain = ctx.toolchains["@io_bazel_rules_dotnet//dotnet:toolchain"]
+
+ if not attr:
+ attr = ctx.attr
+
+ context_data = attr._dotnet_context_data
+ ext = ""
+ if toolchain.default_dotnetos == "windows":
+ ext = ".exe"
+ runner = _get_dotnet_runner(context_data, ext)
+ mcs = _get_dotnet_mcs(context_data)
+ stdlib = _get_dotnet_stdlib(context_data)
+ resgen = _get_dotnet_resgen(context_data)
+
+ return DotnetContext(
+ # Fields
+ label = ctx.label,
+ toolchain = toolchain,
+ actions = ctx.actions,
+ binary = toolchain.actions.binary,
+ library = toolchain.actions.library,
+ resx = toolchain.actions.resx,
+ exe_extension = ext,
+ runner = runner,
+ mcs = mcs,
+ stdlib = stdlib,
+ resgen = resgen,
+ declare_file = _declare_file,
+ new_library = _new_library,
+ new_resource = _new_resource,
+ workspace_name = ctx.workspace_name,
+ libVersion = context_data._libVersion,
+ lib = context_data._lib,
+ _ctx = ctx
+ )
+
+def _dotnet_context_data(ctx):
+ return struct(
+ _mcs_bin = ctx.attr._mcs_bin,
+ _mono_bin = ctx.attr._mono_bin,
+ _lib = ctx.attr._lib,
+ _libVersion = ctx.attr._libVersion,
+ )
+
+dotnet_context_data = rule(
+ _dotnet_context_data,
+ attrs = {
+ "_mcs_bin": attr.label(
+ allow_files = True,
+ default="@dotnet_sdk//:mcs_bin",
+ ),
+ "_mono_bin": attr.label(
+ allow_files = True,
+ default="@dotnet_sdk//:mono_bin",
+ ),
+ "_lib": attr.label(
+ allow_files = True,
+ default="@dotnet_sdk//:lib",
+ ),
+ "_libVersion": attr.string(
+ default="4.5",
+ ),
+ },
+)
+
diff --git a/dotnet/private/dotnet_toolchain.bzl b/dotnet/private/dotnet_toolchain.bzl
new file mode 100644
index 00000000000000..031a89ac6b53ae
--- /dev/null
+++ b/dotnet/private/dotnet_toolchain.bzl
@@ -0,0 +1,75 @@
+# Copyright 2016 The Bazel Go Rules 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.
+"""
+Toolchain rules used by dotnet.
+"""
+
+load("@io_bazel_rules_dotnet//dotnet/private:actions/binary.bzl", "emit_binary")
+load("@io_bazel_rules_dotnet//dotnet/private:actions/library.bzl", "emit_library")
+load("@io_bazel_rules_dotnet//dotnet/private:actions/resx.bzl", "emit_resx")
+
+def _dotnet_toolchain_impl(ctx):
+ return [platform_common.ToolchainInfo(
+ name = ctx.label.name,
+ default_dotnetimpl = ctx.attr.dotnetimpl,
+ default_dotnetos = ctx.attr.dotnetos,
+ default_dotnetarch = ctx.attr.dotnetarch,
+ actions = struct(
+ binary = emit_binary,
+ library = emit_library,
+ resx = emit_resx,
+ ),
+ flags = struct(
+ compile = (),
+ ),
+ )]
+
+_dotnet_toolchain = rule(
+ _dotnet_toolchain_impl,
+ attrs = {
+ # Minimum requirements to specify a toolchain
+ "dotnetimpl": attr.string(mandatory = True),
+ "dotnetos": attr.string(mandatory = True),
+ "dotnetarch": attr.string(mandatory = True),
+ },
+)
+
+def dotnet_toolchain(name, host, constraints=[], **kwargs):
+ """See dotnet/toolchains.rst#dotnet-toolchain for full documentation."""
+
+ elems = host.split("_")
+ impl, os, arch = elems[0], elems[1], elems[2]
+ host_constraints = constraints + [
+ #"@io_bazel_rules_dotnet//dotnet/toolchain:" + impl,
+ "@io_bazel_rules_dotnet//dotnet/toolchain:" + os,
+ "@io_bazel_rules_dotnet//dotnet/toolchain:" + arch,
+ ]
+
+ impl_name = name + "-impl"
+ _dotnet_toolchain(
+ name = impl_name,
+ dotnetimpl = impl,
+ dotnetos = os,
+ dotnetarch = arch,
+ tags = ["manual"],
+ visibility = ["//visibility:public"],
+ **kwargs
+ )
+ native.toolchain(
+ name = name,
+ toolchain_type = "@io_bazel_rules_dotnet//dotnet:toolchain",
+ exec_compatible_with = host_constraints,
+ #target_compatible_with = host_constraints,
+ toolchain = ":"+impl_name,
+ )
diff --git a/dotnet/private/providers.bzl b/dotnet/private/providers.bzl
new file mode 100644
index 00000000000000..37c8cf7b6e84ca
--- /dev/null
+++ b/dotnet/private/providers.bzl
@@ -0,0 +1,12 @@
+
+DotnetLibrary = provider()
+"""
+A represenatation of the dotnet binary.
+See dotnet/providers.rst#DotnetLibrary for full documentation.
+"""
+
+DotnetResource = provider()
+"""
+A represenatation of the dotnet compiled resource (.resources).
+See dotnet/providers.rst#DotnetResource for full documentation.
+"""
diff --git a/dotnet/private/repositories.bzl b/dotnet/private/repositories.bzl
new file mode 100644
index 00000000000000..a3f6387dfade1c
--- /dev/null
+++ b/dotnet/private/repositories.bzl
@@ -0,0 +1,16 @@
+def dotnet_repositories():
+ native.http_file(
+ name = "nuget",
+ url = "https://dist.nuget.org/win-x86-commandline/v4.6.2/nuget.exe",
+ sha256 = "2c562c1a18d720d4885546083ec8eaad6773a6b80befb02564088cc1e55b304e",
+ )
+
+ native.new_http_archive(
+ name = "nunit2",
+ url = "https://github.com/nunit/nunitv2/archive/2.6.4.zip",
+ sha256 = "2db7b4356e7cd9ac022c3f211853e39ae7b3587915124b555c7c39f712902c28",
+ strip_prefix = "nunitv2-2.6.4",
+ build_file = "@io_bazel_rules_dotnet//dotnet/externals:BUILD.nunit2",
+ )
+
+
diff --git a/dotnet/private/rules/binary.bzl b/dotnet/private/rules/binary.bzl
new file mode 100644
index 00000000000000..f8055d50f664bd
--- /dev/null
+++ b/dotnet/private/rules/binary.bzl
@@ -0,0 +1,65 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:context.bzl",
+ "dotnet_context",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:providers.bzl",
+ "DotnetLibrary",
+ "DotnetResource",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:rules/launcher_gen.bzl",
+ "dotnet_launcher_gen",
+)
+
+def _dotnet_binary_impl(ctx):
+ """dotnet_binary_impl emits actions for compiling dotnet executable assembly."""
+ dotnet = dotnet_context(ctx)
+ name = ctx.label.name
+
+ executable = dotnet.binary(dotnet,
+ name = name,
+ srcs = ctx.attr.srcs,
+ deps = ctx.attr.deps,
+ resources = ctx.attr.resources,
+ out = ctx.attr.out,
+ defines = ctx.attr.defines,
+ )
+
+ transitive_files = [d.result for d in executable.transitive.to_list()]
+
+ return [
+ DefaultInfo(
+ files = depset([executable.result]),
+ runfiles = ctx.runfiles(files = [dotnet.stdlib, dotnet.runner], transitive_files=depset(direct=transitive_files)),
+ executable = executable.result,
+ ),
+ ]
+
+_dotnet_binary = rule(
+ _dotnet_binary_impl,
+ attrs = {
+ "deps": attr.label_list(providers=[DotnetLibrary]),
+ "resources": attr.label_list(providers=[DotnetResource]),
+ "srcs": attr.label_list(allow_files = FileType([".cs"])),
+ "out": attr.string(),
+ "defines": attr.string_list(),
+ "_dotnet_context_data": attr.label(default = Label("@io_bazel_rules_dotnet//:dotnet_context_data")),
+ },
+ toolchains = ["@io_bazel_rules_dotnet//dotnet:toolchain"],
+ executable = True,
+)
+
+def dotnet_binary(name, srcs, deps = [], defines = None, out = None):
+ _dotnet_binary(name = "%s_exe" % name, deps = deps, srcs = srcs, out = out, defines = defines)
+ exe = ":%s_exe" % name
+ dotnet_launcher_gen(name = "%s_launcher" % name, exe = exe)
+
+ native.cc_binary(
+ name=name,
+ srcs = [":%s_launcher" % name],
+ deps = ["@io_bazel_rules_dotnet//dotnet/tools/runner", "@io_bazel_rules_dotnet//dotnet/tools/common"],
+ data = [exe],
+ )
\ No newline at end of file
diff --git a/dotnet/private/rules/import.bzl b/dotnet/private/rules/import.bzl
new file mode 100644
index 00000000000000..eaf2e87e52a550
--- /dev/null
+++ b/dotnet/private/rules/import.bzl
@@ -0,0 +1,54 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:context.bzl",
+ "dotnet_context",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:providers.bzl",
+ "DotnetLibrary",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:common.bzl",
+ "sets"
+)
+
+
+def _dotnet_imort_library_impl(ctx):
+ """dotnet_import_library_impl emits actions for importing an external dll (for example provided by nuget)."""
+ dotnet = dotnet_context(ctx)
+ name = ctx.label.name
+
+ deps = ctx.attr.deps
+ src = ctx.attr.src
+
+ deps_libraries = [d[DotnetLibrary] for d in deps]
+ transitive = sets.union(deps_libraries, *[a[DotnetLibrary].transitive for a in deps])
+
+ library = dotnet.new_library(
+ dotnet = dotnet,
+ name = name,
+ deps = deps,
+ transitive = transitive,
+ result = src.files.to_list()[0])
+
+ transitive_files = [d.result for d in library.transitive.to_list()]
+
+ return [
+ library,
+ DefaultInfo(
+ files = depset([library.result]),
+ runfiles = ctx.runfiles(files = [dotnet.stdlib, library.result], transitive_files=depset(direct=transitive_files)),
+ ),
+ ]
+
+dotnet_import_library = rule(
+ _dotnet_imort_library_impl,
+ attrs = {
+ "deps": attr.label_list(providers=[DotnetLibrary]),
+ "src": attr.label(allow_files = FileType([".dll"]), mandatory=True),
+ "_dotnet_context_data": attr.label(default = Label("@io_bazel_rules_dotnet//:dotnet_context_data"))
+ },
+ toolchains = ["@io_bazel_rules_dotnet//dotnet:toolchain"],
+ executable = False,
+)
\ No newline at end of file
diff --git a/dotnet/private/rules/launcher_gen.bzl b/dotnet/private/rules/launcher_gen.bzl
new file mode 100644
index 00000000000000..95f789a9adf0b0
--- /dev/null
+++ b/dotnet/private/rules/launcher_gen.bzl
@@ -0,0 +1,44 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:context.bzl",
+ "dotnet_context",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:providers.bzl",
+ "DotnetLibrary",
+)
+
+_TEMPLATE = """
+const char * Exe = "{}";
+const char * Nunit = "{}";
+"""
+
+def _dotnet_launcher_gen_impl(ctx):
+ """dotnet_launcher_gen_impl emits actions that generates .c file necessary to build launcher."""
+ dotnet = dotnet_context(ctx)
+ name = ctx.label.name
+ exe = ctx.attr.exe.files.to_list()[0]
+ nunit = ""
+ if ctx.attr.nunit:
+ nunit = ctx.attr.nunit.files.to_list()[0].path
+
+ generated_file = dotnet.declare_file(dotnet, "{}_generated.c".format(name))
+ content = _TEMPLATE.format(exe.path, nunit)
+ dotnet.actions.write(output = generated_file, content = content, is_executable=False)
+
+ return [
+ DefaultInfo(
+ files = depset([generated_file]),
+ ),
+ ]
+
+dotnet_launcher_gen = rule(
+ _dotnet_launcher_gen_impl,
+ attrs = {
+ "exe": attr.label(),
+ "nunit": attr.label(),
+ "_dotnet_context_data": attr.label(default = Label("@io_bazel_rules_dotnet//:dotnet_context_data")),
+ },
+ toolchains = ["@io_bazel_rules_dotnet//dotnet:toolchain"],
+ executable = False,
+)
diff --git a/dotnet/private/rules/library.bzl b/dotnet/private/rules/library.bzl
new file mode 100644
index 00000000000000..10d4bcea32b68d
--- /dev/null
+++ b/dotnet/private/rules/library.bzl
@@ -0,0 +1,50 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:context.bzl",
+ "dotnet_context",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:providers.bzl",
+ "DotnetLibrary",
+ "DotnetResource",
+)
+
+
+def _dotnet_library_impl(ctx):
+ """dotnet_library_impl emits actions for compiling dotnet executable assembly."""
+ dotnet = dotnet_context(ctx)
+ name = ctx.label.name
+
+ library = dotnet.library(dotnet,
+ name = name,
+ srcs = ctx.attr.srcs,
+ deps = ctx.attr.deps,
+ resources = ctx.attr.resources,
+ out = ctx.attr.out,
+ defines = ctx.attr.defines,
+
+ )
+
+ transitive_files = [d.result for d in library.transitive.to_list()]
+
+ return [
+ library,
+ DefaultInfo(
+ files = depset([library.result]),
+ runfiles = ctx.runfiles(files = [dotnet.stdlib, library.result], transitive_files=depset(direct=transitive_files)),
+ ),
+ ]
+
+dotnet_library = rule(
+ _dotnet_library_impl,
+ attrs = {
+ "deps": attr.label_list(providers=[DotnetLibrary]),
+ "resources": attr.label_list(providers=[DotnetResource]),
+ "srcs": attr.label_list(allow_files = FileType([".cs"])),
+ "out": attr.string(),
+ "defines": attr.string_list(),
+ "_dotnet_context_data": attr.label(default = Label("@io_bazel_rules_dotnet//:dotnet_context_data"))
+ },
+ toolchains = ["@io_bazel_rules_dotnet//dotnet:toolchain"],
+ executable = False,
+)
\ No newline at end of file
diff --git a/dotnet/private/rules/nuget.bzl b/dotnet/private/rules/nuget.bzl
new file mode 100644
index 00000000000000..06d7cfe4583ab6
--- /dev/null
+++ b/dotnet/private/rules/nuget.bzl
@@ -0,0 +1,74 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:context.bzl",
+ "dotnet_context",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:providers.bzl",
+ "DotnetLibrary",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:common.bzl",
+ "paths",
+)
+
+
+def _dotnet_nuget_impl(ctx,
+ build_file = None,
+ build_file_content = None):
+ """dotnet_nuget_impl emits actions for exposing nunit assmebly."""
+
+ package = ctx.attr.package
+ output_dir = ctx.path("")
+
+ url = ctx.attr.source + "/" + ctx.attr.package + "/" + ctx.attr.version
+ ctx.download_and_extract(url, output_dir, ctx.attr.sha256, type="zip")
+
+ if build_file_content:
+ ctx.file("BUILD", build_file_content)
+ elif build_file:
+ ctx.symlink(ctx.path(build_file), "BUILD")
+ else:
+ ctx.template("BUILD.bazel",
+ Label("@io_bazel_rules_dotnet//dotnet/private:BUILD.nuget.bazel"),
+ executable = False,
+ )
+
+
+dotnet_nuget = repository_rule(
+ _dotnet_nuget_impl,
+ attrs = {
+ # Sources to download the nuget packages from
+ "source":attr.string(default = "https://www.nuget.org/api/v2/package"),
+ # The name of the nuget package
+ "package":attr.string(mandatory=True),
+ # The version of the nuget package
+ "version":attr.string(mandatory=True),
+ "sha256":attr.string(mandatory=True),
+ },
+)
+
+def _dotnet_nuget_new_impl(repository_ctx):
+ build_file = repository_ctx.attr.build_file
+ build_file_content = repository_ctx.attr.build_file_content
+ if not (build_file_content or build_file):
+ fail("build_file or build_file_content is required")
+ _dotnet_nuget_impl(repository_ctx, build_file, build_file_content)
+
+dotnet_nuget_new = repository_rule(
+ _dotnet_nuget_new_impl,
+ attrs = {
+ # Sources to download the nuget packages from
+ "source":attr.string(default = "https://www.nuget.org/api/v2/package"),
+ # The name of the nuget package
+ "package":attr.string(mandatory=True),
+ # The version of the nuget package
+ "version":attr.string(mandatory=True),
+ "sha256":attr.string(mandatory=True),
+ "build_file": attr.label(
+ allow_files = True,
+ ),
+ "build_file_content": attr.string(),
+ },
+)
\ No newline at end of file
diff --git a/dotnet/private/rules/resx.bzl b/dotnet/private/rules/resx.bzl
new file mode 100644
index 00000000000000..759f26a87b6fd1
--- /dev/null
+++ b/dotnet/private/rules/resx.bzl
@@ -0,0 +1,35 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:context.bzl",
+ "dotnet_context",
+)
+
+def _dotnet_resx_impl(ctx):
+ """dotnet_resx_impl emits actions for compiling resx to resource."""
+ dotnet = dotnet_context(ctx)
+ name = ctx.label.name
+
+ resource = dotnet.resx(dotnet,
+ name = name,
+ src = ctx.attr.src,
+ identifier = ctx.attr.identifier,
+ out = ctx.attr.out,
+ )
+ return [
+ resource,
+ DefaultInfo(
+ files = depset([resource.result]),
+ ),
+ ]
+
+dotnet_resx = rule(
+ _dotnet_resx_impl,
+ attrs = {
+ # source files for this target.
+ "src": attr.label(allow_files = FileType([".resx"]), mandatory=True),
+ "identifier": attr.string(),
+ "out": attr.string(),
+ "_dotnet_context_data": attr.label(default = Label("@io_bazel_rules_dotnet//:dotnet_context_data"))
+ },
+ toolchains = ["@io_bazel_rules_dotnet//dotnet:toolchain"],
+ executable = False,
+)
\ No newline at end of file
diff --git a/dotnet/private/rules/stdlib.bzl b/dotnet/private/rules/stdlib.bzl
new file mode 100644
index 00000000000000..55357cc2018e2a
--- /dev/null
+++ b/dotnet/private/rules/stdlib.bzl
@@ -0,0 +1,52 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:context.bzl",
+ "dotnet_context",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:common.bzl",
+ "paths",
+)
+
+def _get_dotnet_stdlib_byname(lib, libVersion, name):
+ lname = name.lower()
+ for f in lib.files:
+ basename = paths.basename(f.path)
+ if basename.lower() != lname:
+ continue
+ dirname = paths.dirname(f.path)
+ if dirname.find(libVersion)==-1:
+ continue
+ return f
+ fail("Could not find %s in dotnet_sdk (lib)" % name)
+
+
+# TODO(tomek) we don't need special treatment for mscorlib.dll
+def _dotnet_stdlib_impl(ctx):
+ """dotnet_stdlib_impl emits the assembly from @dotnet_sdk//:lib."""
+ dotnet = dotnet_context(ctx)
+ name = ctx.label.name
+ result = _get_dotnet_stdlib_byname(dotnet.lib, dotnet.libVersion, name)
+
+ library = dotnet.new_library(
+ dotnet = dotnet,
+ name = name,
+ deps = None,
+ transitive = depset([]),
+ result = result)
+
+ return [
+ library,
+ DefaultInfo(
+ files = depset([library.result]),
+ ),
+ ]
+
+dotnet_stdlib = rule(
+ _dotnet_stdlib_impl,
+ attrs = {
+ "_dotnet_context_data": attr.label(default = Label("@io_bazel_rules_dotnet//:dotnet_context_data"))
+ },
+ toolchains = ["@io_bazel_rules_dotnet//dotnet:toolchain"],
+ executable = False,
+)
\ No newline at end of file
diff --git a/dotnet/private/rules/test.bzl b/dotnet/private/rules/test.bzl
new file mode 100644
index 00000000000000..e971099ff4c3c0
--- /dev/null
+++ b/dotnet/private/rules/test.bzl
@@ -0,0 +1,34 @@
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:context.bzl",
+ "dotnet_context",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:providers.bzl",
+ "DotnetLibrary",
+ "DotnetResource",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:rules/launcher_gen.bzl",
+ "dotnet_launcher_gen",
+)
+
+load(
+ "@io_bazel_rules_dotnet//dotnet/private:rules/library.bzl",
+ "dotnet_library",
+)
+
+
+def dotnet_nunit_test(name, deps, srcs, data = [], defines = None, out = None, **kwargs):
+ dotnet_library(name = "%s_exe" % name, deps = deps, srcs = srcs, out = out, defines = defines)
+ exe = ":%s_exe" % name
+ dotnet_launcher_gen(name = "%s_launcher" % name, exe = exe, nunit="@nunit2//:nunit-console-runner-exe_exe")
+
+ native.cc_test(
+ name=name,
+ srcs = [":%s_launcher" % name],
+ deps = ["@io_bazel_rules_dotnet//dotnet/tools/runner", "@io_bazel_rules_dotnet//dotnet/tools/common"],
+ data = [exe, "@nunit2//:nunit-console-runner-exe_exe"] + data,
+ **kwargs
+ )
\ No newline at end of file
diff --git a/dotnet/private/sdk.bzl b/dotnet/private/sdk.bzl
new file mode 100644
index 00000000000000..25b1dad071e3bb
--- /dev/null
+++ b/dotnet/private/sdk.bzl
@@ -0,0 +1,144 @@
+load("@io_bazel_rules_dotnet//dotnet/private:common.bzl", "executable_extension", "bat_extension", "paths")
+
+# Mono for linux, windows and macos layouts fies differentely
+# So we provide an implementation for each host
+def _dotnet_host_sdk_impl_windows(ctx):
+ mono, mcs = _detect_host_sdk(ctx)
+ _sdk_build_file(ctx)
+ bin = ctx.path(mcs).dirname
+ ctx.symlink(bin, "mcs_bin")
+ bin = ctx.path(mono).dirname
+ ctx.symlink(bin, "mono_bin")
+ lib = paths.join("{}".format(ctx.path(mcs).dirname), "../lib")
+ ctx.symlink(lib, "lib")
+
+
+# Mono launcher is on Linux usually placed in /usr/bin. Since the directory
+# may contain forbidden file names ('[') we cannot link it in dotnet_sdk
+# Instead we create a directory (named mono_bin) and put link to mono in it
+def _dotnet_host_sdk_impl_linux(ctx):
+ mono, mcs = _detect_host_sdk(ctx)
+ _sdk_build_file(ctx)
+ ctx.file("mono_bin/README.md",
+ "Directory to hold link to mono executable",
+ False
+ )
+ ctx.symlink(mono, "mono_bin/mono")
+ monoroot = ctx.path("/usr/lib/mono/")
+ if not monoroot.exists:
+ fail("Can't find mono in /usr/lib/mono/")
+ ctx.symlink(monoroot, "lib")
+ bin = paths.join("{}".format(monoroot), "4.5")
+ ctx.symlink(bin, "mcs_bin")
+
+def _dotnet_host_sdk_impl_osx(ctx):
+ mono, mcs = _detect_host_sdk(ctx)
+ _sdk_build_file(ctx)
+ ctx.file("mono_bin/README.md",
+ "Directory to hold link to mono executable",
+ False
+ )
+ ctx.symlink(mono, "mono_bin/mono")
+ monoroot = ctx.path("/usr/local/Cellar/mono/5.4.1.6/lib/mono")
+ if not monoroot.exists:
+ current = ctx.path(mono).dirname
+ monodir = paths.join("{}".format(current), "..", "lib", "mono")
+ monoroot = ctx.path(monodir)
+ if not monoroot.exists:
+ fail("Can't find mono in /usr/local/Cellar/mono/5.4.1.6/lib/mono")
+ ctx.symlink(monoroot, "lib")
+ bin = paths.join("{}".format(monoroot), "4.5")
+ ctx.symlink(bin, "mcs_bin")
+
+def _dotnet_host_sdk_impl(ctx):
+ if ctx.os.name == 'linux':
+ _dotnet_host_sdk_impl_linux(ctx)
+ elif ctx.os.name == 'mac os x':
+ _dotnet_host_sdk_impl_osx(ctx)
+ elif ctx.os.name.startswith('windows'):
+ _dotnet_host_sdk_impl_windows(ctx)
+
+
+dotnet_host_sdk = repository_rule(
+ implementation = _dotnet_host_sdk_impl,
+ local=True,
+)
+
+def _dotnet_download_sdk_impl(ctx):
+ if ctx.os.name == 'linux':
+ host = "mono_linux_amd64"
+ elif ctx.os.name == 'mac os x':
+ host = "mono_darwin_amd64"
+ elif ctx.os.name.startswith('windows'):
+ host = "mono_windows_amd64"
+ else:
+ fail("Unsupported operating system: " + ctx.os.name)
+ sdks = ctx.attr.sdks
+ if host not in sdks: fail("Unsupported host {}".format(host))
+ filename, sha256 = ctx.attr.sdks[host]
+ _sdk_build_file(ctx)
+ _remote_sdk(ctx, [filename], ctx.attr.strip_prefix, sha256)
+ ctx.symlink("mono/lib/mono/4.5", "mcs_bin")
+ ctx.symlink("mono/bin", "mono_bin")
+ ctx.symlink("mono/lib/mono", "lib")
+
+
+dotnet_download_sdk = repository_rule(
+ _dotnet_download_sdk_impl,
+ attrs = {
+ "sdks": attr.string_list_dict(),
+ "urls": attr.string_list(),
+ "strip_prefix": attr.string(default = ""),
+ },
+)
+
+def _dotnet_local_sdk_impl(ctx):
+ _sdk_build_file(ctx)
+ bin = paths.join(ctx.attr.path, "/bin")
+ ctx.symlink(bin, "bin")
+ lib = paths.join(ctx.attr.path, "/lib")
+ ctx.symlink(lib, "lib")
+
+dotnet_local_sdk = repository_rule(
+ _dotnet_local_sdk_impl,
+ attrs = {
+ "path": attr.string(),
+ },
+)
+
+"""See /dotnet/toolchains.rst#dotnet-sdk for full documentation."""
+
+def _remote_sdk(ctx, urls, strip_prefix, sha256):
+ ctx.download_and_extract(
+ url = urls,
+ stripPrefix = strip_prefix,
+ sha256 = sha256,
+ )
+
+def _sdk_build_file(ctx):
+ ctx.file("ROOT")
+ ctx.template("BUILD.bazel",
+ Label("@io_bazel_rules_dotnet//dotnet/private:BUILD.sdk.bazel"),
+ executable = False,
+ )
+
+
+def _detect_host_sdk(ctx):
+ mcs = ctx.which("mcs" + bat_extension(ctx))
+ if not mcs:
+ defmono = ctx.path("c:/program files/mono/bin")
+ if defmono.exists:
+ mcs = ctx.path("c:/program files/mono/bin/mcs")
+ else:
+ fail("Failed to find mcs")
+
+ mono = ctx.which("mono" + executable_extension(ctx))
+ if not mono:
+ defmono = ctx.path("c:/program files/mono/bin")
+ if defmono.exists:
+ mono = ctx.path("c:/program files/mono/bin/mono.exe")
+ else:
+ fail("Failed to find mono")
+
+ return (mono, mcs)
+
diff --git a/dotnet/private/skylib/README.rst b/dotnet/private/skylib/README.rst
new file mode 100644
index 00000000000000..65aa2f22f692b8
--- /dev/null
+++ b/dotnet/private/skylib/README.rst
@@ -0,0 +1,7 @@
+This directory is a copy of github.com/bazelbuild/bazel-skylib/lib.
+Commit 2169ae1, retrieved on 2018-01-12
+
+This is needed only until nested workspaces works.
+It has to be copied in because we use the functionality inside code that
+go_rules_dependencies itself depends on, which means we cannot automatically
+add the skylib dependency.
diff --git a/dotnet/private/skylib/lib/collections.bzl b/dotnet/private/skylib/lib/collections.bzl
new file mode 100644
index 00000000000000..c86842b3e76c90
--- /dev/null
+++ b/dotnet/private/skylib/lib/collections.bzl
@@ -0,0 +1,70 @@
+# Copyright 2017 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.
+
+"""Skylib module containing functions that operate on collections."""
+
+
+def _after_each(separator, iterable):
+ """Inserts `separator` after each item in `iterable`.
+
+ Args:
+ separator: The value to insert after each item in `iterable`.
+ iterable: The list into which to intersperse the separator.
+ Returns:
+ A new list with `separator` after each item in `iterable`.
+ """
+ result = []
+ for x in iterable:
+ result.append(x)
+ result.append(separator)
+
+ return result
+
+
+def _before_each(separator, iterable):
+ """Inserts `separator` before each item in `iterable`.
+
+ Args:
+ separator: The value to insert before each item in `iterable`.
+ iterable: The list into which to intersperse the separator.
+ Returns:
+ A new list with `separator` before each item in `iterable`.
+ """
+ result = []
+ for x in iterable:
+ result.append(separator)
+ result.append(x)
+
+ return result
+
+
+def _uniq(iterable):
+ """Returns a list of unique elements in `iterable`.
+
+ Requires all the elements to be hashable.
+
+ Args:
+ iterable: An iterable to filter.
+ Returns:
+ A new list with all unique elements from `iterable`.
+ """
+ unique_elements = {element: None for element in iterable}
+ return unique_elements.keys()
+
+
+collections = struct(
+ after_each=_after_each,
+ before_each=_before_each,
+ uniq=_uniq,
+)
diff --git a/dotnet/private/skylib/lib/dicts.bzl b/dotnet/private/skylib/lib/dicts.bzl
new file mode 100644
index 00000000000000..ee1076cb016d41
--- /dev/null
+++ b/dotnet/private/skylib/lib/dicts.bzl
@@ -0,0 +1,42 @@
+# Copyright 2017 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.
+
+"""Skylib module containing functions that operate on dictionaries."""
+
+
+def _add(*dictionaries):
+ """Returns a new `dict` that has all the entries of the given dictionaries.
+
+ If the same key is present in more than one of the input dictionaries, the
+ last of them in the argument list overrides any earlier ones.
+
+ This function is designed to take zero or one arguments as well as multiple
+ dictionaries, so that it follows arithmetic identities and callers can avoid
+ special cases for their inputs: the sum of zero dictionaries is the empty
+ dictionary, and the sum of a single dictionary is a copy of itself.
+
+ Args:
+ *dictionaries: Zero or more dictionaries to be added.
+ Returns:
+ A new `dict` that has all the entries of the given dictionaries.
+ """
+ result = {}
+ for d in dictionaries:
+ result.update(d)
+ return result
+
+
+dicts = struct(
+ add=_add,
+)
diff --git a/dotnet/private/skylib/lib/paths.bzl b/dotnet/private/skylib/lib/paths.bzl
new file mode 100644
index 00000000000000..378fa4537939c0
--- /dev/null
+++ b/dotnet/private/skylib/lib/paths.bzl
@@ -0,0 +1,245 @@
+# Copyright 2017 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.
+
+"""Skylib module containing file path manipulation functions.
+
+NOTE: The functions in this module currently only support paths with Unix-style
+path separators (forward slash, "/"); they do not handle Windows-style paths
+with backslash separators or drive letters.
+"""
+
+
+def _basename(p):
+ """Returns the basename (i.e., the file portion) of a path.
+
+ Note that if `p` ends with a slash, this function returns an empty string.
+ This matches the behavior of Python's `os.path.basename`, but differs from
+ the Unix `basename` command (which would return the path segment preceding
+ the final slash).
+
+ Args:
+ p: The path whose basename should be returned.
+ Returns:
+ The basename of the path, which includes the extension.
+ """
+ return p.rpartition("/")[-1]
+
+
+def _dirname(p):
+ """Returns the dirname of a path.
+
+ The dirname is the portion of `p` up to but not including the file portion
+ (i.e., the basename). Any slashes immediately preceding the basename are not
+ included, unless omitting them would make the dirname empty.
+
+ Args:
+ p: The path whose dirname should be returned.
+ Returns:
+ The dirname of the path.
+ """
+ prefix, sep, _ = p.rpartition("/")
+ if not prefix:
+ return sep
+ else:
+ # If there are multiple consecutive slashes, strip them all out as Python's
+ # os.path.dirname does.
+ return prefix.rstrip("/")
+
+
+def _is_absolute(path):
+ """Returns `True` if `path` is an absolute path.
+
+ Args:
+ path: A path (which is a string).
+ Returns:
+ `True` if `path` is an absolute path.
+ """
+ return path.startswith("/") or path[1] == ":"
+
+
+def _join(path, *others):
+ """Joins one or more path components intelligently.
+
+ This function mimics the behavior of Python's `os.path.join` function on POSIX
+ platform. It returns the concatenation of `path` and any members of `others`,
+ inserting directory separators before each component except the first. The
+ separator is not inserted if the path up until that point is either empty or
+ already ends in a separator.
+
+ If any component is an absolute path, all previous components are discarded.
+
+ Args:
+ path: A path segment.
+ *others: Additional path segments.
+ Returns:
+ A string containing the joined paths.
+ """
+ result = path
+
+ for p in others:
+ if _is_absolute(p):
+ result = p
+ elif not result or result.endswith("/"):
+ result += p
+ else:
+ result += "/" + p
+
+ return result
+
+
+def _normalize(path):
+ """Normalizes a path, eliminating double slashes and other redundant segments.
+
+ This function mimics the behavior of Python's `os.path.normpath` function on
+ POSIX platforms; specifically:
+
+ - If the entire path is empty, "." is returned.
+ - All "." segments are removed, unless the path consists solely of a single
+ "." segment.
+ - Trailing slashes are removed, unless the path consists solely of slashes.
+ - ".." segments are removed as long as there are corresponding segments
+ earlier in the path to remove; otherwise, they are retained as leading ".."
+ segments.
+ - Single and double leading slashes are preserved, but three or more leading
+ slashes are collapsed into a single leading slash.
+ - Multiple adjacent internal slashes are collapsed into a single slash.
+
+ Args:
+ path: A path.
+ Returns:
+ The normalized path.
+ """
+ if not path:
+ return "."
+
+ if path.startswith("//") and not path.startswith("///"):
+ initial_slashes = 2
+ elif path.startswith("/"):
+ initial_slashes = 1
+ else:
+ initial_slashes = 0
+ is_relative = (initial_slashes == 0)
+
+ components = path.split("/")
+ new_components = []
+
+ for component in components:
+ if component in ("", "."):
+ continue
+ if component == "..":
+ if new_components and new_components[-1] != "..":
+ # Only pop the last segment if it isn't another "..".
+ new_components.pop()
+ elif is_relative:
+ # Preserve leading ".." segments for relative paths.
+ new_components.append(component)
+ else:
+ new_components.append(component)
+
+ path = "/".join(new_components)
+ if not is_relative:
+ path = ("/" * initial_slashes) + path
+
+ return path or "."
+
+
+def _relativize(path, start):
+ """Returns the portion of `path` that is relative to `start`.
+
+ Because we do not have access to the underlying file system, this
+ implementation differs slightly from Python's `os.path.relpath` in that it
+ will fail if `path` is not beneath `start` (rather than use parent segments to
+ walk up to the common file system root).
+
+ Relativizing paths that start with parent directory references is not allowed.
+
+ Args:
+ path: The path to relativize.
+ start: The ancestor path against which to relativize.
+ Returns:
+ The portion of `path` that is relative to `start`.
+ """
+ segments = _normalize(path).split("/")
+ start_segments = _normalize(start).split("/")
+ if start_segments == ["."]:
+ start_segments = []
+ start_length = len(start_segments)
+
+ if (path.startswith("..") or start.startswith("..")):
+ fail("Cannot relativize paths above the current (unknown) directory")
+
+ if (path.startswith("/") != start.startswith("/") or
+ len(segments) < start_length):
+ fail("Path '%s' is not beneath '%s'" % (path, start))
+
+ for ancestor_segment, segment in zip(start_segments, segments):
+ if ancestor_segment != segment:
+ fail("Path '%s' is not beneath '%s'" % (path, start))
+
+ length = len(segments) - start_length
+ result_segments = segments[-length:]
+ return "/".join(result_segments)
+
+
+def _replace_extension(p, new_extension):
+ """Replaces the extension of the file at the end of a path.
+
+ If the path has no extension, the new extension is added to it.
+
+ Args:
+ p: The path whose extension should be replaced.
+ new_extension: The new extension for the file. The new extension should
+ begin with a dot if you want the new filename to have one.
+ Returns:
+ The path with the extension replaced (or added, if it did not have one).
+ """
+ return _split_extension(p)[0] + new_extension
+
+
+def _split_extension(p):
+ """Splits the path `p` into a tuple containing the root and extension.
+
+ Leading periods on the basename are ignored, so
+ `path.split_extension(".bashrc")` returns `(".bashrc", "")`.
+
+ Args:
+ p: The path whose root and extension should be split.
+ Returns:
+ A tuple `(root, ext)` such that the root is the path without the file
+ extension, and `ext` is the file extension (which, if non-empty, contains
+ the leading dot). The returned tuple always satisfies the relationship
+ `root + ext == p`.
+ """
+ b = _basename(p)
+ last_dot_in_basename = b.rfind(".")
+
+ # If there is no dot or the only dot in the basename is at the front, then
+ # there is no extension.
+ if last_dot_in_basename <= 0:
+ return (p, "")
+
+ dot_distance_from_end = len(b) - last_dot_in_basename
+ return (p[:-dot_distance_from_end], p[-dot_distance_from_end:])
+
+
+paths = struct(
+ basename=_basename,
+ dirname=_dirname,
+ is_absolute=_is_absolute,
+ join=_join,
+ normalize=_normalize,
+ relativize=_relativize,
+ replace_extension=_replace_extension,
+ split_extension=_split_extension,
+)
diff --git a/dotnet/private/skylib/lib/selects.bzl b/dotnet/private/skylib/lib/selects.bzl
new file mode 100644
index 00000000000000..daf15c7aa43116
--- /dev/null
+++ b/dotnet/private/skylib/lib/selects.bzl
@@ -0,0 +1,83 @@
+# Copyright 2017 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.
+
+"""Skylib module containing convenience interfaces for select()."""
+
+def _with_or(input_dict):
+ """Drop-in replacement for `select()` that supports ORed keys.
+
+ Args:
+ input_dict: The same dictionary `select()` takes, except keys may take
+ either the usual form `"//foo:config1"` or
+ `("//foo:config1", "//foo:config2", ...)` to signify
+ `//foo:config1` OR `//foo:config2` OR `...`.
+
+ Example:
+
+ ```build
+ deps = selects.with_or({
+ "//configs:one": [":dep1"],
+ ("//configs:two", "//configs:three"): [":dep2or3"],
+ "//configs:four": [":dep4"],
+ "//conditions:default": [":default"]
+ })
+ ```
+
+ Key labels may appear at most once anywhere in the input.
+
+ Returns:
+ A native `select()` that expands
+
+ `("//configs:two", "//configs:three"): [":dep2or3"]`
+
+ to
+
+ ```build
+ "//configs:two": [":dep2or3"],
+ "//configs:three": [":dep2or3"],
+ ```
+ """
+ return select(_with_or_dict(input_dict))
+
+
+def _with_or_dict(input_dict):
+ """Variation of `with_or` that returns the dict of the `select()`.
+
+ Unlike `select()`, the contents of the dict can be inspected by Skylark
+ macros.
+
+ Args:
+ input_dict: Same as `with_or`.
+
+ Returns:
+ A dictionary usable by a native `select()`.
+ """
+ output_dict = {}
+ for (key, value) in input_dict.items():
+ if type(key) == type(()):
+ for config_setting in key:
+ if config_setting in output_dict.keys():
+ fail("key %s appears multiple times" % config_setting)
+ output_dict[config_setting] = value
+ else:
+ if key in output_dict.keys():
+ fail("key %s appears multiple times" % config_setting)
+ output_dict[key] = value
+ return output_dict
+
+
+selects = struct(
+ with_or=_with_or,
+ with_or_dict=_with_or_dict
+)
diff --git a/dotnet/private/skylib/lib/sets.bzl b/dotnet/private/skylib/lib/sets.bzl
new file mode 100644
index 00000000000000..edaf8275c30256
--- /dev/null
+++ b/dotnet/private/skylib/lib/sets.bzl
@@ -0,0 +1,145 @@
+# Copyright 2017 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.
+
+"""Skylib module containing common set algorithms.
+
+CAUTION: Operating on sets, particularly sets contained in providers, may
+asymptotically slow down the analysis phase. While constructing large sets with
+addition/union is fast (there is no linear-time copy involved), the
+`difference` function and various comparison predicates involve linear-time
+traversals.
+
+For convenience, the functions in this module can take either sets or lists as
+inputs; operations that take lists treat them as if they were sets (i.e.,
+duplicate elements are ignored). Functions that return new sets always return
+them as the `set` type, regardless of the types of the inputs.
+"""
+
+
+def _precondition_only_sets_or_lists(*args):
+ """Verifies that all arguments are either sets or lists.
+
+ The build will fail if any of the arguments is neither a set nor a list.
+
+ Args:
+ *args: A list of values that must be sets or lists.
+ """
+ for a in args:
+ t = type(a)
+ if t not in("depset", "list"):
+ fail("Expected arguments to be depset or list, but found type %s: %r" %
+ (t, a))
+
+
+def _is_equal(a, b):
+ """Returns whether two sets are equal.
+
+ Args:
+ a: A depset or a list.
+ b: A depset or a list.
+ Returns:
+ True if `a` is equal to `b`, False otherwise.
+ """
+ _precondition_only_sets_or_lists(a, b)
+ return sorted(depset(a)) == sorted(depset(b))
+
+
+def _is_subset(a, b):
+ """Returns whether `a` is a subset of `b`.
+
+ Args:
+ a: A depset or a list.
+ b: A depset or a list.
+
+ Returns:
+ True if `a` is a subset of `b`, False otherwise.
+ """
+ _precondition_only_sets_or_lists(a, b)
+ for e in a:
+ if e not in b:
+ return False
+ return True
+
+
+def _disjoint(a, b):
+ """Returns whether two sets are disjoint.
+
+ Two sets are disjoint if they have no elements in common.
+
+ Args:
+ a: A set or list.
+ b: A set or list.
+
+ Returns:
+ True if `a` and `b` are disjoint, False otherwise.
+ """
+ _precondition_only_sets_or_lists(a, b)
+ for e in a:
+ if e in b:
+ return False
+ return True
+
+
+def _intersection(a, b):
+ """Returns the intersection of two sets.
+
+ Args:
+ a: A set or list.
+ b: A set or list.
+
+ Returns:
+ A set containing the elements that are in both `a` and `b`.
+ """
+ _precondition_only_sets_or_lists(a, b)
+ return depset([e for e in a if e in b])
+
+
+def _union(*args):
+ """Returns the union of several sets.
+
+ Args:
+ *args: An arbitrary number of sets or lists.
+
+ Returns:
+ The set union of all sets or lists in `*args`.
+ """
+ _precondition_only_sets_or_lists(*args)
+ r = depset()
+ for a in args:
+ r += a
+ return r
+
+
+def _difference(a, b):
+ """Returns the elements in `a` that are not in `b`.
+
+ Args:
+ a: A set or list.
+ b: A set or list.
+
+ Returns:
+ A set containing the elements that are in `a` but not in `b`.
+ """
+ _precondition_only_sets_or_lists(a, b)
+ return depset([e for e in a if e not in b])
+
+
+sets = struct(
+ difference = _difference,
+ disjoint = _disjoint,
+ intersection = _intersection,
+ is_equal = _is_equal,
+ is_subset = _is_subset,
+ union = _union,
+)
diff --git a/dotnet/private/skylib/lib/shell.bzl b/dotnet/private/skylib/lib/shell.bzl
new file mode 100644
index 00000000000000..4173fe7ba851cc
--- /dev/null
+++ b/dotnet/private/skylib/lib/shell.bzl
@@ -0,0 +1,55 @@
+# Copyright 2017 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.
+
+"""Skylib module containing shell utility functions."""
+
+
+def _array_literal(iterable):
+ """Creates a string from a sequence that can be used as a shell array.
+
+ For example, `shell.array_literal(["a", "b", "c"])` would return the string
+ `("a" "b" "c")`, which can be used in a shell script wherever an array
+ literal is needed.
+
+ Note that all elements in the array are quoted (using `shell.quote`) for
+ safety, even if they do not need to be.
+
+ Args:
+ iterable: A sequence of elements. Elements that are not strings will be
+ converted to strings first, by calling `str()`.
+ Returns:
+ A string that represents the sequence as a shell array; that is,
+ parentheses containing the quoted elements.
+ """
+ return "(" + " ".join([_quote(str(i)) for i in iterable]) + ")"
+
+
+def _quote(s):
+ """Quotes the given string for use in a shell command.
+
+ This function quotes the given string (in case it contains spaces or other
+ shell metacharacters.)
+
+ Args:
+ s: The string to quote.
+ Returns:
+ A quoted version of the string that can be passed to a shell command.
+ """
+ return "'" + s.replace("'", "'\\''") + "'"
+
+
+shell = struct(
+ array_literal=_array_literal,
+ quote=_quote,
+)
diff --git a/dotnet/private/skylib/lib/structs.bzl b/dotnet/private/skylib/lib/structs.bzl
new file mode 100644
index 00000000000000..78715cca9f1067
--- /dev/null
+++ b/dotnet/private/skylib/lib/structs.bzl
@@ -0,0 +1,36 @@
+# Copyright 2017 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.
+
+"""Skylib module containing functions that operate on structs."""
+
+
+def _to_dict(s):
+ """Converts a `struct` to a `dict`.
+
+ Args:
+ s: A `struct`.
+ Returns:
+ A `dict` whose keys and values are the same as the fields in `s`. The
+ transformation is only applied to the struct's fields and not to any
+ nested values.
+ """
+ attributes = dir(s)
+ attributes.remove("to_json")
+ attributes.remove("to_proto")
+ return {key: getattr(s, key) for key in attributes}
+
+
+structs = struct(
+ to_dict=_to_dict,
+)
diff --git a/dotnet/private/skylib/lib/unittest.bzl b/dotnet/private/skylib/lib/unittest.bzl
new file mode 100644
index 00000000000000..f1208a3cf48723
--- /dev/null
+++ b/dotnet/private/skylib/lib/unittest.bzl
@@ -0,0 +1,270 @@
+# Copyright 2017 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.
+
+"""Unit testing support.
+
+Unlike most Skylib files, this exports two modules: `unittest` which contains
+functions to declare and define unit tests, and `asserts` which contains the
+assertions used to within tests.
+"""
+
+load(":sets.bzl", "sets")
+
+
+def _make(impl, attrs=None):
+ """Creates a unit test rule from its implementation function.
+
+ Each unit test is defined in an implementation function that must then be
+ associated with a rule so that a target can be built. This function handles
+ the boilerplate to create and return a test rule and captures the
+ implementation function's name so that it can be printed in test feedback.
+
+ The optional `attrs` argument can be used to define dependencies for this
+ test, in order to form unit tests of rules.
+
+ An example of a unit test:
+
+ ```
+ def _your_test(ctx):
+ env = unittest.begin(ctx)
+
+ # Assert statements go here
+
+ unittest.end(env)
+
+ your_test = unittest.make(_your_test)
+ ```
+
+ Recall that names of test rules must end in `_test`.
+
+ Args:
+ impl: The implementation function of the unit test.
+ attrs: An optional dictionary to supplement the attrs passed to the
+ unit test's `rule()` constructor.
+ Returns:
+ A rule definition that should be stored in a global whose name ends in
+ `_test`.
+ """
+
+ # Derive the name of the implementation function for better test feedback.
+ # Skylark currently stringifies a function as "", so we use
+ # that knowledge to parse the "NAME" portion out. If this behavior ever
+ # changes, we'll need to update this.
+ # TODO(bazel-team): Expose a ._name field on functions to avoid this.
+ impl_name = str(impl)
+ impl_name = impl_name.partition("")[0]
+
+ attrs = dict(attrs) if attrs else {}
+ attrs["_impl_name"] = attr.string(default=impl_name)
+
+ return rule(
+ impl,
+ attrs=attrs,
+ _skylark_testable=True,
+ test=True,
+ )
+
+
+def _suite(name, *test_rules):
+ """Defines a `test_suite` target that contains multiple tests.
+
+ After defining your test rules in a `.bzl` file, you need to create targets
+ from those rules so that `blaze test` can execute them. Doing this manually
+ in a BUILD file would consist of listing each test in your `load` statement
+ and then creating each target one by one. To reduce duplication, we recommend
+ writing a macro in your `.bzl` file to instantiate all targets, and calling
+ that macro from your BUILD file so you only have to load one symbol.
+
+ For the case where your unit tests do not take any (non-default) attributes --
+ i.e., if your unit tests do not test rules -- you can use this function to
+ create the targets and wrap them in a single test_suite target. In your
+ `.bzl` file, write:
+
+ ```
+ def your_test_suite():
+ unittest.suite(
+ "your_test_suite",
+ your_test,
+ your_other_test,
+ yet_another_test,
+ )
+ ```
+
+ Then, in your `BUILD` file, simply load the macro and invoke it to have all
+ of the targets created:
+
+ ```
+ load("//path/to/your/package:tests.bzl", "your_test_suite")
+ your_test_suite()
+ ```
+
+ If you pass _N_ unit test rules to `unittest.suite`, _N_ + 1 targets will be
+ created: a `test_suite` target named `${name}` (where `${name}` is the name
+ argument passed in here) and targets named `${name}_test_${i}`, where `${i}`
+ is the index of the test in the `test_rules` list, which is used to uniquely
+ name each target.
+
+ Args:
+ name: The name of the `test_suite` target, and the prefix of all the test
+ target names.
+ *test_rules: A list of test rules defines by `unittest.test`.
+ """
+ test_names = []
+ for index, test_rule in enumerate(test_rules):
+ test_name = "%s_test_%d" % (name, index)
+ test_rule(name=test_name)
+ test_names.append(test_name)
+
+ native.test_suite(
+ name=name,
+ tests=[":%s" % t for t in test_names]
+ )
+
+
+def _begin(ctx):
+ """Begins a unit test.
+
+ This should be the first function called in a unit test implementation
+ function. It initializes a "test environment" that is used to collect
+ assertion failures so that they can be reported and logged at the end of the
+ test.
+
+ Args:
+ ctx: The Skylark context. Pass the implementation function's `ctx` argument
+ in verbatim.
+ Returns:
+ A test environment struct that must be passed to assertions and finally to
+ `unittest.end`. Do not rely on internal details about the fields in this
+ struct as it may change.
+ """
+ return struct(ctx=ctx, failures=[])
+
+
+def _end(env):
+ """Ends a unit test and logs the results.
+
+ This must be called before the end of a unit test implementation function so
+ that the results are reported.
+
+ Args:
+ env: The test environment returned by `unittest.begin`.
+ """
+ cmd = "\n".join([
+ "cat << EOF",
+ "\n".join(env.failures),
+ "EOF",
+ "exit %d" % len(env.failures),
+ ])
+ env.ctx.file_action(
+ output=env.ctx.outputs.executable,
+ content=cmd,
+ executable=True,
+ )
+
+
+def _fail(env, msg):
+ """Unconditionally causes the current test to fail.
+
+ Args:
+ env: The test environment returned by `unittest.begin`.
+ msg: The message to log describing the failure.
+ """
+ full_msg = "In test %s: %s" % (env.ctx.attr._impl_name, msg)
+ print(full_msg)
+ env.failures.append(full_msg)
+
+
+def _assert_true(env,
+ condition,
+ msg="Expected condition to be true, but was false."):
+ """Asserts that the given `condition` is true.
+
+ Args:
+ env: The test environment returned by `unittest.begin`.
+ condition: A value that will be evaluated in a Boolean context.
+ msg: An optional message that will be printed that describes the failure.
+ If omitted, a default will be used.
+ """
+ if not condition:
+ _fail(env, msg)
+
+
+def _assert_false(env,
+ condition,
+ msg="Expected condition to be false, but was true."):
+ """Asserts that the given `condition` is false.
+
+ Args:
+ env: The test environment returned by `unittest.begin`.
+ condition: A value that will be evaluated in a Boolean context.
+ msg: An optional message that will be printed that describes the failure.
+ If omitted, a default will be used.
+ """
+ if condition:
+ _fail(env, msg)
+
+
+def _assert_equals(env, expected, actual, msg=None):
+ """Asserts that the given `expected` and `actual` values are equal.
+
+ Args:
+ env: The test environment returned by `unittest.begin`.
+ expected: The expected value of some computation.
+ actual: The actual value returned by some computation.
+ msg: An optional message that will be printed that describes the failure.
+ If omitted, a default will be used.
+ """
+ if expected != actual:
+ expectation_msg = 'Expected "%s", but got "%s"' % (expected, actual)
+ if msg:
+ full_msg = "%s (%s)" % (msg, expectation_msg)
+ else:
+ full_msg = expectation_msg
+ _fail(env, full_msg)
+
+
+def _assert_set_equals(env, expected, actual, msg=None):
+ """Asserts that the given `expected` and `actual` sets are equal.
+
+ Args:
+ env: The test environment returned by `unittest.begin`.
+ expected: The expected set resulting from some computation.
+ actual: The actual set returned by some computation.
+ msg: An optional message that will be printed that describes the failure.
+ If omitted, a default will be used.
+ """
+ if type(actual) != type(depset()) or not sets.is_equal(expected, actual):
+ expectation_msg = "Expected %r, but got %r" % (expected, actual)
+ if msg:
+ full_msg = "%s (%s)" % (msg, expectation_msg)
+ else:
+ full_msg = expectation_msg
+ _fail(env, full_msg)
+
+
+asserts = struct(
+ equals=_assert_equals,
+ false=_assert_false,
+ set_equals=_assert_set_equals,
+ true=_assert_true,
+)
+
+unittest = struct(
+ make=_make,
+ suite=_suite,
+ begin=_begin,
+ end=_end,
+ fail=_fail,
+)
diff --git a/dotnet/private/skylib/lib/versions.bzl b/dotnet/private/skylib/lib/versions.bzl
new file mode 100644
index 00000000000000..d77b2ed6063b48
--- /dev/null
+++ b/dotnet/private/skylib/lib/versions.bzl
@@ -0,0 +1,126 @@
+# Copyright 2018 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.
+
+"""Skylib module containing functions for checking Bazel versions."""
+
+def _get_bazel_version():
+ """Returns the current Bazel version"""
+
+ return native.bazel_version
+
+
+def _extract_version_number(bazel_version):
+ """Extracts the semantic version number from a version string
+
+ Args:
+ bazel_version: the version string that begins with the semantic version
+ e.g. "1.2.3rc1 abc1234" where "abc1234" is a commit hash.
+
+ Returns:
+ The semantic version string, like "1.2.3".
+ """
+ for i in range(len(bazel_version)):
+ c = bazel_version[i]
+ if not (c.isdigit() or c == "."):
+ return bazel_version[:i]
+ return bazel_version
+
+# Parse the bazel version string from `native.bazel_version`.
+# e.g.
+# "0.10.0rc1 abc123d" => (0, 10, 0)
+# "0.3.0" => (0, 3, 0)
+def _parse_bazel_version(bazel_version):
+ """Parses a version string into a 3-tuple of ints
+
+ int tuples can be compared directly using binary operators (<, >).
+
+ Args:
+ bazel_version: the Bazel version string
+
+ Returns:
+ An int 3-tuple of a (major, minor, patch) version.
+ """
+
+ version = _extract_version_number(bazel_version)
+ return tuple([int(n) for n in version.split(".")])
+
+
+def _is_at_most(threshold, version):
+ """Check that a version is lower or equals to a threshold.
+
+ Args:
+ threshold: the maximum version string
+ version: the version string to be compared to the threshold
+
+ Returns:
+ True if version <= threshold.
+ """
+ return _parse_bazel_version(version) <= _parse_bazel_version(threshold)
+
+
+def _is_at_least(threshold, version):
+ """Check that a version is higher or equals to a threshold.
+
+ Args:
+ threshold: the minimum version string
+ version: the version string to be compared to the threshold
+
+ Returns:
+ True if version >= threshold.
+ """
+
+ return _parse_bazel_version(version) >= _parse_bazel_version(threshold)
+
+
+def _check_bazel_version(minimum_bazel_version, maximum_bazel_version=None, bazel_version=None):
+ """Check that the version of Bazel is valid within the specified range.
+
+ Args:
+ minimum_bazel_version: minimum version of Bazel expected
+ maximum_bazel_version: maximum version of Bazel expected
+ bazel_version: the version of Bazel to check. Used for testing, defaults to native.bazel_version
+ """
+ if not bazel_version:
+ if "bazel_version" not in dir(native):
+ fail("\nCurrent Bazel version is lower than 0.2.1, expected at least %s\n" % minimum_bazel_version)
+ elif not native.bazel_version:
+ print("\nCurrent Bazel is not a release version, cannot check for compatibility.")
+ print("Make sure that you are running at least Bazel %s.\n" % minimum_bazel_version)
+ return
+ else:
+ bazel_version = native.bazel_version
+
+ if not _is_at_least(
+ threshold = minimum_bazel_version,
+ version = bazel_version):
+ fail("\nCurrent Bazel version is {}, expected at least {}\n".format(
+ bazel_version, minimum_bazel_version))
+
+ if maximum_bazel_version:
+ max_bazel_version = _parse_bazel_version(maximum_bazel_version)
+ if not _is_at_most(
+ threshold = maximum_bazel_version,
+ version = bazel_version):
+ fail("\nCurrent Bazel version is {}, expected at most {}\n".format(
+ bazel_version, maximum_bazel_version))
+
+ pass
+
+versions = struct(
+ get=_get_bazel_version,
+ parse=_parse_bazel_version,
+ check=_check_bazel_version,
+ is_at_most=_is_at_most,
+ is_at_least=_is_at_least,
+)
diff --git a/dotnet/providers.rst b/dotnet/providers.rst
new file mode 100644
index 00000000000000..346b06fdca6bb5
--- /dev/null
+++ b/dotnet/providers.rst
@@ -0,0 +1,69 @@
+Dotnet providers
+================
+
+.. _providers: https://docs.bazel.build/versions/master/skylark/rules.html#providers
+.. _runfiles: https://docs.bazel.build/versions/master/skylark/lib/runfiles.html
+.. _File: https://docs.bazel.build/versions/master/skylark/lib/File.html
+
+.. role:: param(emphasis)
+.. role:: type(emphasis)
+.. role:: value(code)
+.. |mandatory| replace:: **mandatory value**
+
+
+The providers_ are the outputs of the rules, you generaly get them by having a dependency on a rule,
+and then asking for a provider of a specific type.
+
+.. contents:: :depth: 2
+
+-----
+
+Design
+------
+
+The Dotnet providers are designed primarily for the efficiency of the dotnet rules, the information
+they share is mostly there because it is required for the core rules to work.
+
+All the providers are designed to hold only immutable data. This is partly because its a cleaner
+design choice to be able to assume a provider will never change, but also because only immutable
+objects are allowed to be stored in a depset, and it's really useful to have depsets of providers.
+Specifically the :param:`deps` and :param:`transitive` fields on DotnetLibrary_ only work because
+it is immutable.
+
+API
+---
+
+
+DotnetLibrary
+~~~~~~~~~~~~~
+
+DotnetLibrary is a provider that exposes a compiled library along with it's full transitive
+dependencies.
+This represents a compile dotnet binary.
+
++--------------------------------+-----------------------------------------------------------------+
+| **Name** | **Type** |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`deps` | :type:`list of DotnetLibrary` |
++--------------------------------+-----------------------------------------------------------------+
+| The direct dependencies of this library. |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`transitive` | :type:`depset of DotnetLibrary` |
++--------------------------------+-----------------------------------------------------------------+
+| The full set of transitive dependencies. This includes ``deps`` for this |
+| library and all ``deps`` members transitively reachable through ``deps``. |
++--------------------------------+-----------------------------------------------------------------+
+
+DotnetResource
+~~~~~~~~~~~~~~
+
+DotnetResource is a provider that exposes a compiled resource (.resources file).
+
++--------------------------------+-----------------------------------------------------------------+
+| **Name** | **Type** |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`identifer` | :type:`string` |
++--------------------------------+-----------------------------------------------------------------+
+| The logical name for the resource; the name that is used to load the resource. |
+| The default is the basename of the file name (no subfolder). |
++--------------------------------+-----------------------------------------------------------------+
diff --git a/dotnet/stdlib/BUILD.bazel b/dotnet/stdlib/BUILD.bazel
new file mode 100644
index 00000000000000..e53a4e3bde609b
--- /dev/null
+++ b/dotnet/stdlib/BUILD.bazel
@@ -0,0 +1,128 @@
+package(default_visibility = [ "//visibility:public" ])
+
+load("@io_bazel_rules_dotnet//dotnet/private:rules/stdlib.bzl", "dotnet_stdlib")
+
+dotnet_stdlib(name="Accessibility.dll")
+dotnet_stdlib(name="Commons.Xml.Relaxng.dll")
+dotnet_stdlib(name="CustomMarshalers.dll")
+dotnet_stdlib(name="I18N.CJK.dll")
+dotnet_stdlib(name="I18N.MidEast.dll")
+dotnet_stdlib(name="I18N.Other.dll")
+dotnet_stdlib(name="I18N.Rare.dll")
+dotnet_stdlib(name="I18N.West.dll")
+dotnet_stdlib(name="I18N.dll")
+dotnet_stdlib(name="IBM.Data.DB2.dll")
+dotnet_stdlib(name="Microsoft.Build.Engine.dll")
+dotnet_stdlib(name="Microsoft.Build.Framework.dll")
+dotnet_stdlib(name="Microsoft.Build.Tasks.v4.0.dll")
+dotnet_stdlib(name="Microsoft.Build.Utilities.v4.0.dll")
+dotnet_stdlib(name="Microsoft.Build.dll")
+dotnet_stdlib(name="Microsoft.CSharp.dll")
+dotnet_stdlib(name="Microsoft.VisualBasic.dll")
+dotnet_stdlib(name="Microsoft.VisualC.dll")
+dotnet_stdlib(name="Microsoft.Web.Infrastructure.dll")
+dotnet_stdlib(name="Mono.CSharp.dll")
+dotnet_stdlib(name="Mono.Cairo.dll")
+dotnet_stdlib(name="Mono.CodeContracts.dll")
+dotnet_stdlib(name="Mono.CompilerServices.SymbolWriter.dll")
+dotnet_stdlib(name="Mono.Data.Sqlite.dll")
+dotnet_stdlib(name="Mono.Data.Tds.dll")
+dotnet_stdlib(name="Mono.Debugger.Soft.dll")
+dotnet_stdlib(name="Mono.Http.dll")
+dotnet_stdlib(name="Mono.Management.dll")
+dotnet_stdlib(name="Mono.Messaging.RabbitMQ.dll")
+dotnet_stdlib(name="Mono.Messaging.dll")
+dotnet_stdlib(name="Mono.Parallel.dll")
+dotnet_stdlib(name="Mono.Posix.dll")
+dotnet_stdlib(name="Mono.Security.dll")
+dotnet_stdlib(name="Mono.Simd.dll")
+dotnet_stdlib(name="Mono.Tasklets.dll")
+dotnet_stdlib(name="Mono.WebBrowser.dll")
+dotnet_stdlib(name="Novell.Directory.Ldap.dll")
+dotnet_stdlib(name="PEAPI.dll")
+dotnet_stdlib(name="RabbitMQ.Client.dll")
+dotnet_stdlib(name="System.ComponentModel.Composition.dll")
+dotnet_stdlib(name="System.ComponentModel.DataAnnotations.dll")
+dotnet_stdlib(name="System.Configuration.Install.dll")
+dotnet_stdlib(name="System.Configuration.dll")
+dotnet_stdlib(name="System.Core.dll")
+dotnet_stdlib(name="System.Data.DataSetExtensions.dll")
+dotnet_stdlib(name="System.Data.Entity.dll")
+dotnet_stdlib(name="System.Data.Linq.dll")
+dotnet_stdlib(name="System.Data.OracleClient.dll")
+dotnet_stdlib(name="System.Data.Services.Client.dll")
+dotnet_stdlib(name="System.Data.Services.dll")
+dotnet_stdlib(name="System.Data.dll")
+dotnet_stdlib(name="System.Design.dll")
+dotnet_stdlib(name="System.Diagnostics.Tracing.dll")
+dotnet_stdlib(name="System.DirectoryServices.Protocols.dll")
+dotnet_stdlib(name="System.DirectoryServices.dll")
+dotnet_stdlib(name="System.Drawing.Design.dll")
+dotnet_stdlib(name="System.Drawing.dll")
+dotnet_stdlib(name="System.Dynamic.dll")
+dotnet_stdlib(name="System.EnterpriseServices.dll")
+dotnet_stdlib(name="System.IO.Compression.FileSystem.dll")
+dotnet_stdlib(name="System.IO.Compression.dll")
+dotnet_stdlib(name="System.IdentityModel.Selectors.dll")
+dotnet_stdlib(name="System.IdentityModel.dll")
+dotnet_stdlib(name="System.Json.Microsoft.dll")
+dotnet_stdlib(name="System.Json.dll")
+dotnet_stdlib(name="System.Management.dll")
+dotnet_stdlib(name="System.Messaging.dll")
+dotnet_stdlib(name="System.Net.Http.Formatting.dll")
+dotnet_stdlib(name="System.Net.Http.WebRequest.dll")
+dotnet_stdlib(name="System.Net.Http.dll")
+dotnet_stdlib(name="System.Net.dll")
+dotnet_stdlib(name="System.Numerics.dll")
+dotnet_stdlib(name="System.Reactive.Core.dll")
+dotnet_stdlib(name="System.Reactive.Debugger.dll")
+dotnet_stdlib(name="System.Reactive.Experimental.dll")
+dotnet_stdlib(name="System.Reactive.Interfaces.dll")
+dotnet_stdlib(name="System.Reactive.Linq.dll")
+dotnet_stdlib(name="System.Reactive.Observable.Aliases.dll")
+dotnet_stdlib(name="System.Reactive.PlatformServices.dll")
+dotnet_stdlib(name="System.Reactive.Providers.dll")
+dotnet_stdlib(name="System.Reactive.Runtime.Remoting.dll")
+dotnet_stdlib(name="System.Reactive.Windows.Forms.dll")
+dotnet_stdlib(name="System.Reactive.Windows.Threading.dll")
+dotnet_stdlib(name="System.Reflection.Context.dll")
+dotnet_stdlib(name="System.Runtime.Caching.dll")
+dotnet_stdlib(name="System.Runtime.DurableInstancing.dll")
+dotnet_stdlib(name="System.Runtime.Remoting.dll")
+dotnet_stdlib(name="System.Runtime.Serialization.Formatters.Soap.dll")
+dotnet_stdlib(name="System.Runtime.Serialization.dll")
+dotnet_stdlib(name="System.Security.dll")
+dotnet_stdlib(name="System.ServiceModel.Activation.dll")
+dotnet_stdlib(name="System.ServiceModel.Discovery.dll")
+dotnet_stdlib(name="System.ServiceModel.Routing.dll")
+dotnet_stdlib(name="System.ServiceModel.Web.dll")
+dotnet_stdlib(name="System.ServiceModel.dll")
+dotnet_stdlib(name="System.ServiceProcess.dll")
+dotnet_stdlib(name="System.Threading.Tasks.Dataflow.dll")
+dotnet_stdlib(name="System.Transactions.dll")
+dotnet_stdlib(name="System.Web.Abstractions.dll")
+dotnet_stdlib(name="System.Web.ApplicationServices.dll")
+dotnet_stdlib(name="System.Web.DynamicData.dll")
+dotnet_stdlib(name="System.Web.Extensions.Design.dll")
+dotnet_stdlib(name="System.Web.Extensions.dll")
+dotnet_stdlib(name="System.Web.Http.SelfHost.dll")
+dotnet_stdlib(name="System.Web.Http.WebHost.dll")
+dotnet_stdlib(name="System.Web.Http.dll")
+dotnet_stdlib(name="System.Web.Mvc.dll")
+dotnet_stdlib(name="System.Web.Razor.dll")
+dotnet_stdlib(name="System.Web.Routing.dll")
+dotnet_stdlib(name="System.Web.Services.dll")
+dotnet_stdlib(name="System.Web.WebPages.Deployment.dll")
+dotnet_stdlib(name="System.Web.WebPages.Razor.dll")
+dotnet_stdlib(name="System.Web.WebPages.dll")
+dotnet_stdlib(name="System.Web.dll")
+dotnet_stdlib(name="System.Windows.Forms.DataVisualization.dll")
+dotnet_stdlib(name="System.Windows.Forms.dll")
+dotnet_stdlib(name="System.Windows.dll")
+dotnet_stdlib(name="System.Xaml.dll")
+dotnet_stdlib(name="System.Xml.Linq.dll")
+dotnet_stdlib(name="System.Xml.Serialization.dll")
+dotnet_stdlib(name="System.Xml.dll")
+dotnet_stdlib(name="System.dll")
+dotnet_stdlib(name="WebMatrix.Data.dll")
+dotnet_stdlib(name="WindowsBase.dll")
diff --git a/dotnet/toolchain/BUILD.bazel b/dotnet/toolchain/BUILD.bazel
new file mode 100644
index 00000000000000..fb56e2e8af331d
--- /dev/null
+++ b/dotnet/toolchain/BUILD.bazel
@@ -0,0 +1,12 @@
+load(
+ ":toolchains.bzl",
+ "declare_constraints",
+ "declare_toolchains",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+declare_toolchains()
+
+declare_constraints()
+
diff --git a/dotnet/toolchain/toolchains.bzl b/dotnet/toolchain/toolchains.bzl
new file mode 100644
index 00000000000000..f4e77fe9e932c3
--- /dev/null
+++ b/dotnet/toolchain/toolchains.bzl
@@ -0,0 +1,115 @@
+load(
+ "//dotnet/private:dotnet_toolchain.bzl",
+ "dotnet_toolchain",
+)
+load(
+ "//dotnet/private:sdk.bzl",
+ "dotnet_download_sdk",
+ "dotnet_host_sdk",
+ "dotnet_local_sdk",
+)
+load(
+ "//dotnet/platform:list.bzl",
+ "DOTNETARCH",
+ "DOTNETOS",
+ "DOTNETIMPL",
+ "DOTNETIMPL_OS_ARCH",
+)
+
+DEFAULT_VERSION = "4.2.3"
+
+SDK_REPOSITORIES = {
+ "4.2.3": {
+ "mono_darwin_amd64": ("http://bazel-mirror.storage.googleapis.com/download.mono-project.com/archive/4.2.3/macos-10-x86/MonoFramework-MDK-4.2.3.4.macos10.xamarin.x86.tar.gz",
+ "a7afb92d4a81f17664a040c8f36147e57a46bb3c33314b73ec737ad73608e08b"),
+ },
+}
+
+def _generate_toolchains():
+ # Use all the above information to generate all the possible toolchains we might support
+ toolchains = []
+ for impl, os, arch in DOTNETIMPL_OS_ARCH:
+ host = "{}_{}_{}".format(impl, os, arch)
+ toolchain_name = "dotnet_{}".format(host)
+ csc_flags = []
+ toolchains.append(dict(
+ name = toolchain_name,
+ host = host,
+ csc_flags = csc_flags,
+ ))
+ return toolchains
+
+_toolchains = _generate_toolchains()
+
+
+_label_prefix = "@io_bazel_rules_dotnet//dotnet/toolchain:"
+
+def dotnet_register_toolchains(dotnet_version=DEFAULT_VERSION):
+ """See /dotnet/toolchains.rst#dostnet-register-toolchains for full documentation."""
+ if "dotnet_download_sdk" not in native.existing_rules() and "dotnet_host_sdk" not in native.existing_rules() and "dotnet_local_sdk" not in native.existing_rules():
+ if dotnet_version in SDK_REPOSITORIES:
+ dotnet_download_sdk(
+ name = "dotnet_sdk",
+ sdks = SDK_REPOSITORIES[dotnet_version],
+ )
+ elif dotnet_version == "host":
+ dotnet_host_sdk(
+ name = "dotnet_sdk"
+ )
+ else:
+ fail("Unknown dotnet version {}".format(dotnet_version))
+
+ # Use the final dictionaries to register all the toolchains
+ for toolchain in _toolchains:
+ name = _label_prefix + toolchain["name"]
+ native.register_toolchains(name)
+
+
+def declare_constraints():
+ for os, constraint in DOTNETOS.items():
+ if constraint:
+ native.alias(
+ name = os,
+ actual = constraint,
+ )
+ else:
+ native.constraint_value(
+ name = os,
+ constraint_setting = "@bazel_tools//platforms:os",
+ )
+ for arch, constraint in DOTNETARCH.items():
+ if constraint:
+ native.alias(
+ name = arch,
+ actual = constraint,
+ )
+ else:
+ native.constraint_value(
+ name = arch,
+ constraint_setting = "@bazel_tools//platforms:cpu",
+ )
+ native.constraint_setting(name = "dotnetimpl")
+ for impl, constraint in DOTNETIMPL.items():
+ native.constraint_value(
+ name = impl,
+ constraint_setting = ":dotnetimpl",
+ )
+
+
+ for impl, os, arch in DOTNETIMPL_OS_ARCH:
+ native.platform(
+ name = impl + "_" + os + "_" + arch,
+ constraint_values = [
+ ":" + impl,
+ ":" + os,
+ ":" + arch,
+ ],
+ )
+def declare_toolchains():
+ # Use the final dictionaries to create all the toolchains
+ for toolchain in _toolchains:
+ dotnet_toolchain(
+ # Required fields
+ name = toolchain["name"],
+ host = toolchain["host"],
+ )
diff --git a/dotnet/toolchains.rst b/dotnet/toolchains.rst
new file mode 100644
index 00000000000000..71bae5102944f0
--- /dev/null
+++ b/dotnet/toolchains.rst
@@ -0,0 +1,571 @@
+Dotnet toolchains
+=================
+.. _core: core.bzl
+.. _rules_go: https://github.com/bazelbuild/rules_go
+.. _go_toolchains: https://github.com/bazelbuild/rules_go/blob/master/go/toolchains.rst
+.. _DotnetLibrary: providers.bzl#DotnetLibrary
+.. _DotnetResource: providers.bzl#DotnetResource
+
+.. role:: param(kbd)
+.. role:: type(emphasis)
+.. role:: value(code)
+.. |mandatory| replace:: **mandatory value**
+
+
+The design and implementation is heavily based on rules_go_ `toolchains `_.
+
+-----
+
+Design
+------
+
+The Dotnet toolchain consists of three main layers, `the sdk`_ and `the toolchain`_ and `the context`_.
+
+The SDK
+~~~~~~~
+
+At the bottom is the Mono MDK.
+
+This is always bound to ``@dotnet_sdk`` and can be referred to directly if needed, but in general
+you should always access it through the toolchain.
+
+The dotnet_download_sdk_ and dotnet_host_sdk_ family of rules are responsible for downloading
+these, and adding just enough of a build file to expose the contents to Bazel.
+
+If you don't do anything special, the dotnet rules will download the most recent official SDK for
+your host (if available).
+If you need a forked version of dotnet/mono, want to control the version or just use the
+installed sdk then it is easy to do, you just need to make sure you have bound the dotnet_sdk
+repository before you call dotnet_register_toolchains_.
+
+The toolchain
+~~~~~~~~~~~~~
+
+This a wrapper over the sdk that provides enough extras to match, target and work on a specific
+platforms. It should be considered an opaqute type, you only ever use it through `the context`_.
+
+Declaration
+^^^^^^^^^^^
+
+Toolchains are declared using the dotnet_toolchain_ macro.
+
+Toolchains are pre-declared for all the known combinations of host and target, and the names
+are a predictable
+"<**host**>"
+So for instance if the rules_dotnet repository is loaded with
+it's default name, the following toolchain labels (along with many others) will be available
+
+.. code::
+
+ @io_bazel_rules_dotnet//dotnet/toolchain:linux_amd64
+
+The toolchains are not usable until you register them.
+
+Registration
+^^^^^^^^^^^^
+
+Normally you would just call dotnet_register_toolchains_ from your WORKSPACE to register all the
+pre-declared toolchains, and allow normal selection logic to pick the right one.
+
+It is fine to add more toolchains to the available set if you like. Because the normal
+toolchain matching mechanism prefers the first declared match, you can also override individual
+toolchains by declaring and registering toolchains with the same constraints *before* calling
+dotnet_register_toolchains_.
+
+If you wish to have more control over the toolchains you can instead just make direct
+calls to dotnet_register_toolchains_ with only the toolchains you wish to install. You can see an
+example of this in `limiting the available toolchains`_.
+
+
+The context
+~~~~~~~~~~~
+
+This is the type you use if you are writing custom rules that need dotnet toochain.
+
+Use
+^^^
+
+If you are writing a new rule that wants to use the Dotnet toolchain, you need to do a couple of things.
+First, you have to declare that you want to consume the toolchain on the rule declaration.
+The easiest way to do this is to use the dotnet_rule wrapper, which adds in the toolchain and some
+hidden attributes that it consumes.
+
+.. code:: python
+
+ load("@io_bazel_rules_dotnet//dotnet:def.bzl", "dotnet_context")
+
+ my_rule = rule(
+ _my_rule_impl,
+ attrs = {
+ ...
+ "_dotnet_context_data": attr.label(default = Label("@io_bazel_rules_dotnet//:dotnet_context_data"))
+ },
+ toolchains = ["@io_bazel_rules_dotnet//dotnet:toolchain"],
+ )
+
+And then in the rule body, you need to get the toolchain itself and use it's action generators.
+
+.. code:: python
+
+ def _my_rule_impl(ctx):
+ dotnet = dotnet_context(ctx)
+
+
+Customizing
+-----------
+
+Normal usage
+~~~~~~~~~~~~
+
+This is an example of normal usage for the other examples to be compared against.
+
+WORKSPACE
+^^^^^^^^^
+
+.. code:: python
+
+ load("@io_bazel_rules_dotnet//dotnet:def.bzl", "dotnet_rules_dependencies", "dotnet_register_toolchains")
+
+ dotnet_rules_dependencies()
+ dotnet_register_toolchains()
+
+
+Forcing the Dotnet version
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can select the version of the Mono to use by specifying it when you call
+dotnet_register_toolchains_ but you must use a value that matches a known toolchain.
+
+WORKSPACE
+^^^^^^^^^
+
+.. code:: python
+
+ load("@io_bazel_rules_dotnet//dotnet:def.bzl", "dotnet_rules_dependencies", "dotnet_register_toolchains")
+
+ dotnet_rules_dependencies()
+ dotnet_register_toolchains(dotnet_version="4.2.3")
+
+
+Using the installed Mono
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The "host" version is a special toolchain that breaks the hermetic seal to use the host installed
+toolchain.
+
+WORKSPACE
+^^^^^^^^^
+
+.. code:: python
+
+ load("@io_bazel_rules_dotnet//dotnet:def.bzl", "dotnet_rules_dependencies", "dotnet_register_toolchains")
+
+ dotnet_rules_dependencies()
+ dotnet_register_toolchains(go_version="host")
+
+
+
+Registering a custom Mono
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you want to register your own toolchain that takes precedence over the pre-declared ones you can
+just add it and register it before the normal ones.
+
+WORKSPACE
+^^^^^^^^^
+
+.. code:: python
+
+ load("@io_bazel_rules_dotnet//dotnet:def.bzl", "dotnet_rules_dependencies", "dotnet_register_toolchains", "dotnet_download_sdk")
+
+ dotnet_download_sdk(name="my_macos_sdk", url="http://bazel-mirror.storage.googleapis.com/download.mono-project.com/archive/4.2.3/macos-10-x86/MonoFramework-MDK-4.2.3.4.macos10.xamarin.x86.tar.gz")
+ register_toolchains(
+ "@//:my_macos_toolchain",
+ )
+
+ dotnet_rules_dependencies()
+ dotnet_register_toolchains()
+
+
+BUILD.bazel
+^^^^^^^^^^^
+
+.. code:: python
+
+ dotnet_toolchain(name="my_macos_toolchain", sdk="my_macos_sdk")
+
+
+Limiting the available toolchains
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you wanted to only allow your project to be compiled on mac at Mono version 4.2.3,
+instead of calling dotnet_register_toolchains_ you can put
+
+WORKSPACE
+^^^^^^^^^
+
+.. code:: python
+
+ load("@io_bazel_rules_dotnet//dotnet:def.bzl", "dotnet_rules_dependencies")
+
+ dotnet_rules_dependencies()
+ register_toolchains(
+ "@io_bazel_rules_dotnet//dotnet/toolchain:4.2.3_darwin_amd64",
+ )
+
+
+API
+---
+
+dotnet_register_toolchains
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Installs the Dotnet toolchains. If :param:`dotnet_version` is specified, it sets the
+Mono version to use (for example, :value:`"4.2.3"`). By default, the latest
+Mono will be used.
+
++--------------------------------+-----------------------------+-----------------------------------+
+| **Name** | **Type** | **Default value** |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`dotnet_version` | :type:`string` | :value:`"4.2.3"` |
++--------------------------------+-----------------------------+-----------------------------------+
+| This specifies the Mono version to select. |
+| It will match the version specification of the toochain which for normal sdk toolchains is |
+| also the string part of the binary distribution you want to use. |
+| You can also use it to select the "host" sdk toolchain, or a custom toolchain with a |
+| specialized version string. |
++--------------------------------+-----------------------------+-----------------------------------+
+
+dotnet_download_sdk
+~~~~~~~~~~~~~~~~~~~
+
+This downloads Mono for use in toolchains.
+
++--------------------------------+-----------------------------+-----------------------------------+
+| **Name** | **Type** | **Default value** |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++--------------------------------+-----------------------------+-----------------------------------+
+| A unique name for this sdk. This should almost always be :value:`dotnet_sdk` if you want the SDK |
+| to be used by toolchains. |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`urls` | :type:`string_list` | :value:`official distributions` |
++--------------------------------+-----------------------------+-----------------------------------+
+| A list of mirror urls to the binary distribution of Mono. These must contain the `{}` |
+| used to substitute the sdk filename being fetched (using `.format`. |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`strip_prefix` | :type:`string` | :value:`""` |
++--------------------------------+-----------------------------+-----------------------------------+
+| A directory prefix to strip from the extracted files. |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`sdks` | :type:`string_list_dict` | |mandatory| |
++--------------------------------+-----------------------------+-----------------------------------+
+| This consists of a set of mappings from the host platform tuple to a list of filename and |
+| sha256 for that file. The filename is combined the :param:`urls` to produce the final download |
+| urls to use. |
+| |
+| As an example: |
+| |
+| .. code:: python |
+| |
+| dotnet_download_sdk( |
+| name = "dotnet_sdk", |
+| sdks = { |
+| "linux_amd64": ("go1.8.1.linux-amd64.tar.gz", |
+| "a579ab19d5237e263254f1eac5352efcf1d70b9dacadb6d6bb12b0911ede8994"), |
+| "darwin_amd64": ("go1.8.1.darwin-amd64.tar.gz", |
+| "25b026fe2f4de7c80b227f69588b06b93787f5b5f134fbf2d652926c08c04bcd"), |
+| }, |
+| ) |
+| |
++--------------------------------+-----------------------------+-----------------------------------+
+
+
+dotnet_host_sdk
+~~~~~~~~~~~~~~~
+
+This detects the host Mono for use in toolchains.
+
+It searches the PATH. You can achive the same result by setting
+the version to "host" when registering toolchains to select the installed sdk so it should
+never be neccesary to use this feature directly.
+
++--------------------------------+-----------------------------+-----------------------------------+
+| **Name** | **Type** | **Default value** |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++--------------------------------+-----------------------------+-----------------------------------+
+| A unique name for this sdk. This should almost always be :value:`dotnet_sdk` if you want the SDK |
+| to be used by toolchains. |
++--------------------------------+-----------------------------+-----------------------------------+
+
+
+dotnet_context
+~~~~~~~~~~~~~~
+
+This collects the information needed to form and return a :type:`DotnetContext` from a rule ctx.
+It uses the attrbutes and the toolchains.
+It can only be used in the implementation of a rule that has the dotnet toolchain attached and
+the dotnet context data as an attribute.
+
+.. code:: python
+
+ my_rule = rule(
+ _my_rule_impl,
+ attrs = {
+ ...
+ "_dotnet_context_data": attr.label(default = Label("@io_bazel_rules_dotnet//:dotnet_context_data"))
+ },
+ toolchains = ["@io_bazel_rules_dotnet//dotnet:toolchain"],
+ )
+
+
++--------------------------------+-----------------------------+-----------------------------------+
+| **Name** | **Type** | **Default value** |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`ctx` | :type:`ctx` | |mandatory| |
++--------------------------------+-----------------------------+-----------------------------------+
+| The Bazel ctx object for the current rule. |
++--------------------------------+-----------------------------+-----------------------------------+
+
+The context object
+~~~~~~~~~~~~~~~~~~
+
+DotnetContext is never returned by a rule, instead you build one using dotnet_context(ctx) in the
+top of any custom skylark rule that wants to interact with the go rules.
+It provides all the information needed to create dotnet actions, and create or interact with the
+other dotnet providers.
+
+When you get a DotnetContext from a context (see use_) it exposes a number of fields and methods.
+
+All methods take the DotnetContext as the only positional argument, all other arguments even if
+mandatory must be specified by name, to allow us to re-order and deprecate individual parameters
+over time.
+
+
+Methods
+^^^^^^^
+
+* Action generators
+
+ * library_
+ * binary_
+ * resx_
+
+* Helpers
+
+ * declare_file_
+ * new_library_
+ * new_resource_
+
+
+Fields
+^^^^^^
+
++--------------------------------+-----------------------------------------------------------------+
+| **Name** | **Type** |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`toolchain` | :type:`DotnetToolchain` |
++--------------------------------+-----------------------------------------------------------------+
+| The underlying toolchain. This should be considered an opaque type subject to change. |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`exe_extension` | :type:`string` |
++--------------------------------+-----------------------------------------------------------------+
+| The suffix to use for all executables in this build mode. Mostly used when generating the output |
+| filenames of binary rules. |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`runner` | :type:`File` |
++--------------------------------+-----------------------------------------------------------------+
+| The "mono" binary used to run dotnet executables |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`mcs` | :type:`File` |
++--------------------------------+-----------------------------------------------------------------+
+| The main "mcs" (C# compiler) binary used. |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`resgen` | :type:`File` |
++--------------------------------+-----------------------------------------------------------------+
+| The resource compiler (dotnet executable). |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`stdlib` | :type:`File` |
++--------------------------------+-----------------------------------------------------------------+
+| The standard library (mscorlib.dll) to use in the build. |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`libVersion` | :type:`string` |
++--------------------------------+-----------------------------------------------------------------+
+| The mono library version to used. The default is 4.7-api |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`actions` | :type:`ctx.actions` |
++--------------------------------+-----------------------------------------------------------------+
+| The actions structure from the Bazel context, which has all the methods for building new |
+| bazel actions. |
++--------------------------------+-----------------------------------------------------------------+
+| :param:`lib` | :type:`label` |
++--------------------------------+-----------------------------------------------------------------+
+| The label for directory with the selected libraryVersion assemblies |
++--------------------------------+-----------------------------------------------------------------+
+
+
+library
+~~~~~~~
+
+The library function adds an action that compiles the set of sources into assembly.
+
+It returns DotnetLibrary_ provider.
+
++--------------------------------+--------------------------------+-----------------------------------+
+| **Name** | **Type** | **Default value** |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`dotnet` | :type:`DotnetContext` | |mandatory| |
++--------------------------------+--------------------------------+-----------------------------------+
+| This must be the same DotnetContext object you got this function from. |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`srcs` | :type:`File iterable` | |mandatory| |
++--------------------------------+--------------------------------+-----------------------------------+
+| An iterable of source code artifacts. |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`deps` | :type:`DotnetLibrary iterable` | :value:`[]` |
++--------------------------------+--------------------------------+-----------------------------------+
+| An iterable of all directly imported libraries. |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`resources` | :type:`DotnetResource iterable`| :value:`[]` |
++--------------------------------+--------------------------------+-----------------------------------+
+| An iterable of all directly imported libraries. |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`out` | :type:`string` | :value:`""` |
++--------------------------------+--------------------------------+-----------------------------------+
+| An alternative name of the output file |
++--------------------------------+--------------------------------+-----------------------------------+
+
+binary
+~~~~~~
+
+The function adds an action that compiles the set of sources into executable assembly.
+
+It returns DotnetLibrary_ provider.
+
++--------------------------------+--------------------------------+-----------------------------------+
+| **Name** | **Type** | **Default value** |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`dotnet` | :type:`DotnetContext` | |mandatory| |
++--------------------------------+--------------------------------+-----------------------------------+
+| This must be the same DotnetContext object you got this function from. |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`srcs` | :type:`File iterable` | |mandatory| |
++--------------------------------+--------------------------------+-----------------------------------+
+| An iterable of source code artifacts. |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`deps` | :type:`DotnetLibrary iterable` | :value:`[]` |
++--------------------------------+--------------------------------+-----------------------------------+
+| An iterable of all directly imported libraries. |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`resources` | :type:`DotnetResource iterable`| :value:`[]` |
++--------------------------------+--------------------------------+-----------------------------------+
+| An iterable of all directly imported libraries. |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`out` | :type:`string` | :value:`""` |
++--------------------------------+--------------------------------+-----------------------------------+
+| An alternative name of the output file |
++--------------------------------+--------------------------------+-----------------------------------+
+
+resx
+~~~~
+
+The function adds an action that compiles a single .resx file into .resources file.
+
+It returns DotnetResource_ provider.
+
++----------------------------+-----------------------------+---------------------------------------+
+| **Name** | **Type** | **Default value** |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+---------------------------------------+
+| A unique name for this rule. |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`src` | :type:`label` | |mandatory| |
++----------------------------+-----------------------------+---------------------------------------+
+| The .resx source file that is transformed into .resources file. |
+| Only :value:`.resx` files are permitted |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`identifer` | :type:`string` | :value:`""` |
++----------------------------+-----------------------------+---------------------------------------+
+| The logical name for the resource; the name that is used to load the resource. |
+| The default is the basename of the file name (no subfolder). |
++----------------------------+-----------------------------+---------------------------------------+
+| :param:`out` | :type:`string` | :value:`""` |
++----------------------------+-----------------------------+---------------------------------------+
+| An alternative name of the output file |
++----------------------------+-----------------------------+---------------------------------------+
+
+
+declare_file
+~~~~~~~~~~~~
+
+This is the equivalent of ctx.actions.declare_file.
+
++--------------------------------+-----------------------------+-----------------------------------+
+| **Name** | **Type** | **Default value** |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`dotnet` | :type:`DotnetContext` | |mandatory| |
++--------------------------------+-----------------------------+-----------------------------------+
+| This must be the same DotnetContext object you got this function from. |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`path` | :type:`string` | :value:`""` |
++--------------------------------+-----------------------------+-----------------------------------+
+| A path for this file, including the basename of the file. |
++--------------------------------+-----------------------------+-----------------------------------+
+
+new_library
+~~~~~~~~~~~
+
+This creates a new DotnetLibrary_.
+You can add extra fields to the go library by providing extra named parameters to this function,
+they will be visible to the resolver when it is invoked.
+
++--------------------------------+--------------------------------+-----------------------------------+
+| **Name** | **Type** | **Default value** |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++--------------------------------+--------------------------------+-----------------------------------+
+| A unique name for this library. |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`dotnet` | :type:`DotnetContext` | |mandatory| |
++--------------------------------+--------------------------------+-----------------------------------+
+| This must be the same DotnetContext object you got this function from. |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`deps` | :type:`list of DotnetLibrary` | |
++--------------------------------+--------------------------------+-----------------------------------+
+| The direct dependencies of this library. |
++--------------------------------+--------------------------------+-----------------------------------+
+| :param:`transitive` | :type:`depset of DotnetLibrary`| |
++--------------------------------+--------------------------------+-----------------------------------+
+| The full set of transitive dependencies. This includes ``deps`` for this |
+| library and all ``deps`` members transitively reachable through ``deps``. |
++--------------------------------+--------------------------------+-----------------------------------+
+
+new_resource
+~~~~~~~~~~~~
+
+This creates a new DotnetResource_.
+You can add extra fields to the go library by providing extra named parameters to this function,
+they will be visible to the resolver when it is invoked.
+
++--------------------------------+-----------------------------+-----------------------------------+
+| **Name** | **Type** | **Default value** |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++--------------------------------+-----------------------------+-----------------------------------+
+| A unique name for this library. |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`dotnet` | :type:`DotnetContext` | |mandatory| |
++--------------------------------+-----------------------------+-----------------------------------+
+| This must be the same DotnetContext object you got this function from. |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`result` | :type:`File` | |mandatory| |
++--------------------------------+-----------------------------+-----------------------------------+
+| The .resources file. |
++--------------------------------+-----------------------------+-----------------------------------+
+| :param:`identifier` | :type:`string` | :value:`None` |
++--------------------------------+-----------------------------+-----------------------------------+
+| Identifier passed to -resource flag of mcs compiler. If empty the basename of the result |
+| is used. |
++--------------------------------+-----------------------------+-----------------------------------+
diff --git a/dotnet/tools/BUILD b/dotnet/tools/BUILD
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/dotnet/tools/common/BUILD b/dotnet/tools/common/BUILD
new file mode 100644
index 00000000000000..702efa5dd346b0
--- /dev/null
+++ b/dotnet/tools/common/BUILD
@@ -0,0 +1,13 @@
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+ name = "common",
+ srcs = glob([
+ "*.c",
+ ]),
+ hdrs = glob([
+ "*.h",
+ ]),
+)
+
+exports_files(["manifest.h"])
\ No newline at end of file
diff --git a/dotnet/tools/common/manifest.c b/dotnet/tools/common/manifest.c
new file mode 100644
index 00000000000000..28e90df40d00a0
--- /dev/null
+++ b/dotnet/tools/common/manifest.c
@@ -0,0 +1,281 @@
+#include
+#include
+#include
+#include
+#include
+#ifdef _MSC_VER
+#include
+#include
+#include
+#include
+#include
+#define F_OK 0
+#pragma comment(lib, "shlwapi.lib")
+#else
+#include
+#include
+#endif
+
+#include "manifest.h"
+
+extern const char * Exe;
+struct Entry* g_Entries = NULL;
+
+
+void ReadManifest(const char *manifestDir)
+{
+ char buffer[64*1024];
+ FILE *f;
+ char *p;
+ int line = 0;
+ struct Entry *entry;
+
+ strcpy(buffer, manifestDir);
+ strcat(buffer, "/MANIFEST");
+ /* read manifest file */
+ f = fopen(buffer, "r");
+ if (f == NULL) {
+ p = getcwd(buffer, sizeof(buffer));
+ printf("Can't open file MANIFEST in %s\n", p);
+ exit(-1);
+ }
+ while (fgets(buffer, sizeof(buffer), f) != NULL )
+ {
+ ++line;
+ p = strchr(buffer, '\n');
+ if (p != NULL)
+ *p = '\0';
+ p = strchr(buffer, '\r');
+ if (p != NULL)
+ *p = '\0';
+
+ p = strchr(buffer, ' ');
+ if (p == NULL) {
+ printf("Line %d is malformatted (no space)\n", line);
+ exit(-1);
+ }
+ *p = '\0';
+ entry = (struct Entry*) malloc(sizeof(struct Entry));
+ entry->Key = strdup(buffer);
+ entry->Path = strdup(p+1);
+ entry->Next = g_Entries;
+ g_Entries = entry;
+ }
+ fclose (f);
+}
+
+#ifdef _MSC_VER
+static void CreateLinkIfNeeded(const char* target, const char *toCreate)
+{
+ BOOL result;
+ DWORD error;
+ DWORD flag;
+
+ if (!PathFileExists(target)) {
+ printf("File %s does not exist\n", target);
+ exit(-1);
+ }
+
+ flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
+ retry:
+ result = CreateSymbolicLinkA(toCreate, target, flag);
+ if (!result) {
+ error = GetLastError();
+ if (error == 87 && flag!=0) {
+ printf("SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE seems not supported\n");
+ flag = 0;
+ goto retry;
+ }
+ if (error != ERROR_ALREADY_EXISTS) {
+ printf("Error %d on linking %s to %s\n", error, toCreate, target);
+ exit(-1);
+ }
+ }
+}
+#else
+static void CreateLinkIfNeeded(const char* target, const char *toCreate)
+{
+ int result;
+ if (access(target, F_OK)==-1) {
+ printf("File %s does not exist\n", target);
+ exit(-1);
+ }
+
+ result = symlink(target, toCreate);
+ if (result!=0) {
+ int error = errno;
+ if (error != EEXIST) {
+ printf("Error %d on linking %s to %s\n", error, toCreate, target);
+ exit(-1);
+ }
+ }
+}
+#endif
+
+void LinkFiles(const char *manifestDir) {
+ const struct Entry *p = g_Entries;
+ const char *basename;
+ char toCreate[64*1024];
+
+ while(p != NULL) {
+ basename = strrchr(p->Key, '/');
+ if (basename == NULL)
+ basename = p->Key;
+ else
+ ++basename;
+
+ sprintf(toCreate, "%s/%s", manifestDir, basename);
+
+ CreateLinkIfNeeded(p->Path, toCreate);
+ p = p->Next;
+ }
+}
+
+#ifdef _MSC_VER
+typedef struct _stat Stat;
+static void do_mkdir(const char *path)
+{
+ Stat st;
+
+ if (access(path, F_OK) == 0) {
+ return;
+ }
+
+ /* Directory does not exist. EEXIST for race condition */
+ if (CreateDirectoryA(path, NULL) == 0) {
+ printf("Error %d creating directory for %s\n", GetLastError(), path);
+ exit(-1);
+ }
+}
+
+#else
+
+typedef struct stat Stat;
+static void do_mkdir(const char *path)
+{
+ Stat st;
+ int status = 0;
+
+ if (stat(path, &st) != 0)
+ {
+ /* Directory does not exist. EEXIST for race condition */
+ if (mkdir(path, 0777) != 0 && errno != EEXIST)
+ status = -1;
+ }
+ else if (!S_ISDIR(st.st_mode))
+ {
+ errno = ENOTDIR;
+ status = -1;
+ }
+
+ if (status != 0) {
+ printf("Error %d creating directory for %s\n", errno, path);
+ //exit(-1);
+ }
+}
+#endif
+
+static void NormalizeDir(char *path)
+{
+ char *q, *p;
+ while ((q = strchr(path, '\\'))!= NULL) {
+ *q = '/';
+ }
+
+ while((p = strstr(path, "../"))!=NULL) {
+ q = strchr(p+3, '/');
+ if (q == NULL) {
+ printf("Failed to normalize dir %s\n", path);
+ exit(-1);
+ }
+
+ memcpy(p, q+1, strlen(q+1)+1);
+ }
+}
+static void CreateDirTreeForFile(const char * path)
+{
+ char *pp;
+ char *sp;
+ char copypath[64*1024];
+
+ strcpy(copypath, path);
+
+ pp = strrchr(copypath, '/');
+ *(pp+1) = '\0';
+
+ pp = copypath;
+ while ((sp = strchr(pp, '/')) != NULL)
+ {
+ if (sp != pp)
+ {
+ /* Neither root nor double slash in path */
+ *sp = '\0';
+ do_mkdir(copypath);
+ *sp = '/';
+ }
+ pp = sp + 1;
+ }
+}
+
+
+void LinkFilesTree(const char *manifestDir) {
+ const struct Entry *p = g_Entries;
+ char toCreate[64*1024];
+
+ while(p != NULL) {
+ sprintf(toCreate, "%s%s", manifestDir, p->Key);
+ NormalizeDir(toCreate);
+
+ CreateDirTreeForFile(toCreate);
+ CreateLinkIfNeeded(p->Path, toCreate);
+ p = p->Next;
+ }
+}
+
+/* I didn't find an easy way to locate MANIFEST file.
+ Until now, I have identified the following cases:
+ 1. Current directory (run on Windows).
+ 2. Parrent directory (run on Linux and osx).
+ 3. /.runfiles (when used as a tool and launcher is this program)
+ This function tries to locate the MANIFEST file and returns
+ an absolute path to directory with it.
+*/
+const char *GetManifestDir() {
+ static char buffer[64*1024];
+ char *p;
+ p = getcwd(buffer, sizeof(buffer));
+ if (access("MANIFEST", F_OK)!=-1)
+ return buffer;
+
+
+ strcat(buffer, "/../MANIFEST");
+ if (access(buffer, F_OK)!=-1) {
+ p = strrchr(buffer, '/');
+ *(p+1) = '\0';
+
+ return buffer;
+ }
+
+ p = getcwd(buffer, sizeof(buffer));
+ strcat(buffer, "/");
+ strcat(buffer, Exe);
+ /* We have to convert Exe name to this launcher name (by removing _exe suffix and possibly .exe
+ on non-Windows platforms) */
+ p = strrchr(buffer, '_');
+ #ifdef _MSC_VER
+ strcpy(p, p+4);
+ #else
+ strcpy(p, p+8);
+ #endif
+
+ strcat(buffer, ".runfiles/MANIFEST");
+ printf("Checking %s\n", buffer);
+ if (access(buffer, F_OK)!=-1) {
+ p = strrchr(buffer, '/');
+ *(p+1) = '\0';
+ return buffer;
+ }
+
+ printf("Couldn't find MANIFEST file\n");
+ exit(-1);
+}
diff --git a/dotnet/tools/common/manifest.h b/dotnet/tools/common/manifest.h
new file mode 100644
index 00000000000000..7d34381247e72b
--- /dev/null
+++ b/dotnet/tools/common/manifest.h
@@ -0,0 +1,13 @@
+struct Entry {
+ const char *Key;
+ const char *Path;
+ const struct Entry* Next;
+};
+
+extern struct Entry* g_Entries;
+
+void ReadManifest(const char *manifestDir);
+void LinkFiles(const char *manifestDir);
+void LinkFilesTree(const char *manifestDir);
+const char *GetManifestDir();
+
diff --git a/dotnet/tools/runner/BUILD b/dotnet/tools/runner/BUILD
new file mode 100644
index 00000000000000..64e1b6413edff7
--- /dev/null
+++ b/dotnet/tools/runner/BUILD
@@ -0,0 +1,9 @@
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+ name = "runner",
+ srcs = glob([
+ "*.c",
+ ]),
+ deps = ["//dotnet/tools/common:common"],
+)
diff --git a/dotnet/tools/runner/main.c b/dotnet/tools/runner/main.c
new file mode 100644
index 00000000000000..5da6d3c8895e4c
--- /dev/null
+++ b/dotnet/tools/runner/main.c
@@ -0,0 +1,120 @@
+#include
+#include
+#include
+#ifdef _MSC_VER
+#include
+#include
+#include
+#include
+#include
+#define F_OK 0
+#pragma comment(lib, "shlwapi.lib")
+#else
+#include
+#include
+#endif
+
+#include "dotnet/tools/common/manifest.h"
+
+extern const char * Exe;
+extern const char * Nunit;
+
+
+
+static void RunExe(const char *manifestDir, int argc, char **argv) {
+ char fullpath[64*1024];
+ char **args;
+ int i, c;
+ int test = strlen(Nunit) > 0;
+#ifndef _MSC_VER
+ char monofullpath[64*1024];
+#endif
+
+ getcwd(fullpath, sizeof(fullpath));
+ printf("cwd %s\n", fullpath);
+
+ /* Find Exe's real path */
+ const char *found = strrchr(Exe, '/');
+ if (found == NULL) {
+ found = Exe;
+ } else {
+ ++found;
+ }
+#ifdef _MSC_VER
+ c = argc+1;
+ if (test) c = c + 2;
+ args = malloc( (c) * sizeof(char*));
+ c = 0;
+ if (test) {
+ sprintf(fullpath, "%s/nunit-console-runner-exe_exe.exe", manifestDir);
+ args[c++] = strdup(fullpath);
+ sprintf(fullpath, "-result=%s", getenv("XML_OUTPUT_FILE"));
+ args[c++] = strdup(fullpath);
+ }
+ sprintf(fullpath, "%s/%s", manifestDir, found);
+ args[c++] = strdup(fullpath);
+ for(i = 1; i < argc; ++i) {
+ args[c++] = argv[i];
+ }
+ args[c] = NULL;
+ for(i = 0; args[i]!=NULL; ++i) {
+ printf("Arg %d = %s\n", i, args[i]);
+ }
+ i = _spawnvp(_P_WAIT, args[0], args);
+ if (i != 0) {
+ printf("Couldn't execute %s or returned status code != 0\n", fullpath);
+ exit(-1);
+ }
+#else
+ c = argc+2;
+
+ if (test) c = c+2;
+ args = malloc( (c) * sizeof(char*));
+ c = 0;
+ sprintf(monofullpath, "%s/mono", manifestDir);
+ args[c++] = strdup(monofullpath);
+ if (test) {
+ sprintf(fullpath, "%s/nunit-console-runner-exe_exe.exe", manifestDir);
+ args[c++] = strdup(fullpath);
+ sprintf(fullpath, "-result=%s", getenv("XML_OUTPUT_FILE"));
+ args[c++] = strdup(fullpath);
+ }
+ sprintf(fullpath, "%s/%s", manifestDir, found);
+ args[c++] = strdup(fullpath);
+ for(i = 1; i < argc; ++i) {
+ args[c++] = argv[i];
+ }
+ args[c] = NULL;
+ for(i = 0; args[i]!=NULL; ++i) {
+ printf("Arg %d = %s\n", i, args[i]);
+ }
+ for(i = 0; args[i]!=NULL; ++i) {
+ printf("Arg %d = %s\n", i, args[i]);
+ }
+ if (execvp(args[0], args) == -1) {
+ printf("Couldn't execute %s, (%d)\n", found, errno);
+ exit(-1);
+ }
+#endif
+}
+
+
+int main(int argc, char *argv[], char *envp[])
+{
+ const char *manifestDir;
+ char buffer[64*1024];
+
+ printf("Launcher running %s (%s)\n", Exe, Nunit);
+ if (strlen(Exe) > 32*1024) {
+ printf("File path %s too long\n", Exe);
+ return -1;
+ }
+ manifestDir = GetManifestDir();
+ sprintf(buffer, "MONO_PATH=%s", manifestDir);
+ putenv(buffer);
+ ReadManifest(manifestDir);
+ LinkFiles(manifestDir);
+ RunExe(manifestDir, argc, argv);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/dotnet/tools/test_prep/BUILD b/dotnet/tools/test_prep/BUILD
new file mode 100644
index 00000000000000..ab925f76f2cf09
--- /dev/null
+++ b/dotnet/tools/test_prep/BUILD
@@ -0,0 +1,9 @@
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+ name = "test_prep",
+ srcs = glob([
+ "*.c",
+ ]),
+ deps = ["//dotnet/tools/common:common"],
+)
diff --git a/dotnet/tools/test_prep/main.c b/dotnet/tools/test_prep/main.c
new file mode 100644
index 00000000000000..086a8f90a4a868
--- /dev/null
+++ b/dotnet/tools/test_prep/main.c
@@ -0,0 +1,35 @@
+#include
+#include
+#include
+#ifdef _MSC_VER
+#include
+#include
+#include
+#include
+#include
+#define F_OK 0
+#pragma comment(lib, "shlwapi.lib")
+#else
+#include
+#include
+#endif
+
+#include "dotnet/tools/common/manifest.h"
+
+extern const char * Exe;
+
+int main(int argc, char *argv[], char *envp[])
+{
+ const char *manifestDir;
+ printf("Test prep running %s)\n", Exe);
+ if (strlen(Exe) > 32*1024) {
+ printf("File path %s too long\n", Exe);
+ return -1;
+ }
+
+ manifestDir = GetManifestDir();
+ ReadManifest(manifestDir);
+ LinkFilesTree(manifestDir);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/dotnet/workspace.rst b/dotnet/workspace.rst
new file mode 100644
index 00000000000000..ea7834506abb3d
--- /dev/null
+++ b/dotnet/workspace.rst
@@ -0,0 +1,131 @@
+Dotnet workspace rules
+======================
+
+.. _dotnet_library: core.rst#dotnet_library
+.. _toolchains: toolchains.rst
+.. _dotnet_register_toolchains: toolchains.rst#dotnet_register_toolchains
+.. _dotnet_toolchain: toolchains.rst#dotnet_toolchain
+.. _http_archive: https://docs.bazel.build/versions/master/be/workspace.html#http_archive
+.. _git_repository: https://docs.bazel.build/versions/master/be/workspace.html#git_repository
+.. _nested workspaces: https://bazel.build/designs/2016/09/19/recursive-ws-parsing.html
+.. _dotnet_import_library: core.rst#dotnet_import_library
+
+.. role:: param(kbd)
+.. role:: type(emphasis)
+.. role:: value(code)
+.. |mandatory| replace:: **mandatory value**
+
+Workspace rules are either repository rules, or macros that are intended to be used from the
+WORKSPACE file.
+
+See also the toolchains_ rules, which contains the dotnet_register_toolchains_
+workspace rule.
+
+.. contents:: :depth: 1
+
+-----
+
+
+dotnet_repositories
+~~~~~~~~~~~~~~~~~~~
+
+Fetches remote repositories required by dotnet rules.
+
+dotnet_nuget
+~~~~~~~~~~~~
+
+A simple repository rule to download and extract nuget package. Using dotnet_nuget_new_ is usually
+a better idea.
+
+
+Attributes
+^^^^^^^^^^
+
++----------------------------+-----------------------------+-----------------------------------------------+
+| **Name** | **Type** | **Default value** |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+-----------------------------------------------+
+| A unique name for this rule. |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`source` | :type:`string` | :value:`https://www.nuget.org/api/v2/package` |
++----------------------------+-----------------------------+-----------------------------------------------+
+| The nuget base url for downloading the package. The final url is in the format |
+| {source}/{package}/{version}. |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`package` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+-----------------------------------------------+
+| The nuget package name |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`version` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+-----------------------------------------------+
+| The nuget package version. |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`sha256` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+-----------------------------------------------+
+| The nuget package sha256 digest. |
++----------------------------+-----------------------------+-----------------------------------------------+
+
+
+dotnet_nuget_new
+~~~~~~~~~~~~~~~~
+
+Repository rule to download and extract nuget package. Usually used with dotnet_import_library_.
+
+
+Attributes
+^^^^^^^^^^
+
++----------------------------+-----------------------------+-----------------------------------------------+
+| **Name** | **Type** | **Default value** |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`name` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+-----------------------------------------------+
+| A unique name for this rule. |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`source` | :type:`string` | :value:`https://www.nuget.org/api/v2/package` |
++----------------------------+-----------------------------+-----------------------------------------------+
+| The nuget base url for downloading the package. The final url is in the format |
+| {source}/{package}/{version}. |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`package` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+-----------------------------------------------+
+| The nuget package name |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`version` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+-----------------------------------------------+
+| The nuget package version. |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`sha256` | :type:`string` | |mandatory| |
++----------------------------+-----------------------------+-----------------------------------------------+
+| The nuget package sha256 digest. |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`build_file` | :type:`label` | :value:`None` |
++----------------------------+-----------------------------+-----------------------------------------------+
+| The build file to link into downloaded nnuget package. |
++----------------------------+-----------------------------+-----------------------------------------------+
+| :param:`build_file_content`| :type:`string` | :value:`""` |
++----------------------------+-----------------------------+-----------------------------------------------+
+| The build file content to put into downloaded nnuget package. |
++----------------------------+-----------------------------+-----------------------------------------------+
+
+Example
+^^^^^^^
+
+.. code:: python
+
+ dotnet_nuget_new(
+ name = "npgsql",
+ package="Npgsql",
+ version="3.2.7",
+ sha256="fa3e0cfbb2caa9946d2ce3d8174031a06320aad2c9e69a60f7739b9ddf19f172",
+ build_file_content = """
+ package(default_visibility = [ "//visibility:public" ])
+ load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_import_library")
+
+ dotnet_import_library(
+ name = "npgsqllib",
+ src = "lib/net451/Npgsql.dll"
+ )
+ """
+ )
diff --git a/examples/example_binary/BUILD b/examples/example_binary/BUILD
deleted file mode 100644
index a899294e4d5f72..00000000000000
--- a/examples/example_binary/BUILD
+++ /dev/null
@@ -1,12 +0,0 @@
-load("//dotnet:csharp.bzl", "csharp_binary")
-
-csharp_binary(
- name = "hello",
- srcs = [
- "Program.cs",
- "Properties/AssemblyInfo.cs",
- ],
- deps = [
- "//examples/example_lib:MyClass",
- ],
-)
diff --git a/examples/example_lib/BUILD b/examples/example_lib/BUILD
deleted file mode 100644
index 7b5e971e046ed9..00000000000000
--- a/examples/example_lib/BUILD
+++ /dev/null
@@ -1,14 +0,0 @@
-load("//dotnet:csharp.bzl", "csharp_library")
-
-csharp_library(
- name = "MyClass",
- srcs = [
- "MyClass.cs",
- "Properties/AssemblyInfo.cs",
- ],
- resources = [ "hello.txt" ],
- visibility = ["//visibility:public"],
- deps = [
- "//examples/example_transitive_lib:TransitiveClass",
- ],
-)
diff --git a/examples/example_test/BUILD b/examples/example_test/BUILD
deleted file mode 100644
index e00017ab4b2838..00000000000000
--- a/examples/example_test/BUILD
+++ /dev/null
@@ -1,11 +0,0 @@
-load("//dotnet:csharp.bzl", "csharp_nunit_test")
-
-csharp_nunit_test(
- name = "MyTest",
- srcs = [
- "MyTest.cs",
- ],
- deps = [
- "//examples/example_lib:MyClass",
- ],
-)
diff --git a/index.rst b/index.rst
new file mode 100644
index 00000000000000..da6d87380ac721
--- /dev/null
+++ b/index.rst
@@ -0,0 +1,26 @@
+.. rules_dotnet documentation master file, created by
+ sphinx-quickstart on Tue May 08 22:36:57 2018.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to rules_dotnet's documentation!
+========================================
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ README
+ dotnet/core
+ dotnet/workspace
+ dotnet/providers
+ dotnet/toolchains
+ dotnet/private/skylib/README
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel
new file mode 100644
index 00000000000000..cdf7ea22e58329
--- /dev/null
+++ b/tests/BUILD.bazel
@@ -0,0 +1,9 @@
+
+# Consuming the above md5_sum rule directly into the data deps of a sh_test results in the
+# files just not appearing, and the dependancy not triggering.
+# If we wrap it in a filegroup first however it just works.
+filegroup(
+ name = "rules_dotnet_deps",
+ srcs = ["//dotnet:all_rules"],
+ visibility = ["//visibility:public"],
+)
diff --git a/tests/README.rst b/tests/README.rst
new file mode 100644
index 00000000000000..d82e400ef80274
--- /dev/null
+++ b/tests/README.rst
@@ -0,0 +1,53 @@
+Dotnet rules test suite
+=======================
+
+Main test areas
+---------------
+
+.. Child list start
+
+* `Dotnet rules examples `_
+* `Core Dotnet rules tests `_
+
+.. Child list end
+
+Adding a new test
+-----------------
+
+All tests in the test suite are expected to obey certain rules.
+
+They must be documented
+ Each test folder must contain a README.rst that documents the area of
+ reponsability for the folder. That README must have a section with
+ the same name as each of the test rules that documents exactly what the
+ test is supposed to be checking for.
+ If the test is in response to a previous issue, the documentation must
+ also link to the issue being addressed.
+
+Test one thing at a time
+ Each test should have a clear and specific responsability, and it should be
+ as tightly targeted as possible.
+ Prefer writing multiple tests in a single folder to a single test that
+ excercises multiple things.
+
+They must be turned on
+ Test that do not run by default on the CI machines are not much use,
+ especially as it's often the only way changes get tested in environments
+ that are not the one they are authored on, and the rules are very sensitive
+ to platform specific variations.
+
+They must not be flakey
+ We will generally just delete tests that flake, and if features cannot be
+ tested without flakes we will probably delete the feature as well.
+
+They must work on all platforms
+ We support mac, linux and windows, and all our code must work across all
+ hosts. There are some tests that need to be platform specific, but it's
+ very rare, and needs a really strong rationale to be accepted.
+
+They must be as fast as possible
+ Some tests need to be large and expensive, but most do not. In particular,
+ downloading large external dependancies to perform a small unit test is not
+ ok, prefer creating a small local replication of the problem instead.
+ Anything that requires external dependancies beyond those of the rules
+ belongs in the integration tests.
\ No newline at end of file
diff --git a/tests/bazel_tests.bzl b/tests/bazel_tests.bzl
new file mode 100644
index 00000000000000..11b1980dfb3ebe
--- /dev/null
+++ b/tests/bazel_tests.bzl
@@ -0,0 +1,294 @@
+load("@io_bazel_rules_dotnet//dotnet/private:common.bzl", "env_execute")
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_context")
+load("@io_bazel_rules_dotnet//dotnet/private:rules/launcher_gen.bzl", "dotnet_launcher_gen")
+
+
+# _bazelrc is the bazel.rc file that sets the default options for tests
+_bazelrc = """
+build --verbose_failures
+build --sandbox_debug
+build --test_output=errors
+build --spawn_strategy=standalone
+build --genrule_strategy=standalone
+
+test --test_strategy=standalone
+test --nocache_test_results
+
+build:isolate --
+build:fetch --fetch=True
+"""
+
+# _env_build_template is the template for the bazel test environment repository build file
+_env_build_template = """
+load("@io_bazel_rules_dotnet//tests:bazel_tests.bzl", "bazel_test_settings")
+bazel_test_settings(
+ name = "settings",
+ bazel = "{bazel}",
+ exec_root = "{exec_root}",
+ scratch_dir = "{scratch_dir}",
+ visibility = ["//visibility:public"],
+)
+filegroup(
+ name = "bazelrc",
+ srcs = ["test.bazelrc"],
+ visibility = ["//visibility:public"],
+)
+"""
+
+# _bazel_test_script_template is the template for the bazel invocation script
+_bazel_test_script_template = """
+set -u
+
+echo pwd is `pwd`
+echo command is {command}
+echo running in {work_dir}
+unset TEST_TMPDIR
+RULES_DOTNET_OUTPUT={output}
+
+mkdir -p {work_dir}
+mkdir -p {cache_dir}
+../../{test_prep}
+cp -f {workspace} {work_dir}/WORKSPACE
+cp -f {build} {work_dir}/BUILD.bazel
+cd {work_dir}
+
+{bazel} --bazelrc {bazelrc} --nomaster_blazerc {command} --config {config} {args} {target} >& bazel-output.txt
+result=$?
+
+function at_exit {{
+ echo "bazel exited with status $result"
+ echo "----- bazel-output.txt begin -----"
+ cat bazel-output.txt
+ echo "----- bazel-output.txt end -----"
+ for log in {logs}; do
+ if [ ! -e "$log" ]; then
+ echo "----- $log not found -----"
+ else
+ echo "----- $log begin -----"
+ cat "$log"
+ echo "----- $log end -----"
+ fi
+ done
+}}
+trap at_exit EXIT
+
+{check}
+
+exit $result
+"""
+
+# _basic_workspace is the content appended to all test workspace files
+# it contains the calls required to make the dotnet rules work
+_basic_workspace = """
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_repositories", "dotnet_register_toolchains")
+dotnet_repositories()
+"""
+
+
+def _test_environment_impl(ctx):
+ # Find bazel
+ bazel = ""
+ if "BAZEL" in ctx.os.environ:
+ bazel = ctx.os.environ["BAZEL"]
+ elif "BAZEL_VERSION" in ctx.os.environ:
+ home = ctx.os.environ["HOME"]
+ bazel = home + "/.bazel/{0}/bin/bazel".format(ctx.os.environ["BAZEL_VERSION"])
+ if bazel == "" or not ctx.path(bazel).exists:
+ bazel = ctx.which("bazel")
+
+ # Get a temporary directory to use as our scratch workspace
+ if ctx.os.name.startswith('windows'):
+ scratch_dir = ctx.os.environ["TMP"].replace("\\","/") + "/bazel_go_test"
+ else:
+ result = env_execute(ctx, ["mktemp", "-d"])
+ if result.return_code:
+ fail("failed to create temporary directory for bazel tests: {}".format(result.stderr))
+ scratch_dir = result.stdout.strip()
+
+ # Work out where we are running so we can find externals
+ exec_root, _, _ = str(ctx.path(".")).rpartition("/external/")
+
+ # build the basic environment
+ ctx.file("WORKSPACE", 'workspace(name = "{}")'.format(ctx.name))
+ ctx.file("BUILD.bazel", _env_build_template.format(
+ bazel = bazel,
+ exec_root = exec_root,
+ scratch_dir = scratch_dir,
+ ))
+ ctx.file("test.bazelrc", content=_bazelrc)
+
+_test_environment = repository_rule(
+ implementation = _test_environment_impl,
+ attrs = {},
+ environ = [
+ "BAZEL",
+ "BAZEL_VERSION",
+ "HOME",
+ ],
+)
+
+def test_environment():
+ _test_environment(name="bazel_test")
+
+
+CURRENT_VERSION = "current"
+
+def _bazel_test_script_impl(ctx):
+ dotnet = dotnet_context(ctx)
+ script_file = dotnet.declare_file(dotnet, ext=".bash")
+
+ if not ctx.attr.targets:
+ # Skip test when there are no targets. Targets may be platform-specific,
+ # and we may not have any targets on some platforms.
+ ctx.actions.write(script_file, "", is_executable = True)
+ return [DefaultInfo(files = depset([script_file]))]
+
+ if ctx.attr.dotnet_version == CURRENT_VERSION:
+ register = 'dotnet_register_toolchains()\n'
+ elif ctx.attr.dotnet_version != None:
+ register = 'dotnet_register_toolchains(dotnet_version="{}")\n'.format(ctx.attr.dotnet_version)
+
+ workspace_content = 'workspace(name = "bazel_test")\n\n'
+ for ext in ctx.attr.externals:
+ root = ext.label.workspace_root
+ _,_,name = ext.label.workspace_root.rpartition("/")
+ workspace_content += 'local_repository(name="{name}", path="{exec_root}/{root}")\n'.format(
+ name = name,
+ root = root,
+ exec_root = ctx.attr._settings.exec_root,
+ )
+ if ctx.attr.workspace:
+ workspace_content += ctx.attr.workspace
+ else:
+ workspace_content += _basic_workspace.format()
+ workspace_content += register
+
+ workspace_file = dotnet.declare_file(dotnet, path="WORKSPACE.in")
+ ctx.actions.write(workspace_file, workspace_content)
+ build_file = dotnet.declare_file(dotnet, path="BUILD.in")
+ ctx.actions.write(build_file, ctx.attr.build)
+
+ output = "external/" + ctx.workspace_name + "/" + ctx.label.package
+ targets = ["@" + ctx.workspace_name + "//" + ctx.label.package + t if t.startswith(":") else t for t in ctx.attr.targets]
+ logs = []
+ if ctx.attr.command in ("test", "coverage"):
+ # TODO(jayconrod): read logs for other packages
+ logs = ["bazel-testlogs/{}/{}/test.log".format(output, t[1:])
+ for t in ctx.attr.targets if t.startswith(":")]
+
+ script_content = _bazel_test_script_template.format(
+ test_prep = ctx.attr.test_prep,
+ bazelrc = ctx.attr._settings.exec_root+"/"+ctx.file._bazelrc.path,
+ config = ctx.attr.config,
+ command = ctx.attr.command,
+ args = " ".join(ctx.attr.args),
+ target = " ".join(targets),
+ logs = " ".join(logs),
+ check = ctx.attr.check,
+ workspace = workspace_file.short_path,
+ build = build_file.short_path,
+ output = output,
+ bazel = ctx.attr._settings.bazel,
+ work_dir = ctx.attr._settings.scratch_dir + "/" + ctx.attr.config,
+ cache_dir = ctx.attr._settings.scratch_dir + "/cache",
+ )
+ ctx.actions.write(output=script_file, is_executable=True, content=script_content)
+ return struct(
+ files = depset([script_file]),
+ runfiles = ctx.runfiles([workspace_file, build_file], collect_data=True)
+ )
+
+_bazel_test_script = rule(
+ _bazel_test_script_impl,
+ attrs = {
+ "command": attr.string(
+ mandatory = True,
+ values = [
+ "build",
+ "test",
+ "coverage",
+ "run",
+ ],
+ ),
+ "args": attr.string_list(default = []),
+ "targets": attr.string_list(mandatory = True),
+ "externals": attr.label_list(allow_files = True),
+ "dotnet_version": attr.string(default = CURRENT_VERSION),
+ "workspace": attr.string(),
+ "build": attr.string(),
+ "check": attr.string(),
+ "test_prep": attr.string(),
+ "config": attr.string(default = "isolate"),
+ "data": attr.label_list(
+ allow_files = True,
+ cfg = "data",
+ ),
+ "_bazelrc": attr.label(
+ allow_files = True,
+ single_file = True,
+ default = "@bazel_test//:bazelrc",
+ ),
+ "_settings": attr.label(default = Label("@bazel_test//:settings")),
+ "_dotnet_context_data": attr.label(default = Label("@io_bazel_rules_dotnet//:dotnet_context_data")),
+ },
+ toolchains = ["@io_bazel_rules_dotnet//dotnet:toolchain"],
+)
+
+
+def bazel_test(name, command = None, args=None, targets = None, dotnet_version = None, tags=[], externals=[], workspace="", build="", check="", config=None):
+ script_name = name+"_script"
+ externals = externals + [
+ "@io_bazel_rules_dotnet//:AUTHORS",
+ ]
+ #if dotnet_version == None or dotnet_version == CURRENT_VERSION:
+ # externals.append("@go_sdk//:packages.txt")
+
+ _bazel_test_script(
+ name = script_name,
+ command = command,
+ args = args,
+ targets = targets,
+ externals = externals,
+ dotnet_version = dotnet_version,
+ workspace = workspace,
+ build = build,
+ check = check,
+ config = config,
+ test_prep = name + "_test_prep",
+ )
+
+ dotnet_launcher_gen(name = "%s_test_prep_gen" % name, exe = script_name)
+
+ native.cc_binary(
+ name=name + "_test_prep",
+ srcs = [":%s_test_prep_gen" % name],
+ deps = ["@io_bazel_rules_dotnet//dotnet/tools/test_prep", "@io_bazel_rules_dotnet//dotnet/tools/common"],
+ data = [script_name],
+ )
+ native.sh_test(
+ name = name,
+ size = "large",
+ timeout = "moderate",
+ srcs = [":" + script_name],
+ tags = ["local", "bazel", "exclusive"] + tags,
+ data = [
+ "@bazel_test//:bazelrc",
+ "@io_bazel_rules_dotnet//tests:rules_dotnet_deps",
+ ],
+ )
+
+def _bazel_test_settings_impl(ctx):
+ return struct(
+ bazel = ctx.attr.bazel,
+ exec_root = ctx.attr.exec_root,
+ scratch_dir = ctx.attr.scratch_dir,
+ )
+
+bazel_test_settings = rule(
+ _bazel_test_settings_impl,
+ attrs = {
+ "bazel": attr.string(mandatory = True),
+ "exec_root": attr.string(mandatory = True),
+ "scratch_dir": attr.string(mandatory = True),
+ },
+)
diff --git a/tests/core/README.rst b/tests/core/README.rst
new file mode 100644
index 00000000000000..87a2b8759f2164
--- /dev/null
+++ b/tests/core/README.rst
@@ -0,0 +1,15 @@
+Core dotnet rules tests
+=======================
+
+This contains tests of the core go rules.
+
+Contents
+--------
+
+.. Child list start
+
+* `Basic dotnet_binary functionality `_
+* `Basic dotnet_library functionality `_
+
+.. Child list end
+
diff --git a/tests/core/dotnet_binary/BUILD.bazel b/tests/core/dotnet_binary/BUILD.bazel
new file mode 100644
index 00000000000000..0d6f12a3452e1b
--- /dev/null
+++ b/tests/core/dotnet_binary/BUILD.bazel
@@ -0,0 +1,21 @@
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_binary", "dotnet_nunit_test")
+
+dotnet_binary(
+ name = "custom_bin",
+ srcs = [
+ "main.cs",
+ ],
+ out = "alt_bin.exe",
+)
+
+dotnet_nunit_test(
+ name = "custom_bin_test",
+ srcs = [
+ "main_test.cs",
+ ],
+ deps = [
+ "@nunit2//:nunit.framework",
+ ],
+ data = [":custom_bin"],
+ size = "small",
+)
diff --git a/tests/core/dotnet_binary/README.rst b/tests/core/dotnet_binary/README.rst
new file mode 100644
index 00000000000000..ac87581b21869f
--- /dev/null
+++ b/tests/core/dotnet_binary/README.rst
@@ -0,0 +1,11 @@
+Basic dotnet_binary functionality
+=================================
+
+.. _dotnet_binary: /dotnet/core.rst#_dotnet_binary
+
+Tests to ensure the basic features of dotnet_binary are working as expected.
+
+custom_bin
+----------
+
+Test that a dotnet_binary_ rule can write its executable file with a custom name.
diff --git a/tests/core/dotnet_binary/main.cs b/tests/core/dotnet_binary/main.cs
new file mode 100644
index 00000000000000..c80e1b8cea2b73
--- /dev/null
+++ b/tests/core/dotnet_binary/main.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace example_binary
+{
+ class MainClass
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Ok");
+ }
+ }
+}
diff --git a/tests/core/dotnet_binary/main_test.cs b/tests/core/dotnet_binary/main_test.cs
new file mode 100644
index 00000000000000..1fa0d11e3a2d45
--- /dev/null
+++ b/tests/core/dotnet_binary/main_test.cs
@@ -0,0 +1,17 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+namespace example_test
+{
+ [TestFixture]
+ public class MyTest
+ {
+ [Test]
+ public void MyTest2()
+ {
+ Assert.AreEqual(true, File.Exists("alt_bin.exe"));
+ }
+ }
+}
diff --git a/tests/core/dotnet_library/BUILD.bazel b/tests/core/dotnet_library/BUILD.bazel
new file mode 100644
index 00000000000000..fb67b90c00a383
--- /dev/null
+++ b/tests/core/dotnet_library/BUILD.bazel
@@ -0,0 +1,21 @@
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_library", "dotnet_nunit_test")
+
+dotnet_library(
+ name = "custom_bin",
+ srcs = [
+ "main.cs",
+ ],
+ out = "alt_bin.dll",
+)
+
+dotnet_nunit_test(
+ name = "custom_bin_test",
+ srcs = [
+ "main_test.cs",
+ ],
+ deps = [
+ "@nunit2//:nunit.framework",
+ ],
+ data = [":custom_bin"],
+ size = "small",
+)
diff --git a/tests/core/dotnet_library/README.rst b/tests/core/dotnet_library/README.rst
new file mode 100644
index 00000000000000..956d6856217234
--- /dev/null
+++ b/tests/core/dotnet_library/README.rst
@@ -0,0 +1,11 @@
+Basic dotnet_library functionality
+==================================
+
+.. _dotnet_library: /dotnet/core.rst#_dotnet_library
+
+Tests to ensure the basic features of dotnet_library are working as expected.
+
+custom_bin
+----------
+
+Test that a dotnet_library_ rule can write its assembly file with a custom name.
diff --git a/tests/core/dotnet_library/main.cs b/tests/core/dotnet_library/main.cs
new file mode 100644
index 00000000000000..973d61f65edb50
--- /dev/null
+++ b/tests/core/dotnet_library/main.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace example_library
+{
+ public class MainClass
+ {
+ public void Method()
+ {
+ Console.WriteLine("Ok");
+ }
+ }
+}
diff --git a/tests/core/dotnet_library/main_test.cs b/tests/core/dotnet_library/main_test.cs
new file mode 100644
index 00000000000000..d9b7f72d2ebc20
--- /dev/null
+++ b/tests/core/dotnet_library/main_test.cs
@@ -0,0 +1,17 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+namespace example_test
+{
+ [TestFixture]
+ public class MyTest
+ {
+ [Test]
+ public void MyTest2()
+ {
+ Assert.AreEqual(true, File.Exists("alt_bin.dll"));
+ }
+ }
+}
diff --git a/tests/core/download_sdk/BUILD.bazel b/tests/core/download_sdk/BUILD.bazel
new file mode 100644
index 00000000000000..7b26a155c5e464
--- /dev/null
+++ b/tests/core/download_sdk/BUILD.bazel
@@ -0,0 +1,20 @@
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_binary", "dotnet_nunit_test")
+load("@io_bazel_rules_dotnet//tests:bazel_tests.bzl", "bazel_test")
+
+dotnet_nunit_test(
+ name = "empty_test",
+ srcs = [
+ "main_test.cs",
+ ],
+ deps = [
+ "@nunit2//:nunit.framework",
+ ],
+ size = "small",
+)
+
+bazel_test(
+ name = "download_sdk_test",
+ command = "test",
+ dotnet_version = "host",
+ targets = [":empty_test"],
+)
diff --git a/tests/core/download_sdk/README.rst b/tests/core/download_sdk/README.rst
new file mode 100644
index 00000000000000..8ecabf0f0dc478
--- /dev/null
+++ b/tests/core/download_sdk/README.rst
@@ -0,0 +1,12 @@
+Download sdk functionality
+==========================
+
+.. _dotnet_register_toolchains: /dotnet/core.rst#_dotnet_register_toolchains
+
+Tests to ensure the basic features of dotnet_register_toolchains_ works downloading sdk (at the moment
+only on osx) .
+
+download_sdk_test
+-----------------
+
+Test that a dotnet_register_toolchains_ can download sdk.
diff --git a/tests/core/download_sdk/main.cs b/tests/core/download_sdk/main.cs
new file mode 100644
index 00000000000000..c80e1b8cea2b73
--- /dev/null
+++ b/tests/core/download_sdk/main.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace example_binary
+{
+ class MainClass
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Ok");
+ }
+ }
+}
diff --git a/tests/core/download_sdk/main_test.cs b/tests/core/download_sdk/main_test.cs
new file mode 100644
index 00000000000000..3e84c89bd41fae
--- /dev/null
+++ b/tests/core/download_sdk/main_test.cs
@@ -0,0 +1,16 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+namespace example_test
+{
+ [TestFixture]
+ public class MyTest
+ {
+ [Test]
+ public void MyTest2()
+ {
+ }
+ }
+}
diff --git a/tests/examples/example_binary/BUILD b/tests/examples/example_binary/BUILD
new file mode 100644
index 00000000000000..73a54100f38a6c
--- /dev/null
+++ b/tests/examples/example_binary/BUILD
@@ -0,0 +1,14 @@
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_binary")
+
+
+dotnet_binary(
+ name = "hello",
+ srcs = [
+ "Program.cs",
+ "Properties/AssemblyInfo.cs",
+ ],
+ deps = [
+ "//tests/examples/example_lib:MyClass",
+ "@npgsql//:npgsqllib",
+ ],
+)
diff --git a/examples/example_binary/Program.cs b/tests/examples/example_binary/Program.cs
similarity index 100%
rename from examples/example_binary/Program.cs
rename to tests/examples/example_binary/Program.cs
diff --git a/examples/example_binary/Properties/AssemblyInfo.cs b/tests/examples/example_binary/Properties/AssemblyInfo.cs
similarity index 100%
rename from examples/example_binary/Properties/AssemblyInfo.cs
rename to tests/examples/example_binary/Properties/AssemblyInfo.cs
diff --git a/tests/examples/example_lib/BUILD b/tests/examples/example_lib/BUILD
new file mode 100644
index 00000000000000..b42fbd98c75fae
--- /dev/null
+++ b/tests/examples/example_lib/BUILD
@@ -0,0 +1,14 @@
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_library")
+
+dotnet_library(
+ name = "MyClass",
+ srcs = [
+ "MyClass.cs",
+ "Properties/AssemblyInfo.cs",
+ ],
+ #resources = [ "hello.txt" ],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//tests/examples/example_transitive_lib:TransitiveClass",
+ ],
+)
diff --git a/examples/example_lib/MyClass.cs b/tests/examples/example_lib/MyClass.cs
similarity index 100%
rename from examples/example_lib/MyClass.cs
rename to tests/examples/example_lib/MyClass.cs
diff --git a/examples/example_lib/Properties/AssemblyInfo.cs b/tests/examples/example_lib/Properties/AssemblyInfo.cs
similarity index 100%
rename from examples/example_lib/Properties/AssemblyInfo.cs
rename to tests/examples/example_lib/Properties/AssemblyInfo.cs
diff --git a/examples/example_lib/hello.txt b/tests/examples/example_lib/hello.txt
similarity index 100%
rename from examples/example_lib/hello.txt
rename to tests/examples/example_lib/hello.txt
diff --git a/tests/examples/example_test/BUILD b/tests/examples/example_test/BUILD
new file mode 100644
index 00000000000000..17a89a959117ee
--- /dev/null
+++ b/tests/examples/example_test/BUILD
@@ -0,0 +1,13 @@
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_nunit_test")
+
+dotnet_nunit_test(
+ name = "example_test",
+ srcs = [
+ "MyTest.cs",
+ ],
+ deps = [
+ "//tests/examples/example_lib:MyClass",
+ "@nunit2//:nunit.framework",
+ ],
+ size = "small",
+)
diff --git a/examples/example_test/MyTest.cs b/tests/examples/example_test/MyTest.cs
similarity index 60%
rename from examples/example_test/MyTest.cs
rename to tests/examples/example_test/MyTest.cs
index d5d5d3e5c71879..c033261c21bb2f 100644
--- a/examples/example_test/MyTest.cs
+++ b/tests/examples/example_test/MyTest.cs
@@ -10,9 +10,10 @@ namespace example_test
public class MyTest
{
[Test]
+ [ExpectedException( typeof( ArgumentException ) )]
public void MyTest1()
{
- Assert.That("foo", Is.EqualTo("Foo"));
+ throw new ArgumentException();
}
[Test]
@@ -20,5 +21,10 @@ public void MyTest2()
{
Assert.That("bar", Is.EqualTo("bar"));
}
+ [Test]
+ public void MyTest3()
+ {
+ Assert.That(1, Is.EqualTo(1));
+ }
}
}
\ No newline at end of file
diff --git a/examples/example_tool/BUILD b/tests/examples/example_tool/BUILD
similarity index 79%
rename from examples/example_tool/BUILD
rename to tests/examples/example_tool/BUILD
index 1445aee3e4b892..5b459333082334 100644
--- a/examples/example_tool/BUILD
+++ b/tests/examples/example_tool/BUILD
@@ -1,12 +1,12 @@
-load("//dotnet:csharp.bzl", "csharp_binary")
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_binary")
-csharp_binary(
+dotnet_binary(
name = "hello_tool",
srcs = [
"MyTool.cs",
],
deps = [
- "//examples/example_lib:MyClass",
+ "//tests/examples/example_lib:MyClass",
],
)
diff --git a/examples/example_tool/MyTool.cs b/tests/examples/example_tool/MyTool.cs
similarity index 81%
rename from examples/example_tool/MyTool.cs
rename to tests/examples/example_tool/MyTool.cs
index 1cf8d5647f5391..4fdcd42bf7dcc3 100644
--- a/examples/example_tool/MyTool.cs
+++ b/tests/examples/example_tool/MyTool.cs
@@ -7,6 +7,7 @@ class MainClass
{
public static void Main(string[] args)
{
+ Console.WriteLine("Invoked");
if (args.Length == 0) {
Console.Error.WriteLine("No output files specified!");
Environment.Exit(1);
@@ -14,6 +15,7 @@ public static void Main(string[] args)
var mc = new MyClass();
foreach (string output_file in args) {
+ Console.WriteLine("Generating {0}", output_file);
System.IO.File.WriteAllText(output_file, mc.Message);
}
}
diff --git a/examples/example_transitive_lib/BUILD b/tests/examples/example_transitive_lib/BUILD
similarity index 66%
rename from examples/example_transitive_lib/BUILD
rename to tests/examples/example_transitive_lib/BUILD
index 6788294ce38e22..761ada3f90b9f6 100644
--- a/examples/example_transitive_lib/BUILD
+++ b/tests/examples/example_transitive_lib/BUILD
@@ -1,6 +1,6 @@
-load("//dotnet:csharp.bzl", "csharp_library")
+load("@io_bazel_rules_dotnet//dotnet:defs.bzl", "dotnet_library")
-csharp_library(
+dotnet_library(
name = "TransitiveClass",
srcs = [
"Properties/AssemblyInfo.cs",
diff --git a/examples/example_transitive_lib/Properties/AssemblyInfo.cs b/tests/examples/example_transitive_lib/Properties/AssemblyInfo.cs
similarity index 100%
rename from examples/example_transitive_lib/Properties/AssemblyInfo.cs
rename to tests/examples/example_transitive_lib/Properties/AssemblyInfo.cs
diff --git a/examples/example_transitive_lib/TransitiveClass.cs b/tests/examples/example_transitive_lib/TransitiveClass.cs
similarity index 100%
rename from examples/example_transitive_lib/TransitiveClass.cs
rename to tests/examples/example_transitive_lib/TransitiveClass.cs