diff --git a/CMakeLists.txt b/CMakeLists.txt index 4dbd2a6396d4..13531879aa47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ endif() # The version passed to find_package(Bazel) should match the # minimum_bazel_version value in the call to versions.check() in WORKSPACE. -set(MINIMUM_BAZEL_VERSION 7.1) +set(MINIMUM_BAZEL_VERSION 7.4) find_package(Bazel ${MINIMUM_BAZEL_VERSION} MODULE) if(NOT Bazel_FOUND) set(Bazel_EXECUTABLE "${PROJECT_SOURCE_DIR}/third_party/com_github_bazelbuild_bazelisk/bazelisk.py") diff --git a/MODULE.bazel b/MODULE.bazel index e473a118ed45..0e07216aaf90 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -19,7 +19,8 @@ bazel_dep(name = "rules_cc", version = "0.0.17") bazel_dep(name = "rules_java", version = "8.6.1") bazel_dep(name = "rules_license", version = "1.0.0") bazel_dep(name = "rules_python", version = "0.40.0") -bazel_dep(name = "rules_rust", version = "0.55.6") +bazel_dep(name = "rules_rust", version = "0.55.6") # When upgrading rules_rust, check the TODO in tools/bazel.rc. # noqa +bazel_dep(name = "rules_shell", version = "0.3.0") cc_configure = use_extension( "@rules_cc//cc:extensions.bzl", diff --git a/WORKSPACE b/WORKSPACE index b60e7a1ec6d9..070e1fce20d9 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -26,7 +26,7 @@ load("@bazel_skylib//lib:versions.bzl", "versions") # This needs to be in WORKSPACE or a repository rule for native.bazel_version # to actually be defined. The minimum_bazel_version value should match the # version passed to the find_package(Bazel) call in the root CMakeLists.txt. -versions.check(minimum_bazel_version = "7.1") +versions.check(minimum_bazel_version = "7.4") # The cargo_universe programs are only used by Drake's new_release tooling, not # by any compilation rules. As such, we can put it directly into the WORKSPACE diff --git a/WORKSPACE.bzlmod b/WORKSPACE.bzlmod index 090a11fa756b..2fc2a6d4d6ba 100644 --- a/WORKSPACE.bzlmod +++ b/WORKSPACE.bzlmod @@ -24,7 +24,7 @@ load("@bazel_skylib//lib:versions.bzl", "versions") # This needs to be in WORKSPACE or a repository rule for native.bazel_version # to actually be defined. The minimum_bazel_version value should match the # version passed to the find_package(Bazel) call in the root CMakeLists.txt. -versions.check(minimum_bazel_version = "7.1") +versions.check(minimum_bazel_version = "7.4") # The cargo_universe programs are only used by Drake's new_release tooling, not # by any compilation rules. As such, we can put it directly into the WORKSPACE diff --git a/examples/hardware_sim/BUILD.bazel b/examples/hardware_sim/BUILD.bazel index 8afa264c51d1..876e3600822e 100644 --- a/examples/hardware_sim/BUILD.bazel +++ b/examples/hardware_sim/BUILD.bazel @@ -10,6 +10,7 @@ load( "drake_py_library", "drake_py_unittest", ) +load("//tools/skylark:sh.bzl", "sh_binary") package(default_visibility = ["//visibility:private"]) diff --git a/third_party/com_github_bazelbuild_rules_cc/whole_archive.bzl b/third_party/com_github_bazelbuild_rules_cc/whole_archive.bzl index 045878cfb156..1bd1c35a4132 100644 --- a/third_party/com_github_bazelbuild_rules_cc/whole_archive.bzl +++ b/third_party/com_github_bazelbuild_rules_cc/whole_archive.bzl @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("//tools/skylark:cc.bzl", "CcInfo") + # This function is forked and modified from bazelbuild/rules_cc as of: # https://github.com/bazelbuild/rules_cc/blob/262ebec/cc/find_cc_toolchain.bzl def _find_cc_toolchain(ctx): diff --git a/tools/bazel.rc b/tools/bazel.rc index f5b658bc9533..13d40e3ba177 100644 --- a/tools/bazel.rc +++ b/tools/bazel.rc @@ -4,6 +4,12 @@ common --enable_workspace=true common --enable_bzlmod=false +# Require all rules to be loaded in MODULE.bazel -- don't allow any legacy +# implicit loads built-in to Bazel itself to take effect. +# TODO(jwnimmer-tri) Once we upgrade rules_rust past > 0.55, we can remove +# the rules_shell here; see bazelbuild/rules_rust#3074. +common --incompatible_autoload_externally=@rules_shell + # Default to an optimized build. build -c opt diff --git a/tools/cc_toolchain/BUILD.bazel b/tools/cc_toolchain/BUILD.bazel index 482d42b8a38f..b90fbfea5f70 100644 --- a/tools/cc_toolchain/BUILD.bazel +++ b/tools/cc_toolchain/BUILD.bazel @@ -1,4 +1,5 @@ load("//tools/lint:lint.bzl", "add_lint_tests") +load("//tools/skylark:sh.bzl", "sh_binary") package(default_visibility = ["//visibility:public"]) diff --git a/tools/dynamic_analysis/BUILD.bazel b/tools/dynamic_analysis/BUILD.bazel index bede7a38e557..5c2cb3b8db96 100644 --- a/tools/dynamic_analysis/BUILD.bazel +++ b/tools/dynamic_analysis/BUILD.bazel @@ -1,4 +1,5 @@ load("//tools/lint:lint.bzl", "add_lint_tests") +load("//tools/skylark:sh.bzl", "sh_binary") package(default_visibility = ["//visibility:public"]) diff --git a/tools/install/install.bzl b/tools/install/install.bzl index a203a9020a51..db021ef04daf 100644 --- a/tools/install/install.bzl +++ b/tools/install/install.bzl @@ -1,14 +1,16 @@ load("@python//:version.bzl", "PYTHON_SITE_PACKAGES_RELPATH", "PYTHON_VERSION") load("@rules_license//rules:providers.bzl", "LicenseInfo") +load("//tools/skylark:cc.bzl", "CcInfo") load("//tools/skylark:drake_java.bzl", "MainClassInfo") load("//tools/skylark:drake_py.bzl", "drake_py_test") +load("//tools/skylark:java.bzl", "JavaInfo") load( "//tools/skylark:pathutils.bzl", "dirname", "join_paths", "output_path", ) -load("//tools/skylark:py.bzl", "py_binary") +load("//tools/skylark:py.bzl", "PyInfo", "py_binary") InstallInfo = provider() diff --git a/tools/install/libdrake/header_lint.bzl b/tools/install/libdrake/header_lint.bzl index aa44babc9413..e6f2c7729db6 100644 --- a/tools/install/libdrake/header_lint.bzl +++ b/tools/install/libdrake/header_lint.bzl @@ -1,3 +1,6 @@ +load("//tools/skylark:cc.bzl", "CcInfo") +load("//tools/skylark:sh.bzl", "sh_test") + # This file contains a linter rule that ensures that only our allowed set of # third-party dependencies are used as "interface deps". In almost all cases, # we should be using "implementation deps" when using third-party libraries. @@ -97,7 +100,7 @@ def cc_check_allowed_headers(name, deps = []): tags = ["manual"], deps = deps, ) - native.sh_test( + sh_test( name = name, tags = ["lint"], srcs = [":" + sh_src], diff --git a/tools/skylark/cc.bzl b/tools/skylark/cc.bzl index 4f8b8ff31b5a..a714436c4d82 100644 --- a/tools/skylark/cc.bzl +++ b/tools/skylark/cc.bzl @@ -5,22 +5,35 @@ externals), we should be using this file's macros. We should never call `native.cc_foo()` from anywhere other than this file, and any BUILD file that uses `cc_foo()` rules should load these macros instead of relying on the (implicitly loaded) `native.cc_foo()` default. - -TODO(jwnimmer-tri) Consider writing a linter to check for this, in case -we find that people are unable to manually maintain this invariant. """ +load( + "@rules_cc//cc:defs.bzl", + _CcInfo = "CcInfo", + _cc_binary = "cc_binary", + _cc_import = "cc_import", + _cc_library = "cc_library", + _cc_shared_library = "cc_shared_library", + _cc_test = "cc_test", + _objc_library = "objc_library", +) + def cc_binary(**kwargs): - native.cc_binary(**kwargs) + _cc_binary(**kwargs) def cc_import(**kwargs): - native.cc_import(**kwargs) + _cc_import(**kwargs) def cc_library(**kwargs): - native.cc_library(**kwargs) + _cc_library(**kwargs) def cc_shared_library(**kwargs): - native.cc_shared_library(**kwargs) + _cc_shared_library(**kwargs) def cc_test(**kwargs): - native.cc_test(**kwargs) + _cc_test(**kwargs) + +def objc_library(**kwargs): + _objc_library(**kwargs) + +CcInfo = _CcInfo diff --git a/tools/skylark/drake_cc.bzl b/tools/skylark/drake_cc.bzl index 4463a39f79ac..6b5f53004d42 100644 --- a/tools/skylark/drake_cc.bzl +++ b/tools/skylark/drake_cc.bzl @@ -1,5 +1,5 @@ load("@cc//:compiler.bzl", "COMPILER_ID", "COMPILER_VERSION_MAJOR") -load("//tools/skylark:cc.bzl", "cc_binary", "cc_library", "cc_test") +load("//tools/skylark:cc.bzl", "CcInfo", "cc_binary", "cc_library", "cc_test") load( "//tools/skylark:kwargs.bzl", "incorporate_allow_network", diff --git a/tools/skylark/drake_java.bzl b/tools/skylark/drake_java.bzl index 5340fabed28d..56b4690cfd71 100644 --- a/tools/skylark/drake_java.bzl +++ b/tools/skylark/drake_java.bzl @@ -1,4 +1,4 @@ -load("//tools/skylark:java.bzl", "java_binary") +load("//tools/skylark:java.bzl", "JavaInfo", "java_binary") MainClassInfo = provider() diff --git a/tools/skylark/drake_sh.bzl b/tools/skylark/drake_sh.bzl index de1ef305a040..21594d14783e 100644 --- a/tools/skylark/drake_sh.bzl +++ b/tools/skylark/drake_sh.bzl @@ -5,6 +5,7 @@ load( "incorporate_display", "incorporate_num_threads", ) +load("//tools/skylark:sh.bzl", "sh_test") def drake_sh_test( name, @@ -30,7 +31,7 @@ def drake_sh_test( kwargs = incorporate_display(kwargs, display = display) kwargs = incorporate_num_threads(kwargs, num_threads = num_threads) kwargs = amend(kwargs, "size", default = "small") - native.sh_test( + sh_test( name = name, **kwargs ) diff --git a/tools/skylark/java.bzl b/tools/skylark/java.bzl index 177a6fe086f5..2e43438cedcc 100644 --- a/tools/skylark/java.bzl +++ b/tools/skylark/java.bzl @@ -1,11 +1,21 @@ """Provides a single point of control for rules_java inside Drake.""" load( - "@rules_java//java:defs.bzl", + "@rules_java//java:java_binary.bzl", _java_binary = "java_binary", +) +load( + "@rules_java//java:java_import.bzl", _java_import = "java_import", +) +load( + "@rules_java//java:java_library.bzl", _java_library = "java_library", ) +load( + "@rules_java//java/common:java_info.bzl", + _JavaInfo = "JavaInfo", +) def java_binary(name, **kwargs): _java_binary( @@ -24,3 +34,5 @@ def java_library(name, **kwargs): name = name, **kwargs ) + +JavaInfo = _JavaInfo diff --git a/tools/skylark/py.bzl b/tools/skylark/py.bzl index 7e5d37fc79d5..62b622bce599 100644 --- a/tools/skylark/py.bzl +++ b/tools/skylark/py.bzl @@ -2,6 +2,7 @@ load( "@rules_python//python:defs.bzl", + _PyInfo = "PyInfo", _py_binary = "py_binary", _py_library = "py_library", _py_test = "py_test", @@ -34,3 +35,5 @@ def py_test(name, *, data = None, **kwargs): data = _add_requirements(data), **kwargs ) + +PyInfo = _PyInfo diff --git a/tools/skylark/pybind.bzl b/tools/skylark/pybind.bzl index 3be795d84466..7fb31ed79259 100644 --- a/tools/skylark/pybind.bzl +++ b/tools/skylark/pybind.bzl @@ -1,7 +1,7 @@ load("@cc//:compiler.bzl", "COMPILER_ID") load("@python//:version.bzl", "PYTHON_EXTENSION_SUFFIX") load("//tools/install:install.bzl", "install") -load("//tools/skylark:cc.bzl", "cc_binary") +load("//tools/skylark:cc.bzl", "CcInfo", "cc_binary") load("//tools/skylark:drake_cc.bzl", "drake_cc_binary", "drake_cc_googletest") load("//tools/skylark:drake_py.bzl", "drake_py_library", "drake_py_test") load("//tools/skylark:py.bzl", "py_library") diff --git a/tools/skylark/sh.bzl b/tools/skylark/sh.bzl new file mode 100644 index 000000000000..0af36416b5fe --- /dev/null +++ b/tools/skylark/sh.bzl @@ -0,0 +1,16 @@ +"""Provides a single point of control for rules_shell inside Drake.""" + +load("@rules_shell//shell:sh_binary.bzl", _sh_binary = "sh_binary") +load("@rules_shell//shell:sh_test.bzl", _sh_test = "sh_test") + +def sh_binary(name, **kwargs): + _sh_binary( + name = name, + **kwargs + ) + +def sh_test(name, **kwargs): + _sh_test( + name = name, + **kwargs + ) diff --git a/tools/workspace/BUILD.bazel b/tools/workspace/BUILD.bazel index b304be958e2e..fd4200b05583 100644 --- a/tools/workspace/BUILD.bazel +++ b/tools/workspace/BUILD.bazel @@ -85,8 +85,10 @@ drake_py_test( "//tools/workspace/build_bazel_apple_support:repository.bzl", "//tools/workspace/platforms:repository.bzl", "//tools/workspace/rules_cc:repository.bzl", + "//tools/workspace/rules_java:repository.bzl", "//tools/workspace/rules_license:repository.bzl", "//tools/workspace/rules_rust:repository.bzl", + "//tools/workspace/rules_shell:repository.bzl", ], tags = ["lint"], deps = [ diff --git a/tools/workspace/default.bzl b/tools/workspace/default.bzl index dc489645a092..a4b36d5c8825 100644 --- a/tools/workspace/default.bzl +++ b/tools/workspace/default.bzl @@ -78,10 +78,12 @@ load("//tools/workspace/qdldl_internal:repository.bzl", "qdldl_internal_reposito load("//tools/workspace/qhull_internal:repository.bzl", "qhull_internal_repository") # noqa load("//tools/workspace/ros_xacro_internal:repository.bzl", "ros_xacro_internal_repository") # noqa load("//tools/workspace/rules_cc:repository.bzl", "rules_cc_repository") # noqa +load("//tools/workspace/rules_java:repository.bzl", "rules_java_repository") load("//tools/workspace/rules_license:repository.bzl", "rules_license_repository") # noqa load("//tools/workspace/rules_python:repository.bzl", "rules_python_repository") # noqa load("//tools/workspace/rules_rust:repository.bzl", "rules_rust_repository") load("//tools/workspace/rules_rust_tinyjson:repository.bzl", "rules_rust_tinyjson_repository") # noqa +load("//tools/workspace/rules_shell:repository.bzl", "rules_shell_repository") load("//tools/workspace/rust_toolchain:repository.bzl", "register_rust_toolchains", "rust_toolchain_repositories") # noqa load("//tools/workspace/scs_internal:repository.bzl", "scs_internal_repository") # noqa load("//tools/workspace/sdformat_internal:repository.bzl", "sdformat_internal_repository") # noqa @@ -123,6 +125,7 @@ REPOS_ALREADY_PROVIDED_BY_BAZEL_MODULES = [ "rules_license", "rules_python", "rules_rust", + "rules_shell", ] def add_default_repositories( @@ -301,6 +304,8 @@ def add_default_repositories( ros_xacro_internal_repository(name = "ros_xacro_internal", mirrors = mirrors) # noqa if "rules_cc" not in excludes: rules_cc_repository(name = "rules_cc", mirrors = mirrors) + if "rules_java" not in excludes: + rules_java_repository(name = "rules_java", mirrors = mirrors) if "rules_license" not in excludes: rules_license_repository(name = "rules_license", mirrors = mirrors) if "rules_python" not in excludes: @@ -311,6 +316,8 @@ def add_default_repositories( rules_rust_repository(name = "rules_rust", mirrors = mirrors) if "rules_rust_tinyjson" not in excludes: rules_rust_tinyjson_repository(name = "rules_rust_tinyjson", mirrors = mirrors) # noqa + if "rules_shell" not in excludes: + rules_shell_repository(name = "rules_shell", mirrors = mirrors) if "rust_toolchain" not in excludes: rust_toolchain_repositories(mirrors = mirrors, excludes = excludes) if "scs_internal" not in excludes: diff --git a/tools/workspace/gfortran/package.BUILD.bazel b/tools/workspace/gfortran/package.BUILD.bazel index 215c0a6e37c8..d9855f9bb177 100644 --- a/tools/workspace/gfortran/package.BUILD.bazel +++ b/tools/workspace/gfortran/package.BUILD.bazel @@ -1,6 +1,7 @@ # -*- bazel -*- load("@drake//tools/skylark:cc.bzl", "cc_library") +load("@drake//tools/skylark:sh.bzl", "sh_binary") load(":path.bzl", "LIBDIR") # libgfortran: GPL-3.0-or-later WITH GCC-exception-3.1. diff --git a/tools/workspace/java.bzl b/tools/workspace/java.bzl index 45511c6b76a4..36eb96c20e49 100644 --- a/tools/workspace/java.bzl +++ b/tools/workspace/java.bzl @@ -87,6 +87,7 @@ def drake_java_import( for x in mirrors.get("maven") ], jar_sha256 = maven_jar_sha256, + rule_load = """load("@rules_java//java/bazel/rules:bazel_java_import.bzl", "java_import")""", # noqa ) _internal_drake_java_import( name = name, diff --git a/tools/workspace/rules_java/BUILD.bazel b/tools/workspace/rules_java/BUILD.bazel new file mode 100644 index 000000000000..e9c64f198ee8 --- /dev/null +++ b/tools/workspace/rules_java/BUILD.bazel @@ -0,0 +1,9 @@ +load("//tools/lint:lint.bzl", "add_lint_tests") + +# Required for workspace_bzlmod_sync_test.py. +exports_files( + ["repository.bzl"], + visibility = ["//tools/workspace:__pkg__"], +) + +add_lint_tests() diff --git a/tools/workspace/rules_java/repository.bzl b/tools/workspace/rules_java/repository.bzl new file mode 100644 index 000000000000..fa564a773ee8 --- /dev/null +++ b/tools/workspace/rules_java/repository.bzl @@ -0,0 +1,25 @@ +load("//tools/workspace:github.bzl", "github_archive") + +# Note that we do NOT install a LICENSE file as part of the Drake install +# because this repository is required only when building and testing with +# Bazel. + +def rules_java_repository( + name, + mirrors = None): + if native.bazel_version[0:2] == "7.": + # The new rules_java only works with Bazel 8; for bazel 7 we'll use the + # built-in rules_java. We can remove this once Drake's minimum Bazel + # version is >= 8. + return + github_archive( + name = name, + repository = "bazelbuild/rules_java", # License: Apache-2.0, + upgrade_advice = """ + When updating, you must also manually propagate to the new version + number into the MODULE.bazel file (at the top level of Drake). + """, + commit = "8.6.1", + sha256 = "b2519fabcd360529071ade8732f208b3755489ed7668b118f8f90985c0e51324", # noqa + mirrors = mirrors, + ) diff --git a/tools/workspace/rules_shell/BUILD.bazel b/tools/workspace/rules_shell/BUILD.bazel new file mode 100644 index 000000000000..e9c64f198ee8 --- /dev/null +++ b/tools/workspace/rules_shell/BUILD.bazel @@ -0,0 +1,9 @@ +load("//tools/lint:lint.bzl", "add_lint_tests") + +# Required for workspace_bzlmod_sync_test.py. +exports_files( + ["repository.bzl"], + visibility = ["//tools/workspace:__pkg__"], +) + +add_lint_tests() diff --git a/tools/workspace/rules_shell/repository.bzl b/tools/workspace/rules_shell/repository.bzl new file mode 100644 index 000000000000..ee97ad8ff452 --- /dev/null +++ b/tools/workspace/rules_shell/repository.bzl @@ -0,0 +1,20 @@ +load("//tools/workspace:github.bzl", "github_archive") + +# Note that we do NOT install a LICENSE file as part of the Drake install +# because this repository is required only when building and testing with +# Bazel. + +def rules_shell_repository( + name, + mirrors = None): + github_archive( + name = name, + repository = "bazelbuild/rules_shell", # License: Apache-2.0, + upgrade_advice = """ + When updating, you must also manually propagate to the new version + number into the MODULE.bazel file (at the top level of Drake). + """, + commit = "v0.3.0", + sha256 = "d8cd4a3a91fc1dc68d4c7d6b655f09def109f7186437e3f50a9b60ab436a0c53", # noqa + mirrors = mirrors, + ) diff --git a/tools/workspace/vtk_internal/rules.bzl b/tools/workspace/vtk_internal/rules.bzl index 57a4d576bed5..051e732afeea 100644 --- a/tools/workspace/vtk_internal/rules.bzl +++ b/tools/workspace/vtk_internal/rules.bzl @@ -1,6 +1,6 @@ load("@vtk_internal//:modules.bzl", "MODULES", "PLATFORM") load("@vtk_internal//:settings.bzl", "MODULE_SETTINGS") -load("//tools/skylark:cc.bzl", "cc_library") +load("//tools/skylark:cc.bzl", "cc_library", "objc_library") load( "//tools/workspace:cmake_configure_file.bzl", "cmake_configure_files", @@ -145,7 +145,7 @@ def _vtk_cc_module_impl( # Deal with objc code. if PLATFORM["name"] != "linux" and srcs_objc_non_arc: objc_lib_name = "_" + module_name + "_objc" - native.objc_library( + objc_library( name = objc_lib_name, non_arc_srcs = srcs_objc_non_arc, hdrs = hdrs, diff --git a/tools/workspace/workspace_bzlmod_sync_test.py b/tools/workspace/workspace_bzlmod_sync_test.py index eef6cd4d7d67..e2a427c45e6a 100644 --- a/tools/workspace/workspace_bzlmod_sync_test.py +++ b/tools/workspace/workspace_bzlmod_sync_test.py @@ -42,6 +42,8 @@ def _parse_repo_rule_version(self, content): if not line.startswith("commit = "): continue _, version, _ = line.split('"') + if version.startswith("v"): + version = version[1:] return version self.fail(f"No 'commit = ...' found in:\n{content}") @@ -63,7 +65,6 @@ def test_version_sync(self): # Don't check modules that are known to be module-only. del modules["bazel_features"] - del modules["rules_java"] # Don't check module that are documented to purposefully skew versions. del modules["rules_python"]