diff --git a/BUILD b/BUILD index 3638149..483b000 100644 --- a/BUILD +++ b/BUILD @@ -1,3 +1,109 @@ +load("@bazel_skylib//lib:selects.bzl", "selects") +load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_flag") + licenses(["notice"]) exports_files(["LICENSE"]) + +bool_flag( + name = "minsize", + build_setting_default = False, +) + +config_setting( + name = "with_sizeopts", + flag_values = {":minsize": "True"}, +) + +config_setting( + name = "without_sizeopts", + flag_values = {":minsize": "False"}, +) + +string_flag( + name = "py-limited-api", + build_setting_default = "unset", + values = [ + "cp312", + "cp313", + "unset", + ], +) + +config_setting( + name = "cp312", + flag_values = {":py-limited-api": "cp312"}, +) + +config_setting( + name = "cp313", + flag_values = {":py-limited-api": "cp313"}, +) + +config_setting( + name = "pyunlimitedapi", + flag_values = {":py-limited-api": "unset"}, +) + +selects.config_setting_group( + name = "unix", + match_any = [ + "@platforms//os:linux", + "@platforms//os:macos", + ], +) + +# Config setting indicating that stable ABI extension build was requested. +selects.config_setting_group( + name = "stable-abi", + match_any = [ + ":cp312", + ":cp313", + ], +) + +# A stable ABI build on Linux or Mac. +# This requires a different extension name (.abi3.so instead of just .so). +selects.config_setting_group( + name = "stable-abi-unix", + match_all = [ + ":stable-abi", + ":unix", + ], +) + +# An unlimited Python ABI build on Linux or Mac. Produces a regular .so file. +selects.config_setting_group( + name = "unstable-abi-unix", + match_all = [ + ":pyunlimitedapi", + ":unix", + ], +) + +# Is the currently configured C++ compiler not MSVC? +selects.config_setting_group( + name = "nonmsvc", + match_any = [ + "@rules_cc//cc/compiler:gcc", + "@rules_cc//cc/compiler:clang", + "@rules_cc//cc/compiler:clang-cl", + "@rules_cc//cc/compiler:mingw-gcc", + ], +) + +selects.config_setting_group( + name = "msvc_and_minsize", + match_all = [ + "@rules_cc//cc/compiler:msvc-cl", + ":with_sizeopts", + ], +) + +selects.config_setting_group( + name = "nonmsvc_and_minsize", + match_all = [ + ":nonmsvc", + ":with_sizeopts", + ], +) diff --git a/build_defs.bzl b/build_defs.bzl index 65d8b45..81cd0f4 100644 --- a/build_defs.bzl +++ b/build_defs.bzl @@ -11,9 +11,10 @@ which can then be included e.g. as a `data` input in a ``native.py_library``. """ load("@bazel_skylib//rules:copy_file.bzl", "copy_file") +load("@nanobind_bazel//:helpers.bzl", "extension_name") NANOBIND_COPTS = select({ - Label("@nanobind//:msvc"): [], + Label("@rules_cc//cc/compiler:msvc-cl"): [], "//conditions:default": ["-fexceptions", "-fvisibility=hidden"], }) @@ -40,7 +41,6 @@ def nanobind_extension( features = [], deps = [], **kwargs): - # TODO: This might need a different suffix depending on SABI yes/no. native.cc_binary( name = name + ".so", srcs = srcs, @@ -52,6 +52,12 @@ def nanobind_extension( **kwargs ) + copy_file( + name = name + "_copy_so_to_abi3_so", + src = name + ".so", + out = name + ".abi3.so", + ) + copy_file( name = name + "_copy_so_to_pyd", src = name + ".so", @@ -60,10 +66,7 @@ def nanobind_extension( native.alias( name = name, - actual = select({ - "@platforms//os:windows": name + ".pyd", - "//conditions:default": name + ".so", - }), + actual = extension_name(name), ) def nanobind_library( diff --git a/helpers.bzl b/helpers.bzl index 6104e2d..ec5aaae 100644 --- a/helpers.bzl +++ b/helpers.bzl @@ -2,7 +2,30 @@ def sizeopts(): return select({ - "@nanobind//:msvc_and_minsize": ["/Os"], - "@nanobind//:nonmsvc_and_minsize": ["-Os"], - "@nanobind//:without_sizeopts": [], + "@nanobind_bazel//:msvc_and_minsize": ["/Os"], + "@nanobind_bazel//:nonmsvc_and_minsize": ["-Os"], + "@nanobind_bazel//:without_sizeopts": [], + }) + +def sizedefs(): + return select({ + "@nanobind_bazel//:with_sizeopts": ["NB_COMPACT_ASSERTS"], + "@nanobind_bazel//:without_sizeopts": [], + }) + +# Define the Python version hex if stable ABI builds are requested. +def pyversionhex(): + return select({ + "@nanobind_bazel//:cp312": ["Py_LIMITED_API=0x030C0000"], + "@nanobind_bazel//:cp313": ["Py_LIMITED_API=0x030D0000"], + "@nanobind_bazel//:pyunlimitedapi": [], + }) + +# Get the name for a built nanobind extension based on target platform +# and stable ABI build yes/no. +def extension_name(name): + return select({ + "@platforms//os:windows": name + ".pyd", + "@nanobind_bazel//:stable-abi-unix": name + ".abi3.so", + "@nanobind_bazel//:unstable-abi-unix": name + ".so", }) diff --git a/nanobind.BUILD b/nanobind.BUILD index 9577d20..8b7f069 100644 --- a/nanobind.BUILD +++ b/nanobind.BUILD @@ -5,62 +5,13 @@ Size optimizations used: -Os, LTO Linker optimizations used: LTCG (MSVC on Windows), linker response file (macOS only). """ -load("@bazel_skylib//lib:selects.bzl", "selects") -load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") -load("@nanobind_bazel//:helpers.bzl", "sizeopts") +load("@nanobind_bazel//:helpers.bzl", "pyversionhex", "sizedefs", "sizeopts") licenses(["notice"]) # TODO: Change this when cleaning up exports later. package(default_visibility = ["//visibility:public"]) -bool_flag( - name = "minsize", - build_setting_default = False, -) - -config_setting( - name = "with_sizeopts", - flag_values = {":minsize": "True"}, -) - -config_setting( - name = "without_sizeopts", - flag_values = {":minsize": "False"}, -) - -config_setting( - name = "msvc", - flag_values = {"@bazel_tools//tools/cpp:compiler": "msvc-cl"}, -) - -# Is the currently configured C++ compiler not MSVC? -selects.config_setting_group( - name = "nonmsvc", - match_any = [ - "@rules_cc//cc/compiler:gcc", - "@rules_cc//cc/compiler:clang", - "@rules_cc//cc/compiler:clang-cl", - "@rules_cc//cc/compiler:mingw-gcc", - ], -) - -selects.config_setting_group( - name = "msvc_and_minsize", - match_all = [ - ":msvc", - ":with_sizeopts", - ], -) - -selects.config_setting_group( - name = "nonmsvc_and_minsize", - match_all = [ - ":nonmsvc", - ":with_sizeopts", - ], -) - cc_library( name = "nanobind", srcs = glob(["src/*.cpp"]), @@ -69,7 +20,7 @@ cc_library( "//conditions:default": [], }), copts = select({ - ":msvc": [ + "@rules_cc//cc/compiler:msvc-cl": [ "/EHsc", # exceptions "/GL", # LTO / whole program optimization ], @@ -77,21 +28,22 @@ cc_library( "//conditions:default": [ "-fexceptions", "-flto", - "-Os", ], }) + sizeopts(), + defines = pyversionhex(), includes = [ "ext/robin_map/include", "include", ], linkopts = select({ - ":msvc": ["/LTCG"], # MSVC. + "@rules_cc//cc/compiler:msvc-cl": ["/LTCG"], # MSVC. "@platforms//os:macos": [ "-Wl,@$(location :cmake/darwin-ld-cpython.sym)", # Apple. "-Wl,-dead_strip", ], "//conditions:default": [], }), + local_defines = sizedefs(), # sizeopts apply to nanobind only. textual_hdrs = glob( [ "include/**/*.h",