xref: /llvm-project/utils/bazel/llvm-project-overlay/llvm/cc_plugin_library.bzl (revision 5e57f1bf52834cd5133011624c9bbc8cbf58c272)
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