Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ cc_binary(
"src/Main.cc",
],
copts = OPENROAD_COPTS,
data = [
"//docs:man_pages",
],
features = ["-use_header_modules"],
malloc = select({
"@platforms//os:linux": "@tcmalloc//tcmalloc",
Expand Down
79 changes: 79 additions & 0 deletions bazel/man_pages.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2026, The OpenROAD Authors

"""Bazel rule to generate man pages (cat/ and html/) from module READMEs.

Runs the existing docs Makefile to produce cat/ and html/ outputs.
Requires pandoc, nroff, and python3 (>= 3.10) on the system.
"""

def _man_pages_impl(ctx):
cat_dir = ctx.actions.declare_directory("cat")
html_dir = ctx.actions.declare_directory("html")

command = """
set -euo pipefail

# Ensure homebrew tools (pandoc, python3 >= 3.10) are available on macOS
if [ -d /opt/homebrew/bin ]; then
export PATH="/opt/homebrew/bin:$PATH"
elif [ -d /usr/local/bin ]; then
export PATH="/usr/local/bin:$PATH"
fi

cd docs

# Symlink module READMEs into md/man2/
bash src/scripts/link_readmes.sh 2>/dev/null || true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Masking errors with || true and redirecting stderr to /dev/null can lead to silent failures during the documentation generation process. If the script fails, the resulting man pages might be incomplete or incorrect. It is better to allow the script to fail the build so that issues can be identified and fixed.

Suggested change
bash src/scripts/link_readmes.sh 2>/dev/null || true
bash src/scripts/link_readmes.sh


# Run preprocessing
python3 src/scripts/md_roff_compat.py

# Generate cat and html pages via Makefile
make -f Makefile cat web

cd ..

# Copy outputs to declared Bazel directories
cp -r docs/cat/* {cat_out}/
cp -r docs/html/* {html_out}/
Comment on lines +38 to +39
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using the * glob in the cp command will cause the shell to fail if the source directory is empty (which might happen if the make command fails to produce output but doesn't return a non-zero exit code). Using . is a more robust way to copy the contents of the directory.

Suggested change
cp -r docs/cat/* {cat_out}/
cp -r docs/html/* {html_out}/
cp -r docs/cat/. {cat_out}/
cp -r docs/html/. {html_out}/

""".format(
cat_out = cat_dir.path,
html_out = html_dir.path,
)

ctx.actions.run_shell(
outputs = [cat_dir, html_dir],
inputs = ctx.files.docs_srcs + ctx.files.scripts + ctx.files.readmes + ctx.files.messages,
command = command,
mnemonic = "ManPages",
progress_message = "Generating man pages (cat + html)",
use_default_shell_env = True,
)

return [DefaultInfo(
files = depset([cat_dir, html_dir]),
runfiles = ctx.runfiles(files = [cat_dir, html_dir]),
)]

man_pages = rule(
implementation = _man_pages_impl,
attrs = {
"docs_srcs": attr.label_list(
doc = "All source files under docs/ needed by the Makefile.",
allow_files = True,
),
"messages": attr.label_list(
doc = "Module messages.txt files needed for man3 page generation.",
allow_files = [".txt"],
),
"readmes": attr.label_list(
doc = "Module README.md files (src/*/README.md).",
allow_files = [".md"],
),
"scripts": attr.label_list(
doc = "Python/shell scripts for man page generation.",
allow_files = True,
),
},
)
71 changes: 71 additions & 0 deletions docs/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2026, The OpenROAD Authors

load("//bazel:man_pages.bzl", "man_pages")

man_pages(
name = "man_pages",
Comment on lines +6 to +7
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add //docs:man_pages to the openroad data deps

This target is defined but never consumed by the //:openroad binary, so the new getDocsPath() probe for <exe>.runfiles/_main/docs will not find generated docs during bazel run //:openroad. I checked for //docs:man_pages references and it only appears in this file, which means the man pages are built in isolation but not packaged with the executable’s runfiles; man/GUI help remains unavailable in Bazel-run binaries.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This matches my experience, man in the application doesn't find anything

docs_srcs = [
"Makefile",
] + glob(["md/**/*.md"]),
messages = [
"//src/ant:messages_txt",
"//src/cts:messages_txt",
"//src/dbSta:messages_txt",
"//src/dft:messages_txt",
"//src/dpl:messages_txt",
"//src/drt:messages_txt",
"//src/dst:messages_txt",
"//src/fin:messages_txt",
"//src/gpl:messages_txt",
"//src/grt:messages_txt",
"//src/ifp:messages_txt",
"//src/mpl:messages_txt",
"//src/odb:messages_txt",
"//src/pad:messages_txt",
"//src/par:messages_txt",
"//src/pdn:messages_txt",
"//src/ppl:messages_txt",
"//src/psm:messages_txt",
"//src/rcx:messages_txt",
"//src/rmp:messages_txt",
"//src/rsz:messages_txt",
"//src/stt:messages_txt",
"//src/tap:messages_txt",
"//src/upf:messages_txt",
"//src/utl:messages_txt",
],
readmes = [
"//src/ant:README.md",
"//src/cts:README.md",
"//src/dft:README.md",
"//src/dpl:README.md",
"//src/drt:README.md",
"//src/fin:README.md",
"//src/gpl:README.md",
"//src/grt:README.md",
"//src/gui:README.md",
"//src/ifp:README.md",
"//src/mpl:README.md",
"//src/odb:README.md",
"//src/pad:README.md",
"//src/par:README.md",
"//src/pdn:README.md",
"//src/ppl:README.md",
"//src/psm:README.md",
"//src/rcx:README.md",
"//src/rmp:README.md",
"//src/rsz:README.md",
"//src/stt:README.md",
"//src/tap:README.md",
"//src/upf:README.md",
"//src/utl:README.md",
],
scripts = [
"//docs/src/scripts:link_readmes.sh",
"//docs/src/scripts:md_roff_compat.py",
"//docs/src/scripts:manpage.py",
"//docs/src/scripts:extract_utils.py",
],
visibility = ["//visibility:public"],
)
7 changes: 7 additions & 0 deletions docs/src/scripts/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ py_test(
srcs = ["test_extract_utils.py"],
deps = [":extract_utils"],
)

exports_files([
"md_roff_compat.py",
"manpage.py",
"link_readmes.sh",
"extract_utils.py",
])
7 changes: 7 additions & 0 deletions src/OpenRoad.cc
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,13 @@ std::string OpenRoad::getDocsPath() const
return "";
}

// Check Bazel runfiles layout first
const std::filesystem::path runfiles_docs
= std::filesystem::path(exe + ".runfiles") / "_main" / "docs";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Hardcoding _main as the workspace name is fragile. While _main is the default in modern Bazel versions, it can be overridden in the MODULE.bazel or WORKSPACE file. This logic will break if the workspace is renamed.

if (std::filesystem::exists(runfiles_docs)) {
return runfiles_docs;
}

std::filesystem::path path(exe);

// remove binary name
Expand Down
5 changes: 4 additions & 1 deletion src/ant/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/ant/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/ant/test:__pkg__",
],
)
5 changes: 4 additions & 1 deletion src/cts/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -151,5 +151,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/cts/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/cts/test:__pkg__",
],
)
5 changes: 5 additions & 0 deletions src/dbSta/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("//bazel:tcl_encode_or.bzl", "tcl_encode")
load("//bazel:tcl_wrap_cc.bzl", "tcl_wrap_cc")
load("//test:regression.bzl", "messages_txt")

package(
default_visibility = ["//:__subpackages__"],
Expand Down Expand Up @@ -195,3 +196,7 @@ tcl_wrap_cc(
"//src/odb:swig",
],
)

messages_txt(
visibility = ["//docs:__pkg__"],
)
5 changes: 4 additions & 1 deletion src/dft/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/dft/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/dft/test:__pkg__",
],
)
2 changes: 1 addition & 1 deletion src/dft/test/BUILD
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
load("@rules_python//python:defs.bzl", "py_test")
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2022-2025, The OpenROAD Authors

# Test Parity Note: All tests from CMakeLists.txt are included in this BUILD file.
# No tests are intentionally excluded. See .kiro/specs/bazel-cmake-test-parity/intentional_exclusions.md

load("@rules_cc//cc:cc_test.bzl", "cc_test")
load("@rules_python//python:defs.bzl", "py_test")
load("//test:regression.bzl", "doc_check_test", "regression_test")

package(features = ["layering_check"])
Expand Down
5 changes: 4 additions & 1 deletion src/dpl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -193,5 +193,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/dpl/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/dpl/test:__pkg__",
],
)
5 changes: 4 additions & 1 deletion src/drt/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -324,5 +324,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/drt/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/drt/test:__pkg__",
],
)
5 changes: 5 additions & 0 deletions src/dst/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("//bazel:tcl_encode_or.bzl", "tcl_encode")
load("//bazel:tcl_wrap_cc.bzl", "tcl_wrap_cc")
load("//test:regression.bzl", "messages_txt")

package(
default_visibility = ["//:__subpackages__"],
Expand Down Expand Up @@ -99,3 +100,7 @@ tcl_wrap_cc(
"//src/odb:swig",
],
)

messages_txt(
visibility = ["//docs:__pkg__"],
)
5 changes: 4 additions & 1 deletion src/fin/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/fin/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/fin/test:__pkg__",
],
)
5 changes: 4 additions & 1 deletion src/gpl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -176,5 +176,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/gpl/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/gpl/test:__pkg__",
],
)
5 changes: 4 additions & 1 deletion src/grt/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -268,5 +268,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/grt/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/grt/test:__pkg__",
],
)
5 changes: 4 additions & 1 deletion src/ifp/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/ifp/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/ifp/test:__pkg__",
],
)
5 changes: 4 additions & 1 deletion src/mpl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/mpl/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/mpl/test:__pkg__",
],
)
2 changes: 1 addition & 1 deletion src/mpl/test/BUILD
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
load("@rules_python//python:defs.bzl", "py_test")
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2022-2025, The OpenROAD Authors

# Test Parity Note: All tests from CMakeLists.txt are included in this BUILD file.
# No tests are intentionally excluded. See .kiro/specs/bazel-cmake-test-parity/intentional_exclusions.md

load("@rules_cc//cc:cc_test.bzl", "cc_test")
load("@rules_python//python:defs.bzl", "py_test")
load("//test:regression.bzl", "doc_check_test", "regression_test")

package(features = ["layering_check"])
Expand Down
5 changes: 4 additions & 1 deletion src/odb/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -166,5 +166,8 @@ messages_txt(
src_patterns = [
"include/odb/*.h",
],
visibility = ["//src/odb/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/odb/test:__pkg__",
],
)
5 changes: 4 additions & 1 deletion src/pad/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/pad/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/pad/test:__pkg__",
],
)
5 changes: 4 additions & 1 deletion src/par/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/par/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/par/test:__pkg__",
],
)
5 changes: 4 additions & 1 deletion src/pdn/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/pdn/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/pdn/test:__pkg__",
],
)
5 changes: 4 additions & 1 deletion src/ppl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,8 @@ filegroup(
)

messages_txt(
visibility = ["//src/ppl/test:__pkg__"],
visibility = [
"//docs:__pkg__",
"//src/ppl/test:__pkg__",
],
)
Loading
Loading