Files
OpenROAD/bazel/python_wrap_cc.bzl
Matt Liberty f382eecd90 bazel: dedup SWIG helpers and clean up build files
- Extract shared transitive-depset helpers into bazel/swig_common.bzl;
  tcl_wrap_cc and python_wrap_cc had identical copy-pasted helpers.
  Providers stay distinct so deps type safety is preserved.
- Delete empty bazel/build_helper.bzl (never loaded anywhere).
- Remove dead .tcl/.py endswith filter in tcl_encode_or.bzl; the
  attr.label_list(allow_files=[".tcl", ".py"]) already enforces it.
- Deduplicate -Wall/-Wextra/-Wno-sign-compare/-Wno-unused-parameter
  in OPENROAD_COPTS; these are already set globally via .bazelrc.
- Add missing doc= for runtime_header attr; drop stale "for google3"
  docstring and obsolete/incorrect narration comments.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
2026-04-13 05:50:18 +00:00

150 lines
4.7 KiB
Python

# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2025-2025, The OpenROAD Authors
"""A Python SWIG wrapping rule
These rules generate a C++ src file that is expected to be used as srcs in
cc_library or cc_binary rules. See below for expected usage.
cc_library(srcs=[":python_foo"])
python_wrap_cc(name = "python_foo", srcs=["exception.i"],...)
"""
load(
"//bazel:swig_common.bzl",
"get_transitive_includes",
"get_transitive_options",
"get_transitive_srcs",
)
PythonSwigInfo = provider(
"PythonSwigInfo for taking dependencies on other swig info rules",
fields = [
"transitive_srcs",
"includes",
"swig_options",
],
)
PYTHON_STABLE_API_DEFINE = "Py_LIMITED_API=0x030A0000"
PYTHON_EXTENSION_LINKOPTS = select({
"@platforms//os:macos": [
"-undefined",
"dynamic_lookup",
],
"//conditions:default": [],
})
def _python_wrap_cc_impl(ctx):
"""Generates a single C++ file from the provided srcs in a DefaultInfo."""
if len(ctx.files.srcs) > 1 and not ctx.attr.root_swig_src:
fail("If multiple src files are provided, root_swig_src must be specified.")
swig_lib_dir = ctx.file._swig_swg.dirname
root_file = ctx.file.root_swig_src or ctx.files.srcs[0]
cc_outfile_name = ctx.attr.out or (ctx.attr.name + ".cc")
cc_output_file = ctx.actions.declare_file(cc_outfile_name)
py_outfile_name = ctx.attr.module + ".py"
py_output_file = ctx.actions.declare_file(py_outfile_name)
include_root_directory = ""
if ctx.label.workspace_root:
include_root_directory = ctx.label.workspace_root + "/"
if ctx.label.package:
include_root_directory += ctx.label.package + "/"
src_inputs = get_transitive_srcs(
PythonSwigInfo,
ctx.files.srcs + ctx.files.root_swig_src,
ctx.attr.deps,
)
includes_paths = get_transitive_includes(
PythonSwigInfo,
["{}{}".format(include_root_directory, include) for include in ctx.attr.swig_includes],
ctx.attr.deps,
)
swig_options = get_transitive_options(PythonSwigInfo, ctx.attr.swig_options, ctx.attr.deps)
args = ctx.actions.args()
args.add("-DBAZEL=1")
args.add("-python")
args.add("-c++")
args.add("-flatstaticmethod")
args.add("-module")
args.add(ctx.attr.module)
args.add_all(swig_options.to_list())
args.add_all(includes_paths.to_list(), format_each = "-I%s")
args.add("-o")
args.add(cc_output_file.path)
args.add(root_file.path)
ctx.actions.run(
outputs = [cc_output_file, py_output_file],
inputs = src_inputs,
arguments = [args],
env = {"SWIG_LIB": swig_lib_dir},
tools = ctx.files._swig_lib,
executable = ctx.executable._swig,
)
return [
DefaultInfo(files = depset([cc_output_file, py_output_file])),
PythonSwigInfo(
transitive_srcs = src_inputs,
includes = includes_paths,
swig_options = swig_options,
),
]
python_wrap_cc = rule(
implementation = _python_wrap_cc_impl,
attrs = {
"deps": attr.label_list(
allow_empty = True,
doc = "python_wrap_cc dependencies",
providers = [PythonSwigInfo],
),
"module": attr.string(
mandatory = True,
doc = "swig module",
),
"out": attr.string(
doc = "The name of the C++ source file generated by these rules. If not set, defaults to '<name>.cc'.",
),
"root_swig_src": attr.label(
allow_single_file = [".swig", ".i"],
doc = """If more than one swig file is included in this rule.
The root file must be explicitly provided. This is the file which will be passed to
swig for generation.""",
),
"srcs": attr.label_list(
allow_empty = False,
allow_files = [".i", ".swig", ".h", ".hpp", ".hh"],
doc = "Swig files that generate C++ files",
),
"swig_includes": attr.string_list(
doc = "List of directories relative to the BUILD file to append as -I flags to SWIG",
),
"swig_options": attr.string_list(
doc = "args to pass directly to the swig binary",
),
"_swig": attr.label(
default = "@swig",
allow_files = True,
cfg = "exec",
executable = True,
),
"_swig_lib": attr.label(
default = "@swig//:lib_python",
allow_files = True,
),
"_swig_swg": attr.label(
default = "@swig//:swig_swg",
allow_single_file = True,
doc = "SWIG swig.swg library file used for determining SWIG_LIB " +
"env variable (internal attribute).",
),
},
)