[bazel] Build a single maven artifact bundle (#8049)

Signed-off-by: Austin Schuh <austin.linux@gmail.com>
Co-authored-by: PJ Reiniger <pj.reiniger@gmail.com>
Co-authored-by: David Vo <auscompgeek@users.noreply.github.com>
This commit is contained in:
Austin Schuh
2025-07-22 13:26:20 -07:00
committed by GitHub
parent f3af50fc8e
commit 60098b0685
17 changed files with 930 additions and 136 deletions

View File

@@ -1,4 +1,6 @@
load("@build_bazel_apple_support//rules:universal_binary.bzl", "universal_binary")
load("@rules_cc//cc:action_names.bzl", "CPP_LINK_STATIC_LIBRARY_ACTION_NAME")
load("@rules_cc//cc:cc_shared_library.bzl", "cc_shared_library")
load("@rules_cc//cc:defs.bzl", "CcInfo", "cc_library")
load("@rules_cc//cc:find_cc_toolchain.bzl", "CC_TOOLCHAIN_ATTRS", "find_cpp_toolchain", "use_cc_toolchain")
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
@@ -153,26 +155,38 @@ def wpilib_cc_shared_library(
name,
auto_export_windows_symbols = True,
**kwargs):
folder, lib = _folder_prefix(name)
features = []
if auto_export_windows_symbols:
features.append("windows_export_all_symbols")
native.cc_shared_library(
cc_shared_library(
name = name,
features = features,
**kwargs
)
pkg_files(
name = name + "-shared.pkg",
srcs = [":" + name],
tags = ["manual"],
universal_name = "universal/lib" + lib + ".lib"
universal_binary(
name = universal_name,
binary = name,
target_compatible_with = [
"@platforms//os:osx",
],
)
pkg_zip(
name = name + "-shared-zip",
srcs = ["//:license_pkg_files", name + "-shared.pkg"],
tags = ["no-remote", "manual"],
pkg_files(
name = folder + "/lib" + lib + "-shared-files",
srcs = select({
"@rules_bzlmodrio_toolchains//conditions:osx": [universal_name],
"//conditions:default": [
":" + name,
],
}),
strip_prefix = select({
"@rules_bzlmodrio_toolchains//conditions:osx": "universal",
"//conditions:default": folder,
}),
)
CcStaticLibraryInfo = provider(

View File

@@ -1,6 +1,9 @@
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
load("@rules_cc//cc:defs.bzl", "cc_library")
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
load("@rules_java//java:defs.bzl", "java_library")
load("@rules_java//java/common:java_info.bzl", "JavaInfo")
load("@rules_pkg//:mappings.bzl", "filter_directory")
def _jni_headers_impl(ctx):

View File

@@ -0,0 +1,142 @@
"""Bazel rules for publishing maven artifacts."""
load("@bazel_skylib//rules:write_file.bzl", "write_file")
load("@com_wpilib_allwpilib_publishing_config//:publishing_config.bzl", "CLASSIFIER_FILTER")
load("@platforms//host:constraints.bzl", _host_constraints = "HOST_CONSTRAINTS")
load("@rules_jvm_external//:defs.bzl", "maven_export")
load("@rules_pkg//pkg:zip.bzl", "pkg_zip")
load("@rules_shell//shell:sh_binary.bzl", "sh_binary")
load("//shared/bazel/rules:transitions.bzl", "platform_transition_filegroup")
def _get_host_os():
if "@platforms//os:linux" in _host_constraints:
return "linux"
if "@platforms//os:osx" in _host_constraints:
return "osx"
if "@platforms//os:windows" in _host_constraints:
return "windows"
fail("Unsupported host OS. Must be one of linux, osx, or windows.")
HOST_OS = _get_host_os()
def publish_all(name, targets):
"""Macro to publish multiple maven artifacts with 1 call."""
publish_name = name + "_publish_all"
write_file(
name = publish_name,
out = publish_name + ".sh",
content = [
"#!/bin/bash",
"set -e",
"",
'for arg in "$@";',
"do",
' "$arg"',
"done",
],
)
sh_binary(
name = name,
srcs = [publish_name + ".sh"],
args = ["$(location " + x + ".publish)" for x in targets],
data = [x + ".publish" for x in targets],
)
# Unfortunately, rules_jvm_external really wants each of the classifier
# artifacts to have a unique name so they can go in the runfiles together and
# not collide.
def architectures_pkg_zip(
name,
compilation_modes = ["dbg", "opt"],
architectures = {
"@rules_bzlmodrio_toolchains//platforms/linux_x86_64": "linux-x86-64",
"@rules_bzlmodrio_toolchains//platforms/osx": "osxuniversal",
"@rules_bzlmodrio_toolchains//platforms/systemcore": "systemcore",
"@rules_bzlmodrio_toolchains//platforms/windows_arm64": "windows-arm64",
"@rules_bzlmodrio_toolchains//platforms/windows_x86_64": "windows-x86-64",
},
**kwargs):
architectures_target_compatible_with = {
"linux-x86-64": ["@platforms//os:linux"],
"osxuniversal": ["@platforms//os:osx"],
"systemcore": None,
"windows-arm64": ["@platforms//os:windows"],
"windows-x86-64": ["@platforms//os:windows"],
}
for compilation_mode in compilation_modes:
for platform, shortname in architectures.items():
zip_name = name + "-" + compilation_mode + "-arch-" + shortname
pkg_zip(
name = zip_name,
**kwargs
)
package_name = name + "-" + compilation_mode + "-" + shortname
platform_transition_filegroup(
name = package_name,
srcs = [":" + zip_name],
target_platform = platform,
compilation_mode = compilation_mode,
target_compatible_with = architectures_target_compatible_with[shortname],
)
def platform_prefix(t):
return select({
"@rules_bzlmodrio_toolchains//conditions:linux_x86_64": "linux/x86-64/" + t,
"@rules_bzlmodrio_toolchains//conditions:osx": "osx/universal/" + t,
"@rules_bzlmodrio_toolchains//conditions:windows_arm64": "windows/arm64/" + t,
"@rules_bzlmodrio_toolchains//conditions:windows_x86_64": "windows/x86-64/" + t,
"@rules_bzlmodrio_toolchains//constraints/is_roborio:roborio": "linux/roborio/" + t,
"@rules_bzlmodrio_toolchains//constraints/is_systemcore:systemcore": "linux/systemcore/" + t,
})
def _wpilib_maven_export_impl(
name,
maven_coordinates,
classifier_artifacts,
linux_artifacts,
osx_artifacts,
windows_artifacts,
lib_name = None,
visibility = None):
"""Implementation of wpilib_maven_export."""
all_artifacts = {}
all_artifacts.update(classifier_artifacts)
if HOST_OS == "linux":
all_artifacts.update(linux_artifacts)
elif HOST_OS == "osx":
all_artifacts.update(osx_artifacts)
elif HOST_OS == "windows":
all_artifacts.update(windows_artifacts)
if CLASSIFIER_FILTER:
allowed_classifiers = CLASSIFIER_FILTER.split(",")
filtered_artifacts = {
key: value
for key, value in all_artifacts.items()
if key in allowed_classifiers
}
else:
filtered_artifacts = all_artifacts
maven_export(
name = name,
maven_coordinates = maven_coordinates,
classifier_artifacts = filtered_artifacts,
lib_name = lib_name,
visibility = visibility,
)
wpilib_maven_export = macro(
implementation = _wpilib_maven_export_impl,
attrs = {
"classifier_artifacts": attr.string_keyed_label_dict(default = {}, configurable = False),
"lib_name": attr.string(configurable = False),
"linux_artifacts": attr.string_keyed_label_dict(default = {}, configurable = False),
"maven_coordinates": attr.string(mandatory = True, configurable = False),
"osx_artifacts": attr.string_keyed_label_dict(default = {}, configurable = False),
"windows_artifacts": attr.string_keyed_label_dict(default = {}, configurable = False),
},
doc = "A symbolic macro that wraps maven_export for wpilib.",
)

View File

@@ -0,0 +1,26 @@
# Copyright (c) FIRST and other WPILib contributors.
# Open Source Software; you can modify and/or share it under the terms of
# the WPILib BSD license file in the root directory of this project.
"""Bazel rule definition for publishing maven artifacts."""
def _publishing_repo_impl(repository_ctx):
"""Implementation of the publishing_repo rule."""
classifier_filter = repository_ctx.os.environ.get("WPI_PUBLISH_CLASSIFIER_FILTER", "")
content = """# Generated by publishing_repo rule. DO NOT EDIT.
CLASSIFIER_FILTER = "{classifier_filter}"
""".format(
classifier_filter = classifier_filter,
)
repository_ctx.file("publishing_config.bzl", content)
repository_ctx.file("BUILD.bazel", content = "# Generated file")
publishing_repo = repository_rule(
implementation = _publishing_repo_impl,
environ = ["WPI_PUBLISH_CLASSIFIER_FILTER"],
doc = "Repository rule to determine host OS and classifier filter for publishing. " +
"This rule must be instantiated in the WORKSPACE file with the name " +
"'com_wpilib_allwpilib_publishing_config'.",
)

View File

@@ -0,0 +1,54 @@
"Rules for working with transitions."
def _transition_platform_impl(_, attr):
return {
"//command_line_option:compilation_mode": attr.compilation_mode,
"//command_line_option:platforms": str(attr.target_platform),
}
# Transition from any input configuration to one that includes the
# --platforms command-line flag.
_transition_platform = transition(
implementation = _transition_platform_impl,
inputs = [],
outputs = [
"//command_line_option:platforms",
"//command_line_option:compilation_mode",
],
)
def _platform_transition_filegroup_impl(ctx):
files = []
runfiles = ctx.runfiles()
for src in ctx.attr.srcs:
files.append(src[DefaultInfo].files)
runfiles = runfiles.merge_all([src[DefaultInfo].default_runfiles for src in ctx.attr.srcs])
return [DefaultInfo(
files = depset(transitive = files),
runfiles = runfiles,
)]
platform_transition_filegroup = rule(
_platform_transition_filegroup_impl,
attrs = {
"compilation_mode": attr.string(
doc = "The compilation mode to transition the srcs.",
mandatory = True,
),
"srcs": attr.label_list(
allow_empty = False,
cfg = _transition_platform,
doc = "The input to be transitioned to the target platform.",
),
"target_platform": attr.label(
doc = "The target platform to transition the srcs.",
mandatory = True,
),
# Required to Opt-in to the transitions feature.
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
doc = "Transitions the srcs to use the provided platform. The filegroup will contain artifacts for the target platform.",
)