blob: e18d74465538a57332ba0111d351127a95f8b2da [file] [log] [blame]
# 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.
load("@io_bazel_rules_rust//rust:private/rustc.bzl", "CrateInfo", "DepInfo", "add_crate_link_flags")
load("@io_bazel_rules_rust//rust:private/utils.bzl", "find_toolchain")
def _rust_doc_impl(ctx):
if CrateInfo not in ctx.attr.dep:
fail("Expected rust_library or rust_binary.", "dep")
crate = ctx.attr.dep[CrateInfo]
dep_info = ctx.attr.dep[DepInfo]
toolchain = find_toolchain(ctx)
rustdoc_inputs = (
crate.srcs +
[c.output for c in dep_info.transitive_crates] +
[toolchain.rust_doc] +
toolchain.rustc_lib +
toolchain.rust_lib
)
output_dir = ctx.actions.declare_directory(ctx.label.name)
args = ctx.actions.args()
args.add(crate.root.path)
args.add("--crate-name", crate.name)
args.add("--output", output_dir)
# nb. rustdoc can't do anything with native link flags; we must omit them.
add_crate_link_flags(args, dep_info)
args.add_all(ctx.files.markdown_css, before_each = "--markdown-css")
if ctx.file.html_in_header:
args.add("--html-in-header", ctx.file.html_in_header)
if ctx.file.html_before_content:
args.add("--html-before-content", ctx.file.html_before_content)
if ctx.file.html_after_content:
args.add("--html-after-content", ctx.file.html_after_content)
ctx.actions.run(
executable = toolchain.rust_doc,
inputs = rustdoc_inputs,
outputs = [output_dir],
arguments = [args],
mnemonic = "Rustdoc",
progress_message = "Generating rustdoc for {} ({} files)".format(crate.name, len(crate.srcs)),
)
# This rule does nothing without a single-file output, though the directory should've sufficed.
_zip_action(ctx, output_dir, ctx.outputs.rust_doc_zip)
def _zip_action(ctx, input_dir, output_zip):
args = ctx.actions.args()
# Create but not compress.
args.add("c", output_zip)
args.add_all([input_dir], expand_directories = True)
ctx.actions.run(
executable = ctx.executable._zipper,
inputs = [input_dir],
outputs = [output_zip],
arguments = [args],
)
rust_doc = rule(
_rust_doc_impl,
attrs = {
"dep": attr.label(mandatory = True),
"markdown_css": attr.label_list(allow_files = [".css"]),
"html_in_header": attr.label(allow_files = [".html", ".md"], single_file = True),
"html_before_content": attr.label(allow_files = [".html", ".md"], single_file = True),
"html_after_content": attr.label(allow_files = [".html", ".md"], single_file = True),
"_zipper": attr.label(default = Label("@bazel_tools//tools/zip:zipper"), cfg = "host", executable = True),
},
outputs = {
"rust_doc_zip": "%{name}.zip",
},
toolchains = ["@io_bazel_rules_rust//rust:toolchain"],
)
"""Generates code documentation.
Args:
name: A unique name for this rule.
dep: The label of the target to generate code documentation for.
`rust_doc` can generate HTML code documentation for the source files of
`rust_library` or `rust_binary` targets.
markdown_css: CSS files to include via `<link>` in a rendered
Markdown file.
html_in_header: File to add to `<head>`.
html_before_content: File to add in `<body>`, before content.
html_after_content: File to add in `<body>`, after content.
Example:
Suppose you have the following directory structure for a Rust library crate:
```
[workspace]/
WORKSPACE
hello_lib/
BUILD
src/
lib.rs
```
To build [`rustdoc`][rustdoc] documentation for the `hello_lib` crate, define
a `rust_doc` rule that depends on the the `hello_lib` `rust_library` target:
[rustdoc]: https://doc.rust-lang.org/book/documentation.html
```python
package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_rust//rust:rust.bzl", "rust_library", "rust_doc")
rust_library(
name = "hello_lib",
srcs = ["src/lib.rs"],
)
rust_doc(
name = "hello_lib_doc",
dep = ":hello_lib",
)
```
Running `bazel build //hello_lib:hello_lib_doc` will build a zip file containing
the documentation for the `hello_lib` library crate generated by `rustdoc`.
"""