diff --git a/core/BUILD.bazel b/core/BUILD.bazel index 4c79e613..67675cb4 100644 --- a/core/BUILD.bazel +++ b/core/BUILD.bazel @@ -1,4 +1,3 @@ -load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("//docs:stardoc.bzl", "generate") package(default_visibility = ["//visibility:public"]) @@ -9,47 +8,16 @@ filegroup( visibility = ["//visibility:public"], ) -# boilerplate for `bazel_tools` -bzl_library( - name = "bazel_tools", - srcs = [ - "@bazel_tools//tools:bzl_srcs", - ], -) - -# define Bazel library and its dependencies for generating documentation. considered -# in isolation we could immediately use -# -# generate(deps = [":srcs", ], ...) -# -# but toolchain modules that import definitions from here require a target to -# declare as their dependency for their own documentation rendering. same for -# legacy documentation. one could possibly extract this highly repetitive -# pattern into `generate()` itself, and capture its `deps=` attribute to -# automatically create these Bazel library targets. this approach may become -# meaningful once we want to generate legacy documentation for all the toolchains -# at once, as those toolchains will also have to export their Bazel libraries -# to make that convenient. -bzl_library( - name = "nixpkgs", - srcs = [ +generate( + name = "README.md", + inputs = [ "nixpkgs.bzl", "util.bzl", ], - visibility = ["//visibility:public"], - deps = [ - ":bazel_tools", - "@bazel_skylib//lib:paths", - ], -) - -generate( - name = "README.md", - input = "//:nixpkgs.bzl", symbol_names = [ "nixpkgs_git_repository", "nixpkgs_local_repository", "nixpkgs_package", ], - deps = ["//:nixpkgs"], + deps = ["@bazel_skylib//lib:paths"], ) diff --git a/core/docs/stardoc.bzl b/core/docs/stardoc.bzl index 2b5e07d5..f12f1194 100644 --- a/core/docs/stardoc.bzl +++ b/core/docs/stardoc.bzl @@ -1,15 +1,64 @@ +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("@io_bazel_stardoc//stardoc:stardoc.bzl", _stardoc = "stardoc") def generate( name, - input, + inputs, error_message = None, + deps = [], **kwargs): """ - create rules for generating documentation, copying a file into the source - tree containing it, and testing that the copying has actually happened - (since the copy rule must be run manually). + full-service documentation rendering + + - make a Bazel library from `inputs` + - create rules for + - generating library documentation + - copying a file into the source tree containing it + - testing that the copying has actually happened + (since the copy rule must be run manually) + + NOTE: library name is derived from first file in `inputs`, without extensions. + + Args: + name: target file name for rendered documentation. + inputs: file names for Bazel library and documentation + error_message: custom error message to print if rendered documentation is not up to date. + deps: library dependencies of the `inputs` provided. + **kwargs: arguments for `stardoc`, most notably `symbol_names` to generate documentation for. """ + + # necessary boilerplate: to build a Bazel library, we always need to include + # `bazel_tools` as a dependency. + # since we will combine toolchain libraries with the core library, but only + # need `bazel_tools` dependency once, only create if not already there. + if not native.existing_rule("bazel_tools"): + bzl_library( + name = "bazel_tools", + srcs = [ + "@bazel_tools//tools:bzl_srcs", + ], + ) + + # massage first input file name into nice rule name + lib = Label(absolute_label(inputs[0])).name.split(".")[0] + bzl_library( + name = lib, + srcs = inputs, + visibility = ["//visibility:public"], + deps = [":bazel_tools"] + deps, + ) + + # generate documentation into transient file + out = "_{}".format(name) + stardoc("__{}".format(name), out, inputs[0], deps = [lib], **kwargs) + + # create rule to copy documentation into source tree + # has to be run manually! set up a commit hook for convenience? + copy_files( + name = "update-{}".format(name), + data = [(out, name)], + ) + if not error_message: error_message = [ "{} is not up to date.", @@ -18,15 +67,12 @@ def generate( "bazel run //{}:update-{}", ] error_message = "\n".join(error_message).format(name, native.package_name(), name) - out = "_{}".format(name) - stardoc("__{}".format(name), out, input, **kwargs) - copy_files( - name = "update-{}".format(name), - data = [(out, name)], - ) + + # create test that source tree is up to date with rendered documentation compare_files( name = "check-{}".format(name), - data = [(out, name)], + # expect target file at top level of current workspace, see `copy_files` + data = [(out, to_root(name))], error_message = error_message, ) @@ -77,3 +123,14 @@ def compare_files(name, data, error_message = ""): data = data, env = {"errormsg": error_message}, ) + +def to_root(label): + return "//:" + Label(absolute_label(label)).name + +def absolute_label(label): + # adapted from https://stackoverflow.com/a/66705640/18406610 + if label.startswith("@") or label.startswith("/"): + return label + if label.startswith(":"): + return native.repository_name() + "//" + native.package_name() + label + return native.repository_name() + "//" + native.package_name() + ":" + label diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index f324bcf1..94c6d5ef 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -1,9 +1,8 @@ -load("@rules_nixpkgs_core//docs:stardoc.bzl", "compare_files", "copy_files", "stardoc") +load("@rules_nixpkgs_core//docs:stardoc.bzl", "generate") -stardoc( - name = "nixpkgs", - out = "nixpkgs.md", - input = "//nixpkgs:nixpkgs.bzl", +generate( + name = "README.md", + inputs = ["//nixpkgs:nixpkgs.bzl"], symbol_names = [ "nixpkgs_git_repository", "nixpkgs_local_repository", @@ -12,102 +11,31 @@ stardoc( "nixpkgs_cc_configure_deprecated", "nixpkgs_java_configure", "nixpkgs_python_configure", - "nixpkgs_sh_posix_configure", - ], - deps = ["//nixpkgs"], -) - -stardoc( - name = "core", - out = "core.md", - input = "@rules_nixpkgs_core//:nixpkgs.bzl", - symbol_names = [ - "nixpkgs_git_repository", - "nixpkgs_local_repository", - "nixpkgs_package", - ], - deps = ["@rules_nixpkgs_core//:nixpkgs"], -) - -stardoc( - name = "go", - out = "toolchains/go.md", - input = "//nixpkgs:toolchains/go.bzl", - symbol_names = [ + "nixpkgs_rust_configure", "nixpkgs_go_configure", + "nixpkgs_sh_posix_configure", ], - deps = ["//nixpkgs:toolchains_go"], -) - -genrule( - name = "readme", - srcs = [ - "README.md.tpl", - "nixpkgs.md", - "toolchains/go.md", + deps = [ + "@bazel_skylib//lib:new_sets", + "@bazel_skylib//lib:paths", + "@bazel_skylib//lib:sets", + "@bazel_skylib//lib:versions", + "@rules_nixpkgs_cc//:cc", + "@rules_nixpkgs_core//:nixpkgs", + "@rules_nixpkgs_go//:go", + "@rules_nixpkgs_java//:java", + "@rules_nixpkgs_posix//:posix", + "@rules_nixpkgs_python//:python", + "@rules_nixpkgs_rust//:rust", ], - outs = ["README.md"], - cmd = """$(POSIX_AWK) \\ - <$(execpath README.md.tpl) \\ - >$(OUTS) \\ - '{ - if (/{{nixpkgs}}/) { - RS="\\0"; - getline content <"$(execpath nixpkgs.md)"; - print content; - RS="\\n"; - } else if (/{{toolchains_go}}/) { - RS="\\0"; - getline content <"$(execpath toolchains/go.md)"; - print content; - RS="\\n"; - } else { - print - } - }' -""", - toolchains = ["@rules_sh//sh/posix:make_variables"], ) -genrule( - name = "readme_core", - srcs = [ - "README_core.md.tpl", - "core.md", - ], - outs = ["core/README.md"], - cmd = """$(POSIX_AWK) \\ - <$(execpath README_core.md.tpl) \\ - >$(OUTS) \\ - '{ - if (/{{core}}/) { - RS="\\0"; - getline content <"$(execpath core.md)"; - print content; - RS="\\n"; - } else { - print - } - }' -""", - toolchains = ["@rules_sh//sh/posix:make_variables"], +alias( + name = "update-readme", + actual = "update-README.md", ) -compare_files( +alias( name = "check-readme", - data = [ - ("README.md", "//:README.md"), - ("core/README.md", "@rules_nixpkgs_core//:README.md"), - ], - error_message = """ - The project README is not up-to-date. - Please update it using the following command. - - bazel run //docs:update-readme - """, -) - -copy_files( - name = "update-readme", - data = [("README.md", "core/README.md")], + actual = "check-README.md", ) diff --git a/docs/README.md.tpl b/docs/README.md.tpl deleted file mode 100644 index 997f78b6..00000000 --- a/docs/README.md.tpl +++ /dev/null @@ -1,111 +0,0 @@ - - -# Nixpkgs rules for Bazel - -[![Build status](https://badge.buildkite.com/79bd0a8aa1e47a92e0254ca3afe5f439776e6d389cfbde9d8c.svg?branch=master)](https://buildkite.com/tweag-1/rules-nixpkgs) - -Use [Nix][nix] and the [Nixpkgs][nixpkgs] package set to import -external dependencies (like system packages) into [Bazel][bazel] -hermetically. If the version of any dependency changes, Bazel will -correctly rebuild targets, and only those targets that use the -external dependencies that changed. - -Links: -* [Nix + Bazel = fully reproducible, incremental - builds][blog-bazel-nix] (blog post) -* [Nix + Bazel][youtube-bazel-nix] (lightning talk) - -[nix]: https://nixos.org/nix -[nixpkgs]: https://github.com/NixOS/nixpkgs -[bazel]: https://bazel.build -[blog-bazel-nix]: https://www.tweag.io/posts/2018-03-15-bazel-nix.html -[youtube-bazel-nix]: https://www.youtube.com/watch?v=hDdDUrty1Gw - -## Rules - -* [nixpkgs_git_repository](#nixpkgs_git_repository) -* [nixpkgs_local_repository](#nixpkgs_local_repository) -* [nixpkgs_package](#nixpkgs_package) -* [nixpkgs_cc_configure](#nixpkgs_cc_configure) -* [nixpkgs_cc_configure_deprecated](#nixpkgs_cc_configure_deprecated) -* [nixpkgs_java_configure](#nixpkgs_java_configure) -* [nixpkgs_python_configure](#nixpkgs_python_configure) -* [nixpkgs_sh_posix_configure](#nixpkgs_sh_posix_configure) -* [nixpkgs_go_configure](#nixpkgs_go_configure) - -## Setup - -Add the following to your `WORKSPACE` file, and select a `$COMMIT` accordingly. - -```bzl -http_archive( - name = "io_tweag_rules_nixpkgs", - strip_prefix = "rules_nixpkgs-$COMMIT", - urls = ["https://github.com/tweag/rules_nixpkgs/archive/$COMMIT.tar.gz"], -) - -load("@io_tweag_rules_nixpkgs//nixpkgs:repositories.bzl", "rules_nixpkgs_dependencies") -rules_nixpkgs_dependencies() - -load("@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl", "nixpkgs_git_repository", "nixpkgs_package", "nixpkgs_cc_configure") - -load("@io_tweag_rules_nixpkgs//nixpkgs:toolchains/go.bzl", "nixpkgs_go_configure") # optional -``` - -If you use `rules_nixpkgs` to configure a toolchain, then you will also need to -configure the build platform to include the -`@io_tweag_rules_nixpkgs//nixpkgs/constraints:support_nix` constraint. For -example by adding the following to `.bazelrc`: - -``` -build --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host -``` - -## Example - -```bzl -nixpkgs_git_repository( - name = "nixpkgs", - revision = "17.09", # Any tag or commit hash - sha256 = "" # optional sha to verify package integrity! -) - -nixpkgs_package( - name = "hello", - repositories = { "nixpkgs": "@nixpkgs//:default.nix" } -) -``` - -## Rules - -{{nixpkgs}} - -{{toolchains_go}} - -## Migration from older releases - -### `path` Attribute (removed in 0.3) - -`path` was an attribute from the early days of `rules_nixpkgs`, and -its ability to reference arbitrary paths is a danger to build hermeticity. - -Replace it with either `nixpkgs_git_repository` if you need -a specific version of `nixpkgs`. If you absolutely *must* depend on a -local folder, use Bazel’s -[`local_repository` workspace rule](https://docs.bazel.build/versions/master/be/workspace.html#local_repository). -Both approaches work well with the `repositories` attribute of `nixpkgs_package`. - -```bzl -local_repository( - name = "local-nixpkgs", - path = "/path/to/nixpkgs", -) - -nixpkgs_package( - name = "somepackage", - repositories = { - "nixpkgs": "@local-nixpkgs//:default.nix", - }, - … -) -``` diff --git a/docs/README_core.md.tpl b/docs/README_core.md.tpl deleted file mode 100644 index 6b322bd4..00000000 --- a/docs/README_core.md.tpl +++ /dev/null @@ -1,5 +0,0 @@ -# Nixpkgs for Bazel - -## Rules - -{{core}} \ No newline at end of file diff --git a/nixpkgs/BUILD.bazel b/nixpkgs/BUILD.bazel index 5b8d9d46..8d13f304 100644 --- a/nixpkgs/BUILD.bazel +++ b/nixpkgs/BUILD.bazel @@ -1,70 +1,7 @@ -load("@bazel_skylib//:bzl_library.bzl", "bzl_library") - package(default_visibility = ["//visibility:public"]) -exports_files([ - "nixpkgs.bzl", -]) - filegroup( name = "srcs", srcs = glob(["**"]), visibility = ["//visibility:public"], ) - -# @bazel_tools//tools does not define a bzl_library itself, instead we are -# supposed to define our own using the @bazel_tools//tools:bzl_srcs filegroup. -# See https://github.com/bazelbuild/skydoc/issues/166 -bzl_library( - name = "bazel_tools", - srcs = [ - "@bazel_tools//tools:bzl_srcs", - ], -) - -bzl_library( - name = "repositories", - srcs = [ - "repositories.bzl", - ], - visibility = ["//visibility:public"], - deps = [ - ":bazel_tools", - ], -) - -bzl_library( - name = "nixpkgs", - srcs = [ - "nixpkgs.bzl", - ], - visibility = ["//visibility:public"], - deps = [ - ":bazel_tools", - "@bazel_skylib//lib:new_sets", - "@bazel_skylib//lib:paths", - "@bazel_skylib//lib:sets", - "@bazel_skylib//lib:versions", - "@rules_nixpkgs_cc//:cc.bzl", - "@rules_nixpkgs_core//:nixpkgs", - "@rules_nixpkgs_go//:go.bzl", - "@rules_nixpkgs_java//:java.bzl", - "@rules_nixpkgs_posix//:posix.bzl", - "@rules_nixpkgs_python//:python.bzl", - "@rules_nixpkgs_rust//:rust.bzl", - ], -) - -bzl_library( - name = "toolchains_go", - srcs = [ - "toolchains/go.bzl", - ], - visibility = ["//visibility:public"], - deps = [ - ":bazel_tools", - ":nixpkgs", - "@io_bazel_rules_go//go:deps", - "@rules_nixpkgs_go//:go.bzl", - ], -) diff --git a/nixpkgs/nixpkgs.bzl b/nixpkgs/nixpkgs.bzl index e66c60e8..7222f875 100644 --- a/nixpkgs/nixpkgs.bzl +++ b/nixpkgs/nixpkgs.bzl @@ -1,4 +1,109 @@ -"""Rules for importing Nixpkgs packages.""" +""" + +# Nixpkgs rules for Bazel + +[![Build status](https://badge.buildkite.com/79bd0a8aa1e47a92e0254ca3afe5f439776e6d389cfbde9d8c.svg?branch=master)](https://buildkite.com/tweag-1/rules-nixpkgs) + +Use [Nix][nix] and the [Nixpkgs][nixpkgs] package set to import +external dependencies (like system packages) into [Bazel][bazel] +hermetically. If the version of any dependency changes, Bazel will +correctly rebuild targets, and only those targets that use the +external dependencies that changed. + +Links: +* [Nix + Bazel = fully reproducible, incremental + builds][blog-bazel-nix] (blog post) +* [Nix + Bazel][youtube-bazel-nix] (lightning talk) + +[nix]: https://nixos.org/nix +[nixpkgs]: https://github.com/NixOS/nixpkgs +[bazel]: https://bazel.build +[blog-bazel-nix]: https://www.tweag.io/posts/2018-03-15-bazel-nix.html +[youtube-bazel-nix]: https://www.youtube.com/watch?v=hDdDUrty1Gw + +## Rules + +* [nixpkgs_git_repository](#nixpkgs_git_repository) +* [nixpkgs_local_repository](#nixpkgs_local_repository) +* [nixpkgs_package](#nixpkgs_package) +* [nixpkgs_cc_configure](#nixpkgs_cc_configure) +* [nixpkgs_cc_configure_deprecated](#nixpkgs_cc_configure_deprecated) +* [nixpkgs_java_configure](#nixpkgs_java_configure) +* [nixpkgs_python_configure](#nixpkgs_python_configure) +* [nixpkgs_go_configure](#nixpkgs_go_configure) +* [nixpkgs_rust_configure](#nixpkgs_rust_configure) +* [nixpkgs_sh_posix_configure](#nixpkgs_sh_posix_configure) + +## Setup + +Add the following to your `WORKSPACE` file, and select a `$COMMIT` accordingly. + +```bzl +http_archive( + name = "io_tweag_rules_nixpkgs", + strip_prefix = "rules_nixpkgs-$COMMIT", + urls = ["https://github.com/tweag/rules_nixpkgs/archive/$COMMIT.tar.gz"], +) + +load("@io_tweag_rules_nixpkgs//nixpkgs:repositories.bzl", "rules_nixpkgs_dependencies") +rules_nixpkgs_dependencies() + +load("@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl", "nixpkgs_git_repository", "nixpkgs_package", "nixpkgs_cc_configure") + +load("@io_tweag_rules_nixpkgs//nixpkgs:toolchains/go.bzl", "nixpkgs_go_configure") # optional +``` + +If you use `rules_nixpkgs` to configure a toolchain, then you will also need to +configure the build platform to include the +`@io_tweag_rules_nixpkgs//nixpkgs/constraints:support_nix` constraint. For +example by adding the following to `.bazelrc`: + +``` +build --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host +``` + +## Example + +```bzl +nixpkgs_git_repository( + name = "nixpkgs", + revision = "17.09", # Any tag or commit hash + sha256 = "" # optional sha to verify package integrity! +) + +nixpkgs_package( + name = "hello", + repositories = { "nixpkgs": "@nixpkgs//:default.nix" } +) +``` + +## Migration from older releases + +### `path` Attribute (removed in 0.3) + +`path` was an attribute from the early days of `rules_nixpkgs`, and +its ability to reference arbitrary paths is a danger to build hermeticity. + +Replace it with either `nixpkgs_git_repository` if you need +a specific version of `nixpkgs`. If you absolutely *must* depend on a +local folder, use Bazel's +[`local_repository` workspace rule](https://docs.bazel.build/versions/master/be/workspace.html#local_repository). +Both approaches work well with the `repositories` attribute of `nixpkgs_package`. + +```bzl +local_repository( + name = "local-nixpkgs", + path = "/path/to/nixpkgs", +) + +nixpkgs_package( + name = "somepackage", + repositories = { + "nixpkgs": "@local-nixpkgs//:default.nix", + }, +) +``` +""" load( "@bazel_tools//tools/cpp:lib_cc_configure.bzl", diff --git a/toolchains/cc/BUILD.bazel b/toolchains/cc/BUILD.bazel index 5a979d5b..e9c3dea2 100644 --- a/toolchains/cc/BUILD.bazel +++ b/toolchains/cc/BUILD.bazel @@ -10,7 +10,7 @@ filegroup( generate( name = "README.md", - input = "//:cc.bzl", + inputs = ["//:cc.bzl"], symbol_names = [ "nixpkgs_cc_configure", ], diff --git a/toolchains/go/BUILD.bazel b/toolchains/go/BUILD.bazel index 2d51bbfc..808c6bb5 100644 --- a/toolchains/go/BUILD.bazel +++ b/toolchains/go/BUILD.bazel @@ -10,7 +10,7 @@ filegroup( generate( name = "README.md", - input = "//:go.bzl", + inputs = ["//:go.bzl"], symbol_names = [ "nixpkgs_go_configure", ], diff --git a/toolchains/java/BUILD.bazel b/toolchains/java/BUILD.bazel index c10f0cff..0ce62268 100644 --- a/toolchains/java/BUILD.bazel +++ b/toolchains/java/BUILD.bazel @@ -10,7 +10,7 @@ filegroup( generate( name = "README.md", - input = "//:java.bzl", + inputs = ["//:java.bzl"], symbol_names = [ "nixpkgs_java_configure", ], diff --git a/toolchains/posix/BUILD.bazel b/toolchains/posix/BUILD.bazel index ff004659..29652c99 100644 --- a/toolchains/posix/BUILD.bazel +++ b/toolchains/posix/BUILD.bazel @@ -10,7 +10,7 @@ filegroup( generate( name = "README.md", - input = "//:posix.bzl", + inputs = ["//:posix.bzl"], symbol_names = [ "nixpkgs_sh_posix_configure", ], diff --git a/toolchains/python/BUILD.bazel b/toolchains/python/BUILD.bazel index b8a67011..9721e335 100644 --- a/toolchains/python/BUILD.bazel +++ b/toolchains/python/BUILD.bazel @@ -10,7 +10,7 @@ filegroup( generate( name = "README.md", - input = "//:python.bzl", + inputs = ["//:python.bzl"], symbol_names = [ "nixpkgs_python_configure", ], diff --git a/toolchains/rust/BUILD.bazel b/toolchains/rust/BUILD.bazel index 51f93643..350f9248 100644 --- a/toolchains/rust/BUILD.bazel +++ b/toolchains/rust/BUILD.bazel @@ -10,7 +10,7 @@ filegroup( generate( name = "README.md", - input = "//:rust.bzl", + inputs = ["//:rust.bzl"], symbol_names = [ "nixpkgs_rust_configure", ],