1# This file is licensed under the Apache License v2.0 with LLVM Exceptions. 2# See https://llvm.org/LICENSE.txt for license information. 3# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 5"""A macro to produce a loadable plugin library for the target OS. 6 7This macro produces a set of platform-specific `cc_binary` rules, by appending 8the platform suffix (`.dll`, `.dylib`, or `.so`) to the provided `name`. It then 9connects these to a `cc_import` rule with `name` exactly and `hdrs` that can be 10used by other Bazel rules to depend on the plugin library. 11 12The `srcs` attribute for the `cc_binary` rules is `srcs + hdrs`. Other explicit 13arguments are passed to all of the rules where they apply, and can be used to 14configure generic aspects of all generated rules such as `testonly`. Lastly, 15`kwargs` is expanded into all the `cc_binary` rules. 16""" 17 18load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_import", "cc_library") 19 20def cc_plugin_library(name, srcs, hdrs, include_prefix = None, strip_include_prefix = None, alwayslink = False, features = [], tags = [], testonly = False, **kwargs): 21 # Neither the name of the plugin binary nor tags on whether it is built are 22 # configurable. Instead, we build a `cc_binary` with each name and 23 # selectively depend on them based on platform. 24 # 25 # All-in-all, this is a pretty poor workaround. I think this is part of the 26 # Bazel issue: https://github.com/bazelbuild/bazel/issues/7538 27 so_name = name + ".so" 28 dll_name = name + ".dll" 29 dylib_name = name + ".dylib" 30 interface_output_name = name + "_interface_output" 31 import_name = name + "_import" 32 for impl_name in [dll_name, dylib_name, so_name]: 33 cc_binary( 34 name = impl_name, 35 srcs = srcs + hdrs, 36 linkshared = True, 37 linkstatic = True, 38 features = features, 39 tags = ["manual"] + tags, 40 testonly = testonly, 41 **kwargs 42 ) 43 native.filegroup( 44 name = interface_output_name, 45 srcs = select({ 46 "@platforms//os:windows": [":" + dll_name], 47 "@platforms//os:macos": [":" + dylib_name], 48 "//conditions:default": [":" + so_name], 49 }), 50 output_group = "interface_library", 51 ) 52 cc_import( 53 name = import_name, 54 interface_library = ":" + interface_output_name, 55 shared_library = select({ 56 "@platforms//os:windows": ":" + dll_name, 57 "@platforms//os:macos": ":" + dylib_name, 58 "//conditions:default": ":" + so_name, 59 }), 60 alwayslink = alwayslink, 61 features = features, 62 tags = tags, 63 testonly = testonly, 64 ) 65 cc_library( 66 name = name, 67 hdrs = hdrs, 68 include_prefix = include_prefix, 69 strip_include_prefix = strip_include_prefix, 70 deps = [":" + import_name], 71 alwayslink = alwayslink, 72 features = features, 73 tags = tags, 74 testonly = testonly, 75 ) 76