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

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .bazelignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ src/sta/debug/
# we use abc from MODULE.bazel
third-party/abc/
tmp
# standalone workspace for downstream consumer tests
test/downstream/
32 changes: 8 additions & 24 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_pkg//pkg:tar.bzl", "pkg_tar")
load("@rules_python//python:defs.bzl", "py_library")
load("@rules_shell//shell:sh_binary.bzl", "sh_binary")
load("@rules_shell//shell:sh_test.bzl", "sh_test")
load("//bazel:notification.bzl", "notification_rule")
load("//bazel:python_wrap_cc.bzl", "PYTHON_EXTENSION_LINKOPTS", "PYTHON_STABLE_API_DEFINE", "python_wrap_cc")
load("//bazel:tcl_encode_or.bzl", "tcl_encode")
Expand Down Expand Up @@ -216,7 +213,7 @@ cc_library(
includes = [
"include",
],
visibility = ["//visibility:public"],
visibility = ["//:__subpackages__"],
deps = [
"//src/sta:opensta_lib",
"@abseil-cpp//absl/base:core_headers",
Expand Down Expand Up @@ -334,7 +331,7 @@ cc_binary(
# This packages the SWIG-generated Python wrapper (odb.py) and the
# compiled C++ extension (_odb.so) together.
py_library(
name = "ord_py",
name = "openroad_py",
srcs = [":openroad_swig-py"], # Use the .py output from the swig-py rule
# The data attribute makes the .so file available at runtime.
data = [":_openroadpy.so"],
Expand Down Expand Up @@ -390,15 +387,15 @@ filegroup(
srcs = [
"src/Exception.i",
],
visibility = ["@//:__subpackages__"],
visibility = ["//:__subpackages__"],
)

filegroup(
name = "error_swig-py",
srcs = [
"src/Exception-py.i",
],
visibility = ["@//:__subpackages__"],
visibility = ["//:__subpackages__"],
)

filegroup(
Expand All @@ -413,23 +410,7 @@ filegroup(
srcs = [
"src/options.i",
],
visibility = ["@//:__subpackages__"],
)

sh_binary(
name = "install",
srcs = ["//bazel:install.sh"],
args = [],
data = [":tarfile"],
)

pkg_tar(
name = "tarfile",
srcs = [
":openroad",
],
include_runfiles = True,
package_file_name = "openroad.tar",
visibility = ["//:__subpackages__"],
)

# ---------------------------------------------------------------------------
Expand All @@ -441,6 +422,7 @@ pkg_tar(

# --- TCL linting (tclint) -------------------------------------------------

# buildifier: disable=native-sh-test
sh_test(
name = "lint_tcl_test",
srcs = ["//bazel:tcl_lint_test.sh"],
Expand All @@ -454,6 +436,7 @@ sh_test(

# --- TCL formatting check (tclfmt --check) --------------------------------

# buildifier: disable=native-sh-test
sh_test(
name = "fmt_tcl_test",
srcs = ["//bazel:tcl_fmt_test.sh"],
Expand All @@ -467,6 +450,7 @@ sh_test(

# --- TCL auto-format (tclfmt --in-place) ----------------------------------

# buildifier: disable=native-sh-binary
sh_binary(
name = "tidy_tcl",
srcs = ["//bazel:tcl_tidy.sh"],
Expand Down
37 changes: 29 additions & 8 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,25 @@ bazel_dep(name = "rules_bison", version = "0.3.1")
bazel_dep(name = "rules_cc", version = "0.2.17")
bazel_dep(name = "rules_flex", version = "0.3.1")
bazel_dep(name = "rules_python", version = "1.8.5")
bazel_dep(name = "rules_pkg", version = "1.2.0")

bazel_dep(name = "rules_pkg", version = "1.2.0", dev_dependency = True)

# Used by chisel_binary from @bazel-orfs in test/orfs/mock-array
bazel_dep(name = "rules_jvm_external", version = "6.4", dev_dependency = True)
bazel_dep(name = "rules_chisel", version = "0.2.0", dev_dependency = True)
single_version_override(
module_name = "rules_chisel",
patch_strip = 1,
patches = ["//:rules-chisel-dev-dep.patch"],
)

bazel_dep(name = "rules_scala", version = "7.1.5", dev_dependency = True)
bazel_dep(name = "rules_shell", version = "0.6.1", dev_dependency = True)
bazel_dep(name = "rules_verilator", version = "0.1.0", dev_dependency = True)

bazel_dep(name = "rules_shell", version = "0.6.1")
bazel_dep(name = "rules_verilator", version = "0.1.0")
bazel_dep(name = "swig", version = "4.3.0.bcr.2")
bazel_dep(name = "verilator", version = "5.036.bcr.3")

bazel_dep(name = "verilator", version = "5.036.bcr.3", dev_dependency = True)

BOOST_VERSION = "1.89.0.bcr.2"

Expand Down Expand Up @@ -91,11 +99,19 @@ git_override(
remote = "https://github.com/The-OpenROAD-Project/qt_bazel_prebuilts",
)

## Lock the compiler version and avoid any local compiler
## Lock the compiler version and avoid any local compiler.
## The bazel_dep stays non-dev because llvm_prebuilt's build_file
## references @toolchains_llvm//toolchain:BUILD.llvm_repo.
## The extension and toolchain registration are dev_dependency because
## toolchains_llvm enforces root-module-only extension usage.
## Downstream consumers must configure their own C++ toolchain.
bazel_dep(name = "toolchains_llvm", version = "1.5.0")

# Configure and register the toolchain.
llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm")
llvm = use_extension(
"@toolchains_llvm//toolchain/extensions:llvm.bzl",
"llvm",
dev_dependency = True,
)
llvm.toolchain(
llvm_version = "20.1.8",
)
Expand All @@ -105,7 +121,12 @@ use_repo(llvm, "llvm_toolchain")
# FYI: Comment out on NixOS where you'd like to use the local clang toolchain.
register_toolchains(
"@llvm_toolchain//:all",
dev_dependency = True,
)

register_toolchains(
"@rules_verilator//verilator:verilator_toolchain",
dev_dependency = True,
)

python = use_extension("@rules_python//python/extensions:python.bzl", "python")
Expand Down Expand Up @@ -171,7 +192,7 @@ scala_deps.settings(
)
scala_deps.scala()

chisel = use_extension("@rules_chisel//chisel:extensions.bzl", "chisel")
chisel = use_extension("@rules_chisel//chisel:extensions.bzl", "chisel", dev_dependency = True)
chisel.toolchain(
chisel_version = CHISEL_VERSION,
firtool_resolver_version = FIRTOOL_RESOLVER_VERSION,
Expand Down
10 changes: 5 additions & 5 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 57 additions & 0 deletions docs/user/Bazel.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,63 @@ Without offering any deeper insight some comments about what is shown above:
- `exec` means host, appears with `ST` and an extra hash at the end
- `k8` always there, possibly referring to [K8](https://en.wikipedia.org/wiki/X86-64)

## Using OpenROAD as a dependency from another project

OpenROAD can be consumed as a Bazel module (`bazel_dep`) from another
project. The public API consists of two targets:

| Target | Description |
| --- | --- |
| `@openroad//:openroad` | The CLI binary |
| `@openroad//:openroad_py` | Python bindings for scripting |

All other targets (e.g. `openroad_lib`, internal libraries) are
restricted to OpenROAD's own subpackages and are not part of the
public API.

### Minimal MODULE.bazel for a downstream project

```starlark
module(name = "my-project")

bazel_dep(name = "openroad")
git_override(
module_name = "openroad",
commit = "<commit-hash>",
init_submodules = True,
remote = "https://github.com/The-OpenROAD-Project/OpenROAD.git",
)

# qt-bazel is not in BCR; git_override is root-module-only,
# so downstream consumers must repeat it.
bazel_dep(name = "qt-bazel")
git_override(
module_name = "qt-bazel",
commit = "df022f4ebaa4130713692fffd2f519d49e9d0b97",
remote = "https://github.com/The-OpenROAD-Project/qt_bazel_prebuilts",
)

# OpenROAD's toolchains_llvm extension is dev_dependency,
# so the root module must configure the C++ toolchain.
bazel_dep(name = "toolchains_llvm", version = "1.5.0")

llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm")
llvm.toolchain(llvm_version = "20.1.8")
use_repo(llvm, "llvm_toolchain")
register_toolchains("@llvm_toolchain//:all")
```

### Dev dependencies not leaked to consumers

The following are `dev_dependency` in OpenROAD and will not be forced
on downstream projects via MVS:

- `rules_shell`, `rules_pkg` — only needed for `//packaging:install`
- `rules_verilator`, `verilator` — only needed for test/orfs simulation
- `toolchains_llvm` extension and toolchain registration

The downstream test at `test/downstream/` verifies these invariants.

## Build without testing

bazelisk build :openroad
Expand Down
18 changes: 18 additions & 0 deletions packaging/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2025-2025, The OpenROAD Authors

load("@rules_pkg//pkg:tar.bzl", "pkg_tar")
load("@rules_shell//shell:sh_binary.bzl", "sh_binary")

sh_binary(
name = "install",
srcs = ["//bazel:install.sh"],
data = [":tarfile"],
)

pkg_tar(
name = "tarfile",
srcs = ["//:openroad"],
include_runfiles = True,
package_file_name = "openroad.tar",
)
2 changes: 1 addition & 1 deletion python/openroad/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ py_library(
imports = [".."],
visibility = ["//visibility:public"],
deps = [
"//:ord_py",
"//:openroad_py",
"//src/odb:odb_py",
"//src/utl:utl_py",
],
Expand Down
22 changes: 22 additions & 0 deletions rules-chisel-dev-dep.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--- a/chisel/extensions.bzl
+++ b/chisel/extensions.bzl
@@ -170,9 +170,16 @@
scala_version = settings.scala_version,
)

+ root_is_dev = True
+ for mod in module_ctx.modules:
+ if mod.is_root:
+ for tag in mod.tags.toolchain:
+ if not module_ctx.is_dev_dependency(tag):
+ root_is_dev = False
+
return module_ctx.extension_metadata(
reproducible = settings.lock_file != None,
- root_module_direct_deps = [settings.repo_name],
- root_module_direct_dev_deps = [],
+ root_module_direct_deps = [] if root_is_dev else [settings.repo_name],
+ root_module_direct_dev_deps = [settings.repo_name] if root_is_dev else [],
)

toolchain = tag_class(
13 changes: 13 additions & 0 deletions test/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,23 @@
# Copyright (c) 2025-2025, The OpenROAD Authors

load("@rules_python//python:defs.bzl", "py_test")
load("@rules_shell//shell:sh_test.bzl", "sh_test")
load("//test:regression.bzl", "regression_test")

package(features = ["layering_check"])

# Verifies that downstream consumers only see the intended public API
# and that dev_dependencies are not leaked. Runs bazelisk inside the
# standalone test/downstream/ workspace.
sh_test(
name = "downstream_visibility_test",
srcs = ["downstream/visibility_test.sh"],
tags = [
"local",
"no-sandbox",
],
)

exports_files(
[
"bazel_test.sh",
Expand Down
1 change: 1 addition & 0 deletions test/downstream/.bazelversion
34 changes: 34 additions & 0 deletions test/downstream/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Targets for testing OpenROAD's public API from a downstream module.

load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_python//python:defs.bzl", "py_test")

# //:openroad is the public CLI binary — should be visible.
genrule(
name = "openroad_visible",
srcs = ["@openroad"],
outs = ["openroad_visible.txt"],
cmd = "echo ok > $@",
)

# //:openroad_py is the public Python bindings — should be visible.
py_test(
name = "openroad_py_test",
srcs = ["openroad_py_test.py"],
deps = ["@openroad//:openroad_py"],
)

# Targets below are expected to FAIL analysis (visibility restricted).
# Used by visibility_test.sh to verify internal targets are not exposed.

cc_library(
name = "openroad_lib_consumer",
deps = ["@openroad//:openroad_lib"],
)

genrule(
name = "openroadpy_so_consumer",
srcs = ["@openroad//:_openroadpy.so"],
outs = ["so_consumer.txt"],
cmd = "echo ok > $@",
)
Loading
Loading