From 690e9e8c5ce34e73dca0e9cf7d440c792c7706df Mon Sep 17 00:00:00 2001 From: Friedrich Beckmann Date: Mon, 16 Feb 2026 19:07:31 +0100 Subject: [PATCH 1/6] bazel/macos: compiler/linker flags for Python shared libraries Added -undefined dynamic_lookup linkopts on macOS for Python extension .so targets. The reference symbols are resolved at load time not link time. Without this the linker errors on undefined Python symbols. The change affects only the macos build. Signed-off-by: Friedrich Beckmann --- .bazelrc | 12 ++++++++++++ BUILD.bazel | 7 +++++++ src/gpl/BUILD | 7 +++++++ src/odb/BUILD | 7 +++++++ src/utl/BUILD | 7 +++++++ 5 files changed, 40 insertions(+) diff --git a/.bazelrc b/.bazelrc index 33dedb14cac..534717c2733 100644 --- a/.bazelrc +++ b/.bazelrc @@ -61,6 +61,18 @@ build --copt "-Wno-dangling" --host_copt "-Wno-dangling" build --per_file_copt=.*external/.*@-w build --host_per_file_copt=.*external/.*@-w +##### Platform-specific configs (auto-selected) ############# +# --enable_platform_specific_config makes bazel automatically apply +# build:macos on macOS, build:linux on Linux, etc. +common --enable_platform_specific_config + +# macOS: boost.stacktrace needs this since backtrace() doesn't require GNU source +build:macos --copt=-DBOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED +build:macos --host_copt=-DBOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED +# Aligned allocation/deallocation for abseil is only available since 10.13 +build:macos --macos_minimum_os=10.13 +build:macos --host_macos_minimum_os=10.13 + # Settings for --config=asan address sanitizer build build:asan --strip=never build:asan --copt=-fsanitize=address diff --git a/BUILD.bazel b/BUILD.bazel index 370c9b36b75..2f8925623bf 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -283,6 +283,13 @@ cc_binary( name = "_openroadpy.so", srcs = [":openroad_swig-py"], defines = [PYTHON_STABLE_API_DEFINE], + linkopts = select({ + "@platforms//os:macos": [ + "-undefined", + "dynamic_lookup", + ], + "//conditions:default": [], + }), linkshared = True, deps = [ ":openroad_lib", # Depends on the core odb C++ library diff --git a/src/gpl/BUILD b/src/gpl/BUILD index f58041f238b..0af7f537aed 100644 --- a/src/gpl/BUILD +++ b/src/gpl/BUILD @@ -95,6 +95,13 @@ cc_binary( ], defines = [PYTHON_STABLE_API_DEFINE], includes = ["src"], + linkopts = select({ + "@platforms//os:macos": [ + "-undefined", + "dynamic_lookup", + ], + "//conditions:default": [], + }), linkshared = True, deps = [ "//src/gpl", diff --git a/src/odb/BUILD b/src/odb/BUILD index 427dd649cb9..17169645202 100644 --- a/src/odb/BUILD +++ b/src/odb/BUILD @@ -105,6 +105,13 @@ cc_binary( srcs = [":swig-py"], defines = [PYTHON_STABLE_API_DEFINE], includes = ["src/swig/common"], + linkopts = select({ + "@platforms//os:macos": [ + "-undefined", + "dynamic_lookup", + ], + "//conditions:default": [], + }), linkshared = True, deps = [ ":odb", # Depends on the core odb C++ library diff --git a/src/utl/BUILD b/src/utl/BUILD index c4bb280665a..b2a2fcefaa6 100644 --- a/src/utl/BUILD +++ b/src/utl/BUILD @@ -105,6 +105,13 @@ cc_binary( ], defines = [PYTHON_STABLE_API_DEFINE], includes = ["src"], + linkopts = select({ + "@platforms//os:macos": [ + "-undefined", + "dynamic_lookup", + ], + "//conditions:default": [], + }), linkshared = True, deps = [ "//src/utl", From fa4d289372fda7a915071f993289e843d03c42c1 Mon Sep 17 00:00:00 2001 From: Friedrich Beckmann Date: Mon, 16 Feb 2026 19:10:54 +0100 Subject: [PATCH 2/6] bazel/macos: SWIG exception handler ordering fix Moved %include "Exception-py.i" before %template declarations so the Python exception handler is active when SWIG generates template wrapper code. Without this the python tests in the regression fail because the ask for tcl symbols. Signed-off-by: Friedrich Beckmann --- src/OpenRoad-py.i | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenRoad-py.i b/src/OpenRoad-py.i index 17a2476835e..529b08ca7bf 100644 --- a/src/OpenRoad-py.i +++ b/src/OpenRoad-py.i @@ -47,11 +47,11 @@ get_db_block(); %} +%include "Exception-py.i" + %template(Corners) std::vector; %template(MTerms) std::vector; %template(Masters) std::vector; - -%include "Exception-py.i" %include "ord/Tech.h" %include "ord/Design.h" %include "ord/Timing.h" From 43850d65116df31d99a9d10738ceeda2adb590c1 Mon Sep 17 00:00:00 2001 From: Friedrich Beckmann Date: Mon, 16 Feb 2026 19:13:17 +0100 Subject: [PATCH 3/6] macos: fixed odb regression test which used md5sum (Linux-only) I rewrote the test to use pure tcl file reads and string comparison. Now the test also works on macos. Signed-off-by: Friedrich Beckmann --- src/odb/test/write_def58_gzip.tcl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/odb/test/write_def58_gzip.tcl b/src/odb/test/write_def58_gzip.tcl index 7f5b3ceba9a..5c97a02072f 100644 --- a/src/odb/test/write_def58_gzip.tcl +++ b/src/odb/test/write_def58_gzip.tcl @@ -11,12 +11,16 @@ set out_gzip_def [make_result_file "write_def58_gzip.zipped.def.gz"] write_def $out_gzip_def exec gunzip -f $out_gzip_def -set def0 [exec md5sum $out_def] -set def1 [exec md5sum [string range $out_gzip_def 0 end-3]] +set unzipped_def [string range $out_gzip_def 0 end-3] + +set f0 [open $out_def r] +set def0 [read $f0] +close $f0 + +set f1 [open $unzipped_def r] +set def1 [read $f1] +close $f1 -# Remove filename from output -set def0 [string range $def0 0 32] -set def1 [string range $def1 0 32] if { $def0 == $def1 } { puts "Matched" puts "pass" From 6b9c9c95cf4896fd793b54fadc112b66975b831f Mon Sep 17 00:00:00 2001 From: Friedrich Beckmann Date: Mon, 16 Feb 2026 19:53:32 +0100 Subject: [PATCH 4/6] bazel/macos: fix shell script to also work on macos Signed-off-by: Friedrich Beckmann --- test/regression_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/regression_test.sh b/test/regression_test.sh index 128d65b9820..5f483bd0885 100755 --- a/test/regression_test.sh +++ b/test/regression_test.sh @@ -23,7 +23,7 @@ case "$TEST_TYPE" in esac echo "Command: $CMD" -$CMD |& tee $LOG_FILE +$CMD 2>&1 | tee $LOG_FILE echo "Exitcode: $?" From 6d77389dba8c0cb5d750696d8415777c75174783 Mon Sep 17 00:00:00 2001 From: Friedrich Beckmann Date: Tue, 24 Feb 2026 17:28:22 +0100 Subject: [PATCH 5/6] bazel/macos: central setting for linker settings for python extensions I extended the mechanism that is used to supply the defines for the python module. Now tha linker options are set in one place. Signed-off-by: Friedrich Beckmann --- BUILD.bazel | 10 ++-------- bazel/python_wrap_cc.bzl | 8 ++++++++ src/gpl/BUILD | 10 ++-------- src/odb/BUILD | 10 ++-------- src/utl/BUILD | 10 ++-------- 5 files changed, 16 insertions(+), 32 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index 2f8925623bf..3a69d8213df 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -7,7 +7,7 @@ load("@rules_cc//cc:cc_binary.bzl", "cc_binary") load("@rules_cc//cc:cc_library.bzl", "cc_library") load("@rules_shell//shell:sh_binary.bzl", "sh_binary") load("//bazel:notification.bzl", "notification_rule") -load("//bazel:python_wrap_cc.bzl", "PYTHON_STABLE_API_DEFINE", "python_wrap_cc") +load("//bazel:python_wrap_cc.bzl", "PYTHON_EXTENSION_LINKOPTS", "PYTHON_STABLE_API_DEFINE", "python_wrap_cc") load("//bazel:tcl_encode_or.bzl", "tcl_encode") load("//bazel:tcl_wrap_cc.bzl", "tcl_wrap_cc") @@ -283,13 +283,7 @@ cc_binary( name = "_openroadpy.so", srcs = [":openroad_swig-py"], defines = [PYTHON_STABLE_API_DEFINE], - linkopts = select({ - "@platforms//os:macos": [ - "-undefined", - "dynamic_lookup", - ], - "//conditions:default": [], - }), + linkopts = PYTHON_EXTENSION_LINKOPTS, linkshared = True, deps = [ ":openroad_lib", # Depends on the core odb C++ library diff --git a/bazel/python_wrap_cc.bzl b/bazel/python_wrap_cc.bzl index 43705d590cd..9af088824c7 100644 --- a/bazel/python_wrap_cc.bzl +++ b/bazel/python_wrap_cc.bzl @@ -19,6 +19,14 @@ PythonSwigInfo = provider( PYTHON_STABLE_API_DEFINE = "Py_LIMITED_API=0x030A0000" +PYTHON_EXTENSION_LINKOPTS = select({ + "@platforms//os:macos": [ + "-undefined", + "dynamic_lookup", + ], + "//conditions:default": [], +}) + def _get_transitive_srcs(srcs, deps): return depset( srcs, diff --git a/src/gpl/BUILD b/src/gpl/BUILD index 0af7f537aed..a761be270ea 100644 --- a/src/gpl/BUILD +++ b/src/gpl/BUILD @@ -4,7 +4,7 @@ load("@openroad_rules_python//python:defs.bzl", "py_library") load("@rules_cc//cc:cc_binary.bzl", "cc_binary") load("@rules_cc//cc:cc_library.bzl", "cc_library") -load("//bazel:python_wrap_cc.bzl", "PYTHON_STABLE_API_DEFINE", "python_wrap_cc") +load("//bazel:python_wrap_cc.bzl", "PYTHON_EXTENSION_LINKOPTS", "PYTHON_STABLE_API_DEFINE", "python_wrap_cc") load("//bazel:tcl_encode_or.bzl", "tcl_encode") load("//bazel:tcl_wrap_cc.bzl", "tcl_wrap_cc") @@ -95,13 +95,7 @@ cc_binary( ], defines = [PYTHON_STABLE_API_DEFINE], includes = ["src"], - linkopts = select({ - "@platforms//os:macos": [ - "-undefined", - "dynamic_lookup", - ], - "//conditions:default": [], - }), + linkopts = PYTHON_EXTENSION_LINKOPTS, linkshared = True, deps = [ "//src/gpl", diff --git a/src/odb/BUILD b/src/odb/BUILD index 17169645202..edc14eeeca9 100644 --- a/src/odb/BUILD +++ b/src/odb/BUILD @@ -4,7 +4,7 @@ load("@openroad_rules_python//python:defs.bzl", "py_library") load("@rules_cc//cc:cc_binary.bzl", "cc_binary") load("@rules_cc//cc:cc_library.bzl", "cc_library") -load("//bazel:python_wrap_cc.bzl", "PYTHON_STABLE_API_DEFINE", "python_wrap_cc") +load("//bazel:python_wrap_cc.bzl", "PYTHON_EXTENSION_LINKOPTS", "PYTHON_STABLE_API_DEFINE", "python_wrap_cc") load("//bazel:tcl_encode_or.bzl", "tcl_encode") load("//bazel:tcl_wrap_cc.bzl", "tcl_wrap_cc") @@ -105,13 +105,7 @@ cc_binary( srcs = [":swig-py"], defines = [PYTHON_STABLE_API_DEFINE], includes = ["src/swig/common"], - linkopts = select({ - "@platforms//os:macos": [ - "-undefined", - "dynamic_lookup", - ], - "//conditions:default": [], - }), + linkopts = PYTHON_EXTENSION_LINKOPTS, linkshared = True, deps = [ ":odb", # Depends on the core odb C++ library diff --git a/src/utl/BUILD b/src/utl/BUILD index b2a2fcefaa6..31dcea32a52 100644 --- a/src/utl/BUILD +++ b/src/utl/BUILD @@ -4,7 +4,7 @@ load("@openroad_rules_python//python:defs.bzl", "py_library") load("@rules_cc//cc:cc_binary.bzl", "cc_binary") load("@rules_cc//cc:cc_library.bzl", "cc_library") -load("//bazel:python_wrap_cc.bzl", "PYTHON_STABLE_API_DEFINE", "python_wrap_cc") +load("//bazel:python_wrap_cc.bzl", "PYTHON_EXTENSION_LINKOPTS", "PYTHON_STABLE_API_DEFINE", "python_wrap_cc") load("//bazel:tcl_encode_or.bzl", "tcl_encode") load("//bazel:tcl_wrap_cc.bzl", "tcl_wrap_cc") @@ -105,13 +105,7 @@ cc_binary( ], defines = [PYTHON_STABLE_API_DEFINE], includes = ["src"], - linkopts = select({ - "@platforms//os:macos": [ - "-undefined", - "dynamic_lookup", - ], - "//conditions:default": [], - }), + linkopts = PYTHON_EXTENSION_LINKOPTS, linkshared = True, deps = [ "//src/utl", From 561b8d52be5ef6277b0c4795128c1b8c2d8be10a Mon Sep 17 00:00:00 2001 From: Friedrich Beckmann Date: Thu, 26 Feb 2026 09:08:48 +0100 Subject: [PATCH 6/6] bazel/macos: update third-party/abc submodule I already made the tcl changes in the third-party/abc module. They are commited in abc. So lets track them. Signed-off-by: Friedrich Beckmann --- third-party/abc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third-party/abc b/third-party/abc index 4c756ffb8df..a68b23c77d4 160000 --- a/third-party/abc +++ b/third-party/abc @@ -1 +1 @@ -Subproject commit 4c756ffb8dff7c583e80c7970d117abd3dfddb5c +Subproject commit a68b23c77d4c9b3947fcff9cdb7d509cad7fe46a