blob: 947ebbae1555cbdfd396af3b513804d8de5a5f0c [file] [log] [blame]
# Copyright 2023 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("@bazel_skylib//rules:write_file.bzl", "write_file")
load("@dev_pip//:requirements.bzl", "requirement")
load("//python:py_binary.bzl", "py_binary")
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED") # buildifier: disable=bzl-visibility
load("//python/private:util.bzl", "IS_BAZEL_7_OR_HIGHER") # buildifier: disable=bzl-visibility
load("//sphinxdocs:readthedocs.bzl", "readthedocs_install")
load("//sphinxdocs:sphinx.bzl", "sphinx_build_binary", "sphinx_docs")
load("//sphinxdocs:sphinx_stardoc.bzl", "sphinx_stardocs")
# We only build for Linux and Mac because:
# 1. The actual doc process only runs on Linux
# 2. Mac is a common development platform, and is close enough to Linux
# it's feasible to make work.
# Making CI happy under Windows is too much of a headache, though, so we don't
# bother with that.
_TARGET_COMPATIBLE_WITH = select({
"@platforms//os:linux": [],
"@platforms//os:macos": [],
"//conditions:default": ["@platforms//:incompatible"],
}) if IS_BAZEL_7_OR_HIGHER else ["@platforms//:incompatible"]
# See README.md for instructions. Short version:
# * `bazel run //docs/sphinx:docs.serve` in a separate terminal
# * `ibazel build //docs/sphinx:docs` to automatically rebuild docs
sphinx_docs(
name = "docs",
srcs = [
":bzl_api_docs",
] + glob(
include = [
"*.md",
"**/*.md",
"_static/**",
"_includes/**",
],
exclude = [
"README.md",
"_*",
"*.inv*",
],
),
config = "conf.py",
formats = [
"html",
],
renamed_srcs = {
"//:CHANGELOG.md": "changelog.md",
"//:CONTRIBUTING.md": "contributing.md",
"//sphinxdocs/inventories:bazel_inventory": "bazel_inventory.inv",
},
sphinx = ":sphinx-build",
strip_prefix = package_name() + "/",
tags = ["docs"],
target_compatible_with = _TARGET_COMPATIBLE_WITH,
)
sphinx_stardocs(
name = "bzl_api_docs",
docs = {
"api/python/cc/py_cc_toolchain.md": dict(
dep = "//python/private:py_cc_toolchain_bzl",
input = "//python/private:py_cc_toolchain_rule.bzl",
public_load_path = "//python/cc:py_cc_toolchain.bzl",
),
"api/python/cc/py_cc_toolchain_info.md": "//python/cc:py_cc_toolchain_info_bzl",
"api/python/defs.md": "//python:defs_bzl",
"api/python/entry_points/py_console_script_binary.md": "//python/entry_points:py_console_script_binary_bzl",
"api/python/packaging.md": "//python:packaging_bzl",
"api/python/pip.md": "//python:pip_bzl",
"api/python/private/common/py_binary_rule_bazel.md": "//python/private/common:py_binary_rule_bazel_bzl",
"api/python/private/common/py_library_rule_bazel.md": "//python/private/common:py_library_rule_bazel_bzl",
"api/python/private/common/py_runtime_rule.md": "//python/private/common:py_runtime_rule_bzl",
"api/python/private/common/py_test_rule_bazel.md": "//python/private/common:py_test_rule_bazel_bzl",
"api/python/py_binary.md": "//python:py_binary_bzl",
"api/python/py_cc_link_params_info.md": "//python:py_cc_link_params_info_bzl",
"api/python/py_library.md": "//python:py_library_bzl",
"api/python/py_runtime.md": "//python:py_runtime_bzl",
"api/python/py_runtime_info.md": "//python:py_runtime_info_bzl",
"api/python/py_runtime_pair.md": dict(
dep = "//python/private:py_runtime_pair_rule_bzl",
input = "//python/private:py_runtime_pair_rule.bzl",
public_load_path = "//python:py_runtime_pair.bzl",
),
"api/python/py_test.md": "//python:py_test_bzl",
} | ({
# Bazel 6 + Stardoc isn't able to parse something about the python bzlmod extension
"api/python/extensions/python.md": "//python/extensions:python_bzl",
} if IS_BAZEL_7_OR_HIGHER else {}) | ({
# This depends on @pythons_hub, which is only created under bzlmod,
"api/python/extensions/pip.md": "//python/extensions:pip_bzl",
} if IS_BAZEL_7_OR_HIGHER and BZLMOD_ENABLED else {}),
tags = ["docs"],
target_compatible_with = _TARGET_COMPATIBLE_WITH,
)
readthedocs_install(
name = "readthedocs_install",
docs = [":docs"],
target_compatible_with = _TARGET_COMPATIBLE_WITH,
)
sphinx_build_binary(
name = "sphinx-build",
target_compatible_with = _TARGET_COMPATIBLE_WITH,
deps = [
requirement("sphinx"),
requirement("sphinx_rtd_theme"),
requirement("myst_parser"),
requirement("readthedocs_sphinx_ext"),
requirement("typing_extensions"),
"//sphinxdocs/src/sphinx_bzl",
],
)
_REQUIREMENTS_TARGET_COMPATIBLE_WITH = select({
"@platforms//os:linux": [],
"@platforms//os:macos": [],
"@platforms//os:windows": [],
"//conditions:default": ["@platforms//:incompatible"],
}) if BZLMOD_ENABLED else ["@platforms//:incompatible"]
# Run bazel run //docs/sphinx:requirements.update
genrule(
name = "requirements",
srcs = ["pyproject.toml"],
outs = ["_requirements.txt"],
cmd = "$(UV_BIN) pip compile " + " ".join([
"--custom-compile-command='bazel run //docs/sphinx:requirements.update'",
"--generate-hashes",
"--universal",
"--emit-index-url",
"--no-strip-extras",
"--no-build",
"--python=$(PYTHON3)",
"$<",
"--output-file=$@",
# Always try upgrading
"--upgrade",
]),
tags = [
"local",
"manual",
"no-cache",
],
target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
toolchains = [
"//python/uv:current_toolchain",
"//python:current_py_toolchain",
],
)
# Write a script that can be used for updating the in-tree version of the
# requirements file
write_file(
name = "gen_update_requirements",
out = "requirements.update.py",
content = [
"from os import environ",
"from pathlib import Path",
"from sys import stderr",
"",
'src = Path(environ["REQUIREMENTS_FILE"])',
'dst = Path(environ["BUILD_WORKSPACE_DIRECTORY"]) / "docs" / "sphinx" / "requirements.txt"',
'print(f"Writing requirements contents from {src} to {dst}", file=stderr)',
"dst.write_text(src.read_text())",
'print("Success!", file=stderr)',
],
target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
)
py_binary(
name = "requirements.update",
srcs = ["requirements.update.py"],
data = [":requirements"],
env = {
"REQUIREMENTS_FILE": "$(location :requirements)",
},
tags = ["manual"],
target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
)