Skip to content

Commit

Permalink
Adds new_nuget_package (bazelbuild#27)
Browse files Browse the repository at this point in the history
* - Adds new_http_archive for nuget-binary from github commit zipfile.
- Adds label attributes to nuget_package rule to get mono and nuget binary paths.
- Checks return value of execute nuget_cmd and fails with non-zero value.
- Changes dll_import rule in nuget_package BUILD from
  `@workspace_name//:workspace_name` to `@workspace_name//:dylibs`
  (less redundant, more descriptive).
- Bumps README.md to 0.0.3.

* - Adds new_nuget_package as workaround for Issue bazelbuild#18.
- csharp_binary fixes for path outputs. Closes bazelbuild#26.

* Reverts attr dict addition to maintain syntax conformance with python.

* Documentation for new_nuget_package.
  • Loading branch information
pcj authored and zaphar committed Sep 29, 2016
1 parent 28edd42 commit f8950cb
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 47 deletions.
49 changes: 42 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

## 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)

__WARNING:__ Theses rules are not compatible with
Expand All @@ -28,7 +28,7 @@ Add the following to your `WORKSPACE` file to add the external repositories:
git_repository(
name = "io_bazel_rules_dotnet",
remote = "https://github.com/bazelbuild/rules_dotnet.git",
tag = "0.0.1",
tag = "0.0.3",
)

load(
Expand All @@ -46,10 +46,11 @@ nuget_package(
)
```

The `csharp_repositories` rule fetches external dependencies, namely the NUnit
binaries and the mono repository. Setting `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
The `csharp_repositories` rule fetches external dependencies, namely
the mono repository, the nuget binary, and the nunit binary. Setting
`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
Expand Down Expand Up @@ -93,12 +94,46 @@ file.

```python
nuget_package(
name="ndesk_options", # referenced via path @ndesk_options//:ndesk_options
name="ndesk_options", # referenced via path @ndesk_options//:dylibs
package="NDesk.Options",
version="0.2.1",
)
```

### 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.
Expand Down
4 changes: 2 additions & 2 deletions dotnet/NUGET_BUILD.tpl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
load("@io_bazel_rules_dotnet//dotnet:csharp.bzl", "dll_import")

dll_import(
name = "%{package}",
name = "dylibs",
srcs = glob(["**/*.dll"]),
visibility = ["//visibility:public"],
)
)
131 changes: 93 additions & 38 deletions dotnet/csharp.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,20 @@ def _make_nunit_launcher(ctx, depinfo, output):
_LAUNCHER_SCRIPT = """\
#!/bin/bash
set -e
if [[ -e "$0.runfiles" ]]; then
cd $0.runfiles/{workspace}
fi
# TODO(jeremy): This is a gross and fragile hack.
# We should be able to do better than this.
ln -s -f {workspace}/{exe} $(basename {exe})
ln -s -f {exe} $(basename {exe})
for l in {libs}; do
ln -s -f {workspace}/$l $(basename {workspace}/$l)
ln -s -f $l $(basename {workspace}/$l)
done
{workspace}/{mono_exe} $(basename {exe}) "$@"
{mono_exe} $(basename {exe}) "$@"
"""

def _make_launcher(ctx, depinfo, output):
Expand Down Expand Up @@ -412,14 +414,21 @@ dll_import = rule(
attrs = _NUGET_ATTRS,
)

def _nuget_package_impl(repository_ctx):
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 = [
repository_ctx.attr.nuget_bin_path,
mono,
"--config", "%s/../etc/mono/config" % mono.dirname,
nuget,
"install",
"-Version", repository_ctx.attr.version,
"-OutputDirectory", output_dir,
Expand All @@ -431,48 +440,80 @@ def _nuget_package_impl(repository_ctx):
# Lastly we add the nuget package name.
nuget_cmd += [repository_ctx.attr.package]
# execute nuget download.
repository_ctx.execute(nuget_cmd)
# TODO(jeremy): report errors if there were any

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})

# This rule is a repository rule and is only usable in WORKSPACE files.
# due to some limitations of repository_rules it does require you to
# tell it where your nuget.exe is located. You may want to manage that binary
# in your repository as a result.
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"),
),
# Reference to the nuget.exe file
"nuget_exe":attr.label(
default=Label("@nuget//:nuget.exe"),
),
}

nuget_package = repository_rule(
implementation=_nuget_package_impl,
#local=False,
attrs={
# TODO(jeremy): use repository_ctx.which("mono") in the impl?
"mono_bin_path":attr.string(default=_MONO_UNIX_BIN),
# Location of the nuget exe
"nuget_bin_path":attr.string(default="/usr/local/bin/nuget"),
# 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),
# content of the BUILD file for this external resource.
})
attrs=_nuget_package_attrs,
)
"""Fetches a nuget package as an external dependency.
This rule is a repository rule and is only usable in WORKSPACE files.
due to some current limitations of repository_rules it does require you to
tell it where your nuget.exe is located. You may want to manage that binary
in your repository as a result.
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=_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(
Expand Down Expand Up @@ -520,6 +561,7 @@ mono_package = repository_rule(

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",
Expand All @@ -529,4 +571,17 @@ def csharp_repositories(use_local_mono=False):
# 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)

0 comments on commit f8950cb

Please sign in to comment.