mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
* [bazel] Package headers in ntcoreffi correctly The original package includes headers from ntcore and wpiutil, so include those too. * Merge in new 2027
761 lines
28 KiB
Python
761 lines
28 KiB
Python
load("@build_bazel_apple_support//rules:universal_binary.bzl", "universal_binary")
|
|
load("@rules_cc//cc:action_names.bzl", "CPP_LINK_STATIC_LIBRARY_ACTION_NAME", "OBJ_COPY_ACTION_NAME", "STRIP_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")
|
|
load("@rules_pkg//:mappings.bzl", "pkg_files")
|
|
load("@rules_pkg//:pkg.bzl", "pkg_zip")
|
|
load("//shared/bazel/rules/gen:defs.bzl", "gen_versionscript")
|
|
|
|
# Copied from bazel since it isn't exposed publicly that I can find.
|
|
# https://github.com/bazelbuild/bazel/blob/cc4e3b25a89cd8294406d9489ece706cfcc019bd/src/main/starlark/builtins_bzl/common/cc/cc_helper.bzl#L272
|
|
def generate_def_file(ctx, def_parser, object_files, dll_name):
|
|
def_file = ctx.actions.declare_file(ctx.label.name + ".gen.def")
|
|
|
|
args = ctx.actions.args()
|
|
args.add(def_file)
|
|
args.add(dll_name)
|
|
argv = ctx.actions.args()
|
|
argv.use_param_file("@%s", use_always = True)
|
|
argv.set_param_file_format("shell")
|
|
for object_file in object_files:
|
|
argv.add(object_file.path)
|
|
|
|
ctx.actions.run(
|
|
mnemonic = "DefParser",
|
|
executable = def_parser,
|
|
toolchain = None,
|
|
arguments = [args, argv],
|
|
inputs = object_files,
|
|
outputs = [def_file],
|
|
use_default_shell_env = True,
|
|
)
|
|
return def_file
|
|
|
|
def _split_debug_symbols_impl(ctx):
|
|
"""This splits debug symbols out from the main shared library where supported.
|
|
|
|
WPILIB doesn't split them out for osx or Windows, so just pass them through.
|
|
For some builds, like for the systemcore, we don't want them split.
|
|
|
|
Args:
|
|
copy: If true, pass the file right on through, though make sure the name
|
|
is right.
|
|
use_debug_name: If true, the file should be named 'libfood.so' when done
|
|
rather than 'libfoo.so'. This only makes sense on Linux.
|
|
shared_library: The library to split apart.
|
|
"""
|
|
|
|
label = ctx.attr.shared_library.label
|
|
target_name = label.name
|
|
if label.package:
|
|
target_name = label.package + "/" + label.name
|
|
folder, lib_name = _folder_prefix(target_name)
|
|
|
|
# For Windows and OSX, we just want to pass it all on through. Don't be clever.
|
|
if (ctx.target_platform_has_constraint(ctx.attr._darwin_constraint[platform_common.ConstraintValueInfo]) or
|
|
ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])):
|
|
files = ctx.attr.shared_library[OutputGroupInfo].main_shared_library_output
|
|
return [
|
|
DefaultInfo(files = files),
|
|
OutputGroupInfo(
|
|
default = files,
|
|
),
|
|
]
|
|
|
|
# Linux
|
|
debug_suffix = "d" if ctx.attr.use_debug_name else ""
|
|
|
|
if not ctx.target_platform_has_constraint(ctx.attr._linux_constraint[platform_common.ConstraintValueInfo]):
|
|
fail("Unsupported platform")
|
|
|
|
lib = ctx.actions.declare_file(folder + "/split/lib" + lib_name + debug_suffix + ".so")
|
|
|
|
if ctx.attr.copy:
|
|
files = ctx.attr.shared_library[OutputGroupInfo].main_shared_library_output.to_list()
|
|
if len(files) != 1:
|
|
fail("Wrong number of files", files)
|
|
|
|
ctx.actions.run_shell(
|
|
command = " ".join([
|
|
"cp",
|
|
files[0].path,
|
|
lib.path,
|
|
]),
|
|
inputs = depset(
|
|
direct = files,
|
|
),
|
|
outputs = [lib],
|
|
)
|
|
|
|
return [
|
|
DefaultInfo(files = depset([lib])),
|
|
OutputGroupInfo(
|
|
default = depset([lib]),
|
|
),
|
|
]
|
|
else:
|
|
debug = ctx.actions.declare_file(folder + "/split/lib" + lib_name + debug_suffix + ".so.debug")
|
|
cc_toolchain = find_cpp_toolchain(ctx)
|
|
|
|
feature_configuration = cc_common.configure_features(
|
|
ctx = ctx,
|
|
cc_toolchain = cc_toolchain,
|
|
requested_features = ctx.features,
|
|
unsupported_features = ctx.disabled_features,
|
|
)
|
|
|
|
objcopy = cc_common.get_tool_for_action(
|
|
feature_configuration = feature_configuration,
|
|
action_name = OBJ_COPY_ACTION_NAME,
|
|
)
|
|
|
|
strip = cc_common.get_tool_for_action(
|
|
feature_configuration = feature_configuration,
|
|
action_name = STRIP_ACTION_NAME,
|
|
)
|
|
|
|
# This is the set of commands we want to implement to strip debug symbols out and link them back together:
|
|
# objcopy --only-keep-debug libmy-library.so libmy-library.so.debug
|
|
# strip --strip-debug libmy-library.so
|
|
# objcopy --strip-debug libmy-library.so
|
|
|
|
files = ctx.attr.shared_library[OutputGroupInfo].main_shared_library_output.to_list()
|
|
if len(files) != 1:
|
|
fail("Wrong number of files", files)
|
|
shared_library = files[0]
|
|
|
|
ctx.actions.run_shell(
|
|
command = " ".join([
|
|
"cp",
|
|
shared_library.path,
|
|
lib.path,
|
|
"&& chmod u+w",
|
|
lib.path,
|
|
"&&",
|
|
objcopy,
|
|
"--only-keep-debug",
|
|
lib.path,
|
|
debug.path,
|
|
"&&",
|
|
strip,
|
|
"--strip-debug",
|
|
lib.path,
|
|
"&&",
|
|
objcopy,
|
|
"--strip-debug",
|
|
lib.path,
|
|
]),
|
|
inputs = depset(
|
|
direct = files,
|
|
transitive = [
|
|
cc_toolchain.all_files,
|
|
],
|
|
),
|
|
outputs = [lib, debug],
|
|
)
|
|
|
|
return [
|
|
DefaultInfo(files = depset([lib, debug])),
|
|
OutputGroupInfo(
|
|
default = depset([lib, debug]),
|
|
),
|
|
]
|
|
|
|
_split_debug_symbols = rule(
|
|
implementation = _split_debug_symbols_impl,
|
|
attrs = {
|
|
"copy": attr.bool(mandatory = True),
|
|
"shared_library": attr.label(mandatory = True),
|
|
"use_debug_name": attr.bool(mandatory = True),
|
|
"_darwin_constraint": attr.label(default = "@platforms//os:osx"),
|
|
"_linux_constraint": attr.label(default = "@platforms//os:linux"),
|
|
"_windows_constraint": attr.label(default = "@platforms//os:windows"),
|
|
} | CC_TOOLCHAIN_ATTRS,
|
|
fragments = ["cpp"],
|
|
toolchains = use_cc_toolchain(),
|
|
)
|
|
|
|
def _folder_prefix(name):
|
|
if "/" in name:
|
|
last_slash = name.rfind("/")
|
|
return (name[0:last_slash], name[last_slash + 1:])
|
|
else:
|
|
return ("", name)
|
|
|
|
def third_party_cc_lib_helper(
|
|
name,
|
|
include_root,
|
|
src_root = None,
|
|
src_excludes = [],
|
|
defines = [],
|
|
visibility = None):
|
|
"""
|
|
Helper for src / headers pairs that aren't directly compiled, but rather pulled into a bigger library.
|
|
|
|
Due to allwpilibs directory structure of includes and sources living next to eachother, it often is required
|
|
to make a header shim to deal with the include path, and a filegroup of the sources. This pattern is extermely
|
|
common for the thirdparty libraries that live beneath certain libraries.
|
|
|
|
This will produce a library shim with the include path stripped, a filegroup of sources, and packages that can be
|
|
used to downstream to zip headers / sources with their "parent" library.
|
|
|
|
Params
|
|
include_root: The package relative path to the header files. This will be used to glob the files and strip the include prefix
|
|
src_root: Optional. The package relative path to the source files.
|
|
src_excludes: Optional. Used to exclude files from the src_root glob
|
|
visibilty: The visibility of header shim / source files / package files
|
|
"""
|
|
cc_library(
|
|
name = name + "-headers",
|
|
hdrs = native.glob([
|
|
include_root + "/**",
|
|
]),
|
|
includes = [include_root],
|
|
defines = defines,
|
|
strip_include_prefix = include_root,
|
|
visibility = visibility,
|
|
)
|
|
|
|
pkg_files(
|
|
name = name + "-hdrs-pkg",
|
|
srcs = native.glob([include_root + "/**"]),
|
|
strip_prefix = include_root,
|
|
visibility = visibility,
|
|
)
|
|
|
|
if src_root:
|
|
native.filegroup(
|
|
name = name + "-srcs",
|
|
srcs = native.glob([src_root + "/**"], exclude = src_excludes),
|
|
visibility = visibility,
|
|
)
|
|
|
|
pkg_files(
|
|
name = name + "-srcs-pkg",
|
|
srcs = native.glob([src_root + "/**"]),
|
|
strip_prefix = src_root,
|
|
)
|
|
|
|
def wpilib_cc_library(
|
|
name,
|
|
srcs = [],
|
|
hdrs = [],
|
|
deps = [],
|
|
copts = [],
|
|
third_party_libraries = [],
|
|
third_party_header_only_libraries = [],
|
|
extra_src_pkg_files = [],
|
|
extra_hdr_pkg_files = [],
|
|
include_license_files = False,
|
|
srcs_pkg_root = "src/main/native/cpp",
|
|
hdrs_pkg_root = "src/main/native/include",
|
|
strip_include_prefix = None,
|
|
linkopts = None,
|
|
visibility = None,
|
|
**kwargs):
|
|
"""
|
|
This function is used to ease the creation of a cc_library with publishing given the standard allwpilib directory structure.
|
|
|
|
This will create a cc_library as well as automatically create header, source, and library artifacts that can be used for publishing. This
|
|
also provides some syntactic sugar for third party library shims declared by third_party_cc_lib_helper.
|
|
|
|
Important outputs:
|
|
":name" - The cc_library
|
|
name + "-srcs-zip" - A zip file containing all the exported sources
|
|
name + "-hdrs-zip" - A zip file containing all the exported headers
|
|
name + "-zip" - A zip file that contains the compiled library
|
|
|
|
Params:
|
|
srcs: The sources used to compile the library. Note: This may be platform dependent and not include all the sources of the library for packaging
|
|
hdrs: The headers used to compile the library. Note: This may be platform dependent and not include all the sources of the library for packaging
|
|
third_party_libraries: These are helper dependencies, created by third_party_cc_lib_helper. Header shims will be added as deps and src filegroups will be added to srcs
|
|
third_party_header_only_libraries: Similar to third_party_libraries, but for shims that contain no sources
|
|
extra_src_pkg_files: Extra pkg_files to add to the source bundle. This is useful in the event that a library is complicated and requires
|
|
extra, customized sources to be added to the published zip file
|
|
extra_hdr_pkg_files: Extra pkg_files to add to the headers bundle. This is useful in the event that a library is complicated and requires
|
|
extra, customized headers to be added to the published zip file
|
|
include_license_files: If the header / source / library zip files should automatically includes the license files. This is used to maintain
|
|
consistency with the gradle publishing, as not all of them export the license files.
|
|
"""
|
|
maybe_license_pkg = ["//:license_pkg_files"] if include_license_files else []
|
|
|
|
cc_library(
|
|
name = name + "-headers",
|
|
hdrs = hdrs,
|
|
deps = [lib + "-headers" for lib in third_party_libraries + third_party_header_only_libraries],
|
|
strip_include_prefix = strip_include_prefix,
|
|
visibility = visibility,
|
|
**kwargs
|
|
)
|
|
|
|
cc_library(
|
|
name = name,
|
|
hdrs = hdrs,
|
|
copts = copts,
|
|
srcs = srcs + [lib + "-srcs" for lib in third_party_libraries],
|
|
deps = deps + [lib + "-headers" for lib in third_party_libraries + third_party_header_only_libraries],
|
|
strip_include_prefix = strip_include_prefix,
|
|
linkopts = linkopts,
|
|
visibility = visibility,
|
|
**kwargs
|
|
)
|
|
|
|
if srcs_pkg_root:
|
|
pkg_files(
|
|
name = name + "-srcs-pkg",
|
|
srcs = native.glob([srcs_pkg_root + "/**"]),
|
|
strip_prefix = srcs_pkg_root,
|
|
)
|
|
|
|
pkg_zip(
|
|
name = name + "-srcs-zip",
|
|
srcs = maybe_license_pkg + extra_src_pkg_files + [name + "-srcs-pkg"] + [lib + "-srcs-pkg" for lib in third_party_libraries],
|
|
tags = ["manual"],
|
|
)
|
|
|
|
if hdrs_pkg_root:
|
|
pkg_files(
|
|
name = name + "-hdrs-pkg",
|
|
srcs = native.glob([hdrs_pkg_root + "/**"]),
|
|
strip_prefix = hdrs_pkg_root,
|
|
visibility = visibility,
|
|
)
|
|
|
|
pkg_zip(
|
|
name = name + "-hdrs-zip",
|
|
srcs = extra_hdr_pkg_files + maybe_license_pkg + [name + "-hdrs-pkg"] + [lib + "-hdrs-pkg" for lib in third_party_libraries + third_party_header_only_libraries],
|
|
tags = ["manual"],
|
|
)
|
|
|
|
def wpilib_cc_shared_library(
|
|
name,
|
|
auto_export_windows_symbols = True,
|
|
user_link_flags = None,
|
|
visibility = None,
|
|
use_debug_name = True,
|
|
features = None,
|
|
win_def_file = None,
|
|
symbols = None,
|
|
additional_linker_inputs = None,
|
|
**kwargs):
|
|
"""Builds a cc_shared_library with some wpilib conventions applied.
|
|
|
|
The main workhorse of this rule is cc_shared_library and a pkg_files on the
|
|
back end to collect up the outputs. wpilib has some extra conventions we
|
|
can commonalize.
|
|
|
|
Args:
|
|
auto_export_windows_symbols: If true, export all the symbols found in the
|
|
shared library on Windows.
|
|
user_link_flags: User link flags to add to the linking process. Note:
|
|
this gets augmented with extra flags to produce libfoo.so
|
|
or libfood.so if in debug mode.
|
|
additional_linker_inputs: Additional inputs to provide to the linking process.
|
|
use_debug_name: If true, (default): when in debug mode, produce
|
|
libfood.so, otherwise produce libfoo.so. This matches the
|
|
wpilib convention for debug library naming. JNI libraries
|
|
though want to be loaded with the same name for all builds,
|
|
which necesitates turning this off.
|
|
win_def_file: The .def file used to specify symbols used in linking on
|
|
Windows. This is selected automatically such that it is
|
|
only used on Windows.
|
|
symbols: The symbols to export in the shared library.
|
|
"""
|
|
|
|
folder, lib = _folder_prefix(name)
|
|
|
|
if not features:
|
|
features = []
|
|
|
|
if symbols:
|
|
if win_def_file:
|
|
fail("Can't specify symbols and win_def_file")
|
|
|
|
exports_target = name + "_exports"
|
|
gen_versionscript(
|
|
name = exports_target,
|
|
src = symbols,
|
|
lib_name = lib,
|
|
format = select({
|
|
"@platforms//os:linux": "linux",
|
|
"@platforms//os:osx": "osx",
|
|
"@platforms//os:windows": "windows",
|
|
}),
|
|
)
|
|
|
|
additional_linker_inputs = (additional_linker_inputs or []) + select({
|
|
"@platforms//os:windows": [],
|
|
"//conditions:default": [exports_target],
|
|
})
|
|
user_link_flags = (user_link_flags or []) + select({
|
|
"@platforms//os:linux": ["-Wl,--version-script,$(location " + exports_target + ")"],
|
|
"@platforms//os:osx": ["-Wl,-exported_symbols_list,$(location " + exports_target + ")"],
|
|
"@platforms//os:windows": [],
|
|
})
|
|
win_def_file = exports_target
|
|
|
|
if auto_export_windows_symbols:
|
|
features.append("windows_export_all_symbols")
|
|
|
|
if use_debug_name:
|
|
user_link_flags = (user_link_flags or []) + select({
|
|
"//shared/bazel/rules:linux_compilation_mode_dbg": ["-Wl,-soname,lib" + lib + "d.so"],
|
|
"//shared/bazel/rules:osx_compilation_mode_dbg": ["-Wl,-install_name,lib" + lib + "d.so"],
|
|
"@platforms//os:linux": ["-Wl,-soname,lib" + lib + ".so"],
|
|
"@platforms//os:osx": ["-Wl,-install_name,lib" + lib + ".so"],
|
|
"//conditions:default": [],
|
|
})
|
|
else:
|
|
user_link_flags = (user_link_flags or []) + select({
|
|
"@platforms//os:linux": ["-Wl,-soname,lib" + lib + ".so"],
|
|
"@platforms//os:osx": ["-Wl,-install_name,lib" + lib + ".so"],
|
|
"//conditions:default": [],
|
|
})
|
|
|
|
cc_shared_library(
|
|
name = name,
|
|
user_link_flags = user_link_flags,
|
|
features = features,
|
|
visibility = visibility,
|
|
additional_linker_inputs = additional_linker_inputs,
|
|
# Only include a .def file on windows. This makes it so we can mark
|
|
# the .def file as only compatible with windows.
|
|
win_def_file = select({
|
|
"@platforms//os:windows": win_def_file,
|
|
"//conditions:default": None,
|
|
}),
|
|
**kwargs
|
|
)
|
|
|
|
universal_name = "universal/lib" + lib + ".lib"
|
|
universal_binary(
|
|
name = universal_name,
|
|
binary = name,
|
|
target_compatible_with = [
|
|
"@platforms//os:osx",
|
|
],
|
|
)
|
|
|
|
_split_debug_symbols(
|
|
name = name + "-symbolsplit",
|
|
copy = select({
|
|
"@rules_bzlmodrio_toolchains//conditions:linux_arm64": False,
|
|
"@rules_bzlmodrio_toolchains//conditions:linux_x86_64": True,
|
|
"//conditions:default": True,
|
|
}),
|
|
use_debug_name = select({
|
|
"//shared/bazel/rules:compilation_mode_dbg": True,
|
|
"//conditions:default": False,
|
|
}) if use_debug_name else False,
|
|
shared_library = name,
|
|
)
|
|
|
|
pkg_files(
|
|
name = folder + "/lib" + lib + "-shared-files",
|
|
srcs = select({
|
|
"@rules_bzlmodrio_toolchains//conditions:osx": [universal_name],
|
|
"//conditions:default": [
|
|
":" + name + "-symbolsplit",
|
|
],
|
|
}),
|
|
strip_prefix = select({
|
|
"@rules_bzlmodrio_toolchains//conditions:osx": "universal",
|
|
"//conditions:default": None,
|
|
}),
|
|
visibility = visibility,
|
|
)
|
|
|
|
CcStaticLibraryInfo = provider(
|
|
"Information about a cc static library.",
|
|
fields = {
|
|
"linker_input": "the resulting linker input artifact for the static library",
|
|
"used_objects": "the object files already accounted for",
|
|
},
|
|
)
|
|
|
|
def _accumulate_used_objects(ctx):
|
|
transitive_used_objects = []
|
|
for dep in ctx.attr.static_deps:
|
|
transitive_used_objects.append(dep[CcStaticLibraryInfo].used_objects)
|
|
|
|
return transitive_used_objects
|
|
|
|
def _filter_inputs(
|
|
ctx,
|
|
feature_configuration,
|
|
cc_toolchain,
|
|
deps,
|
|
used_objects):
|
|
dependency_linker_inputs_sets = []
|
|
for dep in deps:
|
|
dependency_linker_inputs_sets.append(dep[CcInfo].linking_context.linker_inputs)
|
|
|
|
dependency_linker_inputs = depset(transitive = dependency_linker_inputs_sets, order = "topological").to_list()
|
|
|
|
used_objects_depset = depset(transitive = used_objects, order = "topological").to_list()
|
|
|
|
linker_inputs = []
|
|
for linker_input in dependency_linker_inputs:
|
|
for lib in linker_input.libraries:
|
|
if lib.pic_objects:
|
|
for o in lib.pic_objects:
|
|
if o not in used_objects_depset:
|
|
linker_inputs.append(o)
|
|
elif lib.objects:
|
|
for o in lib.objects:
|
|
if o not in used_objects_depset:
|
|
linker_inputs.append(o)
|
|
|
|
return sorted(linker_inputs)
|
|
|
|
def _cc_static_library_impl(ctx):
|
|
"""
|
|
This is a modified version of built in cc_static_library implementation
|
|
https://github.com/bazelbuild/bazel/blob/8.2.1/src/main/starlark/builtins_bzl/common/cc/experimental_cc_static_library.bzl
|
|
|
|
The built in version amalgamates all of the transative dependency objects into a single shared library. However, we do not want our
|
|
static libraries to only have the symbols related to the objects for this library, and not anything transative. In order to do this,
|
|
we add the option to specify transative static_libraries. The rule then filters out the objects that are defines in the other static
|
|
libraries.
|
|
"""
|
|
deps = ctx.attr.deps
|
|
|
|
cc_toolchain = find_cpp_toolchain(ctx)
|
|
feature_configuration = cc_common.configure_features(
|
|
ctx = ctx,
|
|
cc_toolchain = cc_toolchain,
|
|
requested_features = ctx.features + ["force_no_whole_archive"],
|
|
unsupported_features = ctx.disabled_features,
|
|
)
|
|
|
|
# Find all the objects which are already in another static library.
|
|
used_objects = _accumulate_used_objects(ctx)
|
|
|
|
# Now, find the ones we depend on which aren't.
|
|
libs = _filter_inputs(
|
|
ctx,
|
|
feature_configuration,
|
|
cc_toolchain,
|
|
deps,
|
|
used_objects,
|
|
)
|
|
|
|
used_objects_depset = depset(direct = libs, transitive = used_objects, order = "topological")
|
|
|
|
# Generate the output library name if one isn't provided.
|
|
output_file = ctx.actions.declare_file(ctx.attr.static_lib_name)
|
|
|
|
# And, now do it.
|
|
linker_input = cc_common.create_linker_input(
|
|
owner = ctx.label,
|
|
libraries = depset(direct = [
|
|
cc_common.create_library_to_link(
|
|
actions = ctx.actions,
|
|
feature_configuration = feature_configuration,
|
|
cc_toolchain = cc_toolchain,
|
|
static_library = output_file,
|
|
),
|
|
]),
|
|
)
|
|
compilation_context = cc_common.create_compilation_context()
|
|
linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linker_input], order = "topological"))
|
|
|
|
archiver_path = cc_common.get_tool_for_action(
|
|
feature_configuration = feature_configuration,
|
|
action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME,
|
|
)
|
|
archiver_variables = cc_common.create_link_variables(
|
|
feature_configuration = feature_configuration,
|
|
cc_toolchain = cc_toolchain,
|
|
output_file = output_file.path,
|
|
is_using_linker = False,
|
|
)
|
|
command_line = cc_common.get_memory_inefficient_command_line(
|
|
feature_configuration = feature_configuration,
|
|
action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME,
|
|
variables = archiver_variables,
|
|
)
|
|
|
|
args = ctx.actions.args()
|
|
args.add_all(command_line)
|
|
args.add_all(libs)
|
|
|
|
if cc_common.is_enabled(
|
|
feature_configuration = feature_configuration,
|
|
feature_name = "archive_param_file",
|
|
):
|
|
# TODO: The flag file arg should come from the toolchain instead.
|
|
args.use_param_file("@%s", use_always = True)
|
|
|
|
env = cc_common.get_environment_variables(
|
|
feature_configuration = feature_configuration,
|
|
action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME,
|
|
variables = archiver_variables,
|
|
)
|
|
|
|
ctx.actions.run(
|
|
executable = archiver_path,
|
|
arguments = [args],
|
|
env = env,
|
|
inputs = depset(
|
|
direct = libs,
|
|
transitive = [
|
|
cc_toolchain.all_files,
|
|
],
|
|
),
|
|
outputs = [output_file],
|
|
)
|
|
|
|
cc_info = cc_common.merge_cc_infos(cc_infos = [
|
|
CcInfo(compilation_context = compilation_context, linking_context = linking_context),
|
|
] + [dep[CcInfo] for dep in ctx.attr.deps])
|
|
|
|
# TODO(austin): Do we want this to be able to link into a binary? Probably... Need to figure out what the right result needs to be for that.
|
|
|
|
return [
|
|
cc_info,
|
|
DefaultInfo(
|
|
files = depset([output_file]),
|
|
),
|
|
CcStaticLibraryInfo(
|
|
used_objects = used_objects_depset,
|
|
linker_input = linker_input,
|
|
),
|
|
]
|
|
|
|
_wpilib_cc_static_library = rule(
|
|
implementation = _cc_static_library_impl,
|
|
attrs = {
|
|
"deps": attr.label_list(
|
|
providers = [CcInfo],
|
|
doc = """
|
|
List of all the dependencies to accumulate objects from to link into this static library.
|
|
""",
|
|
),
|
|
"static_deps": attr.label_list(
|
|
providers = [CcStaticLibraryInfo],
|
|
doc = """
|
|
List of all static libraries to not duplicate .o files from.
|
|
""",
|
|
),
|
|
"static_lib_name": attr.string(doc = """
|
|
By default cc_static_library will use a name for the static library output file based on
|
|
the target's name and the platform. This includes an extension and sometimes a prefix.
|
|
Sometimes you may not want the default name, in which case you can use this
|
|
attribute to choose a custom name."""),
|
|
} | CC_TOOLCHAIN_ATTRS,
|
|
toolchains = use_cc_toolchain(),
|
|
fragments = ["cpp"],
|
|
)
|
|
|
|
def wpilib_cc_static_library(
|
|
name,
|
|
static_lib_name = None,
|
|
**kwargs):
|
|
if not static_lib_name:
|
|
folder, lib = _folder_prefix(name)
|
|
static_lib_name = select({
|
|
"//shared/bazel/rules:compilation_mode_dbg": folder + "/lib" + lib + "d.a",
|
|
"//shared/bazel/rules:compilation_mode_windows_dbg": folder + "/" + lib + ".lib",
|
|
"@platforms//os:windows": folder + "/" + lib + ".lib",
|
|
"//conditions:default": folder + "/lib" + lib + ".a",
|
|
})
|
|
|
|
_wpilib_cc_static_library(
|
|
name = name,
|
|
static_lib_name = static_lib_name,
|
|
**kwargs
|
|
)
|
|
|
|
def _generate_def_windows_impl(ctx):
|
|
# Generate the .def file for Windows. Do this by finding the .obj files
|
|
# specified, and then passing those into the def file generator.
|
|
deps = ctx.attr.deps
|
|
|
|
cc_toolchain = find_cpp_toolchain(ctx)
|
|
|
|
feature_configuration = cc_common.configure_features(
|
|
ctx = ctx,
|
|
cc_toolchain = cc_toolchain,
|
|
requested_features = ctx.features + ["force_no_whole_archive"],
|
|
unsupported_features = ctx.disabled_features,
|
|
)
|
|
|
|
def_parser = ctx.file._def_parser
|
|
win_def_file = []
|
|
|
|
if cc_common.is_enabled(feature_configuration = feature_configuration, feature_name = "targets_windows"):
|
|
object_files = []
|
|
|
|
# Now, hunt down all the linker inputs directly specified.
|
|
for dep in deps:
|
|
linker_input = dep[CcInfo].linking_context.linker_inputs
|
|
|
|
for l in linker_input.to_list():
|
|
# Find the linker stanza owned directly by the dependency, not transitively
|
|
if l.owner != dep.label:
|
|
continue
|
|
|
|
# Grab all the .o's out of it.
|
|
for library in l.libraries:
|
|
if library.pic_static_library != None:
|
|
if library.pic_objects != None:
|
|
object_files.extend(library.pic_objects)
|
|
elif library.static_library != None:
|
|
if library.objects != None:
|
|
object_files.extend(library.objects)
|
|
|
|
# Filter the list so we only generate def files for the provided dependencies.
|
|
filtered_object_files = []
|
|
for o in object_files:
|
|
for f in ctx.attr.filters:
|
|
if f in o.path:
|
|
filtered_object_files.append(o)
|
|
break
|
|
|
|
if def_parser != None:
|
|
generated_def_file = generate_def_file(ctx, def_parser, filtered_object_files, ctx.label.name)
|
|
|
|
win_def_file = [generated_def_file]
|
|
|
|
files = depset(direct = win_def_file)
|
|
return [
|
|
DefaultInfo(files = files),
|
|
OutputGroupInfo(default = files),
|
|
]
|
|
|
|
_generate_def_windows = rule(
|
|
implementation = _generate_def_windows_impl,
|
|
attrs = {
|
|
"deps": attr.label_list(
|
|
providers = [CcInfo],
|
|
doc = """
|
|
List of all static libraries to not duplicate .o files from.
|
|
""",
|
|
),
|
|
"filters": attr.string_list(),
|
|
"_def_parser": attr.label(default = "@bazel_tools//tools/def_parser:def_parser", allow_single_file = True, cfg = "exec"),
|
|
} | CC_TOOLCHAIN_ATTRS,
|
|
toolchains = use_cc_toolchain(),
|
|
fragments = ["cpp"],
|
|
)
|
|
|
|
def generate_def_windows(name, deps = None, **kwargs):
|
|
"""Generates a .def file for linking a windows .dll for the provided cc_library and filters
|
|
|
|
Args:
|
|
deps: A list of cc_libraries to export symbols from.
|
|
filters: All object files in the provided cc_libraries (but not their
|
|
dependencies) are checked against this list. If a string in
|
|
this list appears inside the name of the object file, it is
|
|
added to the export list.
|
|
"""
|
|
_generate_def_windows(
|
|
name = name,
|
|
deps = deps,
|
|
target_compatible_with = ["@platforms//os:windows"],
|
|
**kwargs
|
|
)
|