xref: /aosp_15_r20/external/protobuf/pkg/cc_dist_library.bzl (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1*1b3f573fSAndroid Build Coastguard Worker# Rules for distributable C++ libraries
2*1b3f573fSAndroid Build Coastguard Worker
3*1b3f573fSAndroid Build Coastguard Workerload("@rules_cc//cc:action_names.bzl", cc_action_names = "ACTION_NAMES")
4*1b3f573fSAndroid Build Coastguard Workerload("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain")
5*1b3f573fSAndroid Build Coastguard Worker
6*1b3f573fSAndroid Build Coastguard Worker# Creates an action to build the `output_file` static library (archive)
7*1b3f573fSAndroid Build Coastguard Worker# using `object_files`.
8*1b3f573fSAndroid Build Coastguard Workerdef _create_archive_action(
9*1b3f573fSAndroid Build Coastguard Worker        ctx,
10*1b3f573fSAndroid Build Coastguard Worker        feature_configuration,
11*1b3f573fSAndroid Build Coastguard Worker        cc_toolchain,
12*1b3f573fSAndroid Build Coastguard Worker        output_file,
13*1b3f573fSAndroid Build Coastguard Worker        object_files):
14*1b3f573fSAndroid Build Coastguard Worker    # Based on Bazel's src/main/starlark/builtins_bzl/common/cc/cc_import.bzl:
15*1b3f573fSAndroid Build Coastguard Worker
16*1b3f573fSAndroid Build Coastguard Worker    # Build the command line and add args for all of the input files:
17*1b3f573fSAndroid Build Coastguard Worker    archiver_variables = cc_common.create_link_variables(
18*1b3f573fSAndroid Build Coastguard Worker        feature_configuration = feature_configuration,
19*1b3f573fSAndroid Build Coastguard Worker        cc_toolchain = cc_toolchain,
20*1b3f573fSAndroid Build Coastguard Worker        output_file = output_file.path,
21*1b3f573fSAndroid Build Coastguard Worker        is_using_linker = False,
22*1b3f573fSAndroid Build Coastguard Worker    )
23*1b3f573fSAndroid Build Coastguard Worker    command_line = cc_common.get_memory_inefficient_command_line(
24*1b3f573fSAndroid Build Coastguard Worker        feature_configuration = feature_configuration,
25*1b3f573fSAndroid Build Coastguard Worker        action_name = cc_action_names.cpp_link_static_library,
26*1b3f573fSAndroid Build Coastguard Worker        variables = archiver_variables,
27*1b3f573fSAndroid Build Coastguard Worker    )
28*1b3f573fSAndroid Build Coastguard Worker    args = ctx.actions.args()
29*1b3f573fSAndroid Build Coastguard Worker    args.add_all(command_line)
30*1b3f573fSAndroid Build Coastguard Worker    args.add_all(object_files)
31*1b3f573fSAndroid Build Coastguard Worker    args.use_param_file("@%s", use_always = True)
32*1b3f573fSAndroid Build Coastguard Worker
33*1b3f573fSAndroid Build Coastguard Worker    archiver_path = cc_common.get_tool_for_action(
34*1b3f573fSAndroid Build Coastguard Worker        feature_configuration = feature_configuration,
35*1b3f573fSAndroid Build Coastguard Worker        action_name = cc_action_names.cpp_link_static_library,
36*1b3f573fSAndroid Build Coastguard Worker    )
37*1b3f573fSAndroid Build Coastguard Worker
38*1b3f573fSAndroid Build Coastguard Worker    env = cc_common.get_environment_variables(
39*1b3f573fSAndroid Build Coastguard Worker        feature_configuration = feature_configuration,
40*1b3f573fSAndroid Build Coastguard Worker        action_name = cc_action_names.cpp_link_static_library,
41*1b3f573fSAndroid Build Coastguard Worker        variables = archiver_variables,
42*1b3f573fSAndroid Build Coastguard Worker    )
43*1b3f573fSAndroid Build Coastguard Worker
44*1b3f573fSAndroid Build Coastguard Worker    ctx.actions.run(
45*1b3f573fSAndroid Build Coastguard Worker        executable = archiver_path,
46*1b3f573fSAndroid Build Coastguard Worker        arguments = [args],
47*1b3f573fSAndroid Build Coastguard Worker        env = env,
48*1b3f573fSAndroid Build Coastguard Worker        inputs = depset(
49*1b3f573fSAndroid Build Coastguard Worker            direct = object_files,
50*1b3f573fSAndroid Build Coastguard Worker            transitive = [
51*1b3f573fSAndroid Build Coastguard Worker                cc_toolchain.all_files,
52*1b3f573fSAndroid Build Coastguard Worker            ],
53*1b3f573fSAndroid Build Coastguard Worker        ),
54*1b3f573fSAndroid Build Coastguard Worker        use_default_shell_env = True,
55*1b3f573fSAndroid Build Coastguard Worker        outputs = [output_file],
56*1b3f573fSAndroid Build Coastguard Worker        mnemonic = "CppArchiveDist",
57*1b3f573fSAndroid Build Coastguard Worker    )
58*1b3f573fSAndroid Build Coastguard Worker
59*1b3f573fSAndroid Build Coastguard Worker# Implementation for cc_dist_library rule.
60*1b3f573fSAndroid Build Coastguard Workerdef _cc_dist_library_impl(ctx):
61*1b3f573fSAndroid Build Coastguard Worker    cc_toolchain_info = find_cc_toolchain(ctx)
62*1b3f573fSAndroid Build Coastguard Worker    if cc_toolchain_info.ar_executable == None:
63*1b3f573fSAndroid Build Coastguard Worker        return []
64*1b3f573fSAndroid Build Coastguard Worker
65*1b3f573fSAndroid Build Coastguard Worker    feature_configuration = cc_common.configure_features(
66*1b3f573fSAndroid Build Coastguard Worker        ctx = ctx,
67*1b3f573fSAndroid Build Coastguard Worker        cc_toolchain = cc_toolchain_info,
68*1b3f573fSAndroid Build Coastguard Worker    )
69*1b3f573fSAndroid Build Coastguard Worker
70*1b3f573fSAndroid Build Coastguard Worker    # Collect the set of object files from the immediate deps.
71*1b3f573fSAndroid Build Coastguard Worker
72*1b3f573fSAndroid Build Coastguard Worker    objs = []
73*1b3f573fSAndroid Build Coastguard Worker    pic_objs = []
74*1b3f573fSAndroid Build Coastguard Worker    for dep in ctx.attr.deps:
75*1b3f573fSAndroid Build Coastguard Worker        if CcInfo not in dep:
76*1b3f573fSAndroid Build Coastguard Worker            continue
77*1b3f573fSAndroid Build Coastguard Worker
78*1b3f573fSAndroid Build Coastguard Worker        link_ctx = dep[CcInfo].linking_context
79*1b3f573fSAndroid Build Coastguard Worker        if link_ctx == None:
80*1b3f573fSAndroid Build Coastguard Worker            continue
81*1b3f573fSAndroid Build Coastguard Worker
82*1b3f573fSAndroid Build Coastguard Worker        linker_inputs = link_ctx.linker_inputs.to_list()
83*1b3f573fSAndroid Build Coastguard Worker        for link_input in linker_inputs:
84*1b3f573fSAndroid Build Coastguard Worker            if link_input.owner != dep.label:
85*1b3f573fSAndroid Build Coastguard Worker                # This is a transitive dep: skip it.
86*1b3f573fSAndroid Build Coastguard Worker                continue
87*1b3f573fSAndroid Build Coastguard Worker
88*1b3f573fSAndroid Build Coastguard Worker            for lib in link_input.libraries:
89*1b3f573fSAndroid Build Coastguard Worker                objs.extend(lib.objects or [])
90*1b3f573fSAndroid Build Coastguard Worker                pic_objs.extend(lib.pic_objects or [])
91*1b3f573fSAndroid Build Coastguard Worker
92*1b3f573fSAndroid Build Coastguard Worker    # For static libraries, build separately with and without pic.
93*1b3f573fSAndroid Build Coastguard Worker
94*1b3f573fSAndroid Build Coastguard Worker    stemname = "lib" + ctx.label.name
95*1b3f573fSAndroid Build Coastguard Worker    outputs = []
96*1b3f573fSAndroid Build Coastguard Worker
97*1b3f573fSAndroid Build Coastguard Worker    if len(objs) > 0:
98*1b3f573fSAndroid Build Coastguard Worker        archive_out = ctx.actions.declare_file(stemname + ".a")
99*1b3f573fSAndroid Build Coastguard Worker        _create_archive_action(
100*1b3f573fSAndroid Build Coastguard Worker            ctx,
101*1b3f573fSAndroid Build Coastguard Worker            feature_configuration,
102*1b3f573fSAndroid Build Coastguard Worker            cc_toolchain_info,
103*1b3f573fSAndroid Build Coastguard Worker            archive_out,
104*1b3f573fSAndroid Build Coastguard Worker            objs,
105*1b3f573fSAndroid Build Coastguard Worker        )
106*1b3f573fSAndroid Build Coastguard Worker        outputs.append(archive_out)
107*1b3f573fSAndroid Build Coastguard Worker
108*1b3f573fSAndroid Build Coastguard Worker    if len(pic_objs) > 0:
109*1b3f573fSAndroid Build Coastguard Worker        pic_archive_out = ctx.actions.declare_file(stemname + ".pic.a")
110*1b3f573fSAndroid Build Coastguard Worker        _create_archive_action(
111*1b3f573fSAndroid Build Coastguard Worker            ctx,
112*1b3f573fSAndroid Build Coastguard Worker            feature_configuration,
113*1b3f573fSAndroid Build Coastguard Worker            cc_toolchain_info,
114*1b3f573fSAndroid Build Coastguard Worker            pic_archive_out,
115*1b3f573fSAndroid Build Coastguard Worker            pic_objs,
116*1b3f573fSAndroid Build Coastguard Worker        )
117*1b3f573fSAndroid Build Coastguard Worker        outputs.append(pic_archive_out)
118*1b3f573fSAndroid Build Coastguard Worker
119*1b3f573fSAndroid Build Coastguard Worker    # For dynamic libraries, use the `cc_common.link` command to ensure
120*1b3f573fSAndroid Build Coastguard Worker    # everything gets built correctly according to toolchain definitions.
121*1b3f573fSAndroid Build Coastguard Worker
122*1b3f573fSAndroid Build Coastguard Worker    compilation_outputs = cc_common.create_compilation_outputs(
123*1b3f573fSAndroid Build Coastguard Worker        objects = depset(objs),
124*1b3f573fSAndroid Build Coastguard Worker        pic_objects = depset(pic_objs),
125*1b3f573fSAndroid Build Coastguard Worker    )
126*1b3f573fSAndroid Build Coastguard Worker    link_output = cc_common.link(
127*1b3f573fSAndroid Build Coastguard Worker        actions = ctx.actions,
128*1b3f573fSAndroid Build Coastguard Worker        feature_configuration = feature_configuration,
129*1b3f573fSAndroid Build Coastguard Worker        cc_toolchain = cc_toolchain_info,
130*1b3f573fSAndroid Build Coastguard Worker        compilation_outputs = compilation_outputs,
131*1b3f573fSAndroid Build Coastguard Worker        name = ctx.label.name,
132*1b3f573fSAndroid Build Coastguard Worker        output_type = "dynamic_library",
133*1b3f573fSAndroid Build Coastguard Worker        user_link_flags = ctx.attr.linkopts,
134*1b3f573fSAndroid Build Coastguard Worker    )
135*1b3f573fSAndroid Build Coastguard Worker    library_to_link = link_output.library_to_link
136*1b3f573fSAndroid Build Coastguard Worker
137*1b3f573fSAndroid Build Coastguard Worker    # Note: library_to_link.dynamic_library and interface_library are often
138*1b3f573fSAndroid Build Coastguard Worker    # symlinks in the solib directory. For DefaultInfo, prefer reporting
139*1b3f573fSAndroid Build Coastguard Worker    # the resolved artifact paths.
140*1b3f573fSAndroid Build Coastguard Worker    if library_to_link.resolved_symlink_dynamic_library != None:
141*1b3f573fSAndroid Build Coastguard Worker        outputs.append(library_to_link.resolved_symlink_dynamic_library)
142*1b3f573fSAndroid Build Coastguard Worker    elif library_to_link.dynamic_library != None:
143*1b3f573fSAndroid Build Coastguard Worker        outputs.append(library_to_link.dynamic_library)
144*1b3f573fSAndroid Build Coastguard Worker
145*1b3f573fSAndroid Build Coastguard Worker    if library_to_link.resolved_symlink_interface_library != None:
146*1b3f573fSAndroid Build Coastguard Worker        outputs.append(library_to_link.resolved_symlink_interface_library)
147*1b3f573fSAndroid Build Coastguard Worker    elif library_to_link.interface_library != None:
148*1b3f573fSAndroid Build Coastguard Worker        outputs.append(library_to_link.interface_library)
149*1b3f573fSAndroid Build Coastguard Worker
150*1b3f573fSAndroid Build Coastguard Worker    # We could expose the libraries for use from cc rules:
151*1b3f573fSAndroid Build Coastguard Worker    #
152*1b3f573fSAndroid Build Coastguard Worker    # linking_context = cc_common.create_linking_context(
153*1b3f573fSAndroid Build Coastguard Worker    #     linker_inputs = depset([
154*1b3f573fSAndroid Build Coastguard Worker    #         cc_common.create_linker_input(
155*1b3f573fSAndroid Build Coastguard Worker    #             owner = ctx.label,
156*1b3f573fSAndroid Build Coastguard Worker    #             libraries = depset([library_to_link]),
157*1b3f573fSAndroid Build Coastguard Worker    #         ),
158*1b3f573fSAndroid Build Coastguard Worker    #     ]),
159*1b3f573fSAndroid Build Coastguard Worker    # )
160*1b3f573fSAndroid Build Coastguard Worker    # cc_info = CcInfo(linking_context = linking_context)  # and return this
161*1b3f573fSAndroid Build Coastguard Worker    #
162*1b3f573fSAndroid Build Coastguard Worker    # However, if the goal is to force a protobuf dependency to use the
163*1b3f573fSAndroid Build Coastguard Worker    # DSO, then `cc_import` is a better-supported way to do so.
164*1b3f573fSAndroid Build Coastguard Worker    #
165*1b3f573fSAndroid Build Coastguard Worker    # If we wanted to expose CcInfo from this rule (and make it usable as a
166*1b3f573fSAndroid Build Coastguard Worker    # C++ dependency), then we would probably want to include the static
167*1b3f573fSAndroid Build Coastguard Worker    # archive and headers as well. exposing headers would probably require
168*1b3f573fSAndroid Build Coastguard Worker    # an additional aspect to extract CcInfos with just the deps' headers.
169*1b3f573fSAndroid Build Coastguard Worker
170*1b3f573fSAndroid Build Coastguard Worker    return [
171*1b3f573fSAndroid Build Coastguard Worker        DefaultInfo(files = depset(outputs)),
172*1b3f573fSAndroid Build Coastguard Worker    ]
173*1b3f573fSAndroid Build Coastguard Worker
174*1b3f573fSAndroid Build Coastguard Workercc_dist_library = rule(
175*1b3f573fSAndroid Build Coastguard Worker    implementation = _cc_dist_library_impl,
176*1b3f573fSAndroid Build Coastguard Worker    doc = """
177*1b3f573fSAndroid Build Coastguard WorkerCreate libraries suitable for distribution.
178*1b3f573fSAndroid Build Coastguard Worker
179*1b3f573fSAndroid Build Coastguard WorkerThis rule creates static and dynamic libraries from the libraries listed in
180*1b3f573fSAndroid Build Coastguard Worker'deps'. The resulting libraries are suitable for distributing all of 'deps'
181*1b3f573fSAndroid Build Coastguard Workerin a single logical library, for example, in an installable binary package.
182*1b3f573fSAndroid Build Coastguard WorkerOnly the targets listed in 'deps' are included in the result (i.e., the
183*1b3f573fSAndroid Build Coastguard Workeroutput does not include transitive dependencies), allowing precise control
184*1b3f573fSAndroid Build Coastguard Workerover the library boundary.
185*1b3f573fSAndroid Build Coastguard Worker
186*1b3f573fSAndroid Build Coastguard WorkerThe outputs of this rule are a dynamic library and a static library. (If
187*1b3f573fSAndroid Build Coastguard Workerthe build produces both PIC and non-PIC object files, then there is also a
188*1b3f573fSAndroid Build Coastguard Workersecond static library.) The example below illustrates additional details.
189*1b3f573fSAndroid Build Coastguard Worker
190*1b3f573fSAndroid Build Coastguard WorkerThis rule is different from Bazel's experimental `shared_cc_library` in
191*1b3f573fSAndroid Build Coastguard Workerseveral ways. First, this rule ignores transitive dependencies, which means
192*1b3f573fSAndroid Build Coastguard Workerthat dynamic library dependencies generally need to be specified via
193*1b3f573fSAndroid Build Coastguard Worker'linkopts'. Second, this rule produces a static archive library in addition
194*1b3f573fSAndroid Build Coastguard Workerto the dynamic shared library. Third, this rule is not directly usable as a
195*1b3f573fSAndroid Build Coastguard WorkerC++ dependency (although the outputs could be used, e.g., by `cc_import`).
196*1b3f573fSAndroid Build Coastguard Worker
197*1b3f573fSAndroid Build Coastguard WorkerExample:
198*1b3f573fSAndroid Build Coastguard Worker
199*1b3f573fSAndroid Build Coastguard Worker    cc_library(name = "a", srcs = ["a.cc"], hdrs = ["a.h"])
200*1b3f573fSAndroid Build Coastguard Worker    cc_library(name = "b", srcs = ["b.cc"], hdrs = ["b.h"], deps = [":a"])
201*1b3f573fSAndroid Build Coastguard Worker    cc_library(name = "c", srcs = ["c.cc"], hdrs = ["c.h"], deps = [":b"])
202*1b3f573fSAndroid Build Coastguard Worker
203*1b3f573fSAndroid Build Coastguard Worker    # Creates libdist.so and (typically) libdist.pic.a:
204*1b3f573fSAndroid Build Coastguard Worker    # (This may also produce libdist.a if the build produces non-PIC objects.)
205*1b3f573fSAndroid Build Coastguard Worker    cc_dist_library(
206*1b3f573fSAndroid Build Coastguard Worker        name = "dist",
207*1b3f573fSAndroid Build Coastguard Worker        linkopts = ["-la"],   # libdist.so dynamically links against liba.so.
208*1b3f573fSAndroid Build Coastguard Worker        deps = [":b", ":c"],  # Output contains b.o and c.o, but not a.o.
209*1b3f573fSAndroid Build Coastguard Worker    )
210*1b3f573fSAndroid Build Coastguard Worker""",
211*1b3f573fSAndroid Build Coastguard Worker    attrs = {
212*1b3f573fSAndroid Build Coastguard Worker        "deps": attr.label_list(
213*1b3f573fSAndroid Build Coastguard Worker            doc = ("The list of libraries to be included in the outputs. " +
214*1b3f573fSAndroid Build Coastguard Worker                   "Only these targets' compilation outputs will be " +
215*1b3f573fSAndroid Build Coastguard Worker                   "included (i.e., the transitive dependencies are not " +
216*1b3f573fSAndroid Build Coastguard Worker                   "included in the output)."),
217*1b3f573fSAndroid Build Coastguard Worker        ),
218*1b3f573fSAndroid Build Coastguard Worker        "linkopts": attr.string_list(
219*1b3f573fSAndroid Build Coastguard Worker            doc = ("Add these flags to the C++ linker command when creating " +
220*1b3f573fSAndroid Build Coastguard Worker                   "the dynamic library."),
221*1b3f573fSAndroid Build Coastguard Worker        ),
222*1b3f573fSAndroid Build Coastguard Worker        # C++ toolchain before https://github.com/bazelbuild/bazel/issues/7260:
223*1b3f573fSAndroid Build Coastguard Worker        "_cc_toolchain": attr.label(
224*1b3f573fSAndroid Build Coastguard Worker            default = Label("@rules_cc//cc:current_cc_toolchain"),
225*1b3f573fSAndroid Build Coastguard Worker        ),
226*1b3f573fSAndroid Build Coastguard Worker    },
227*1b3f573fSAndroid Build Coastguard Worker    toolchains = [
228*1b3f573fSAndroid Build Coastguard Worker        # C++ toolchain after https://github.com/bazelbuild/bazel/issues/7260:
229*1b3f573fSAndroid Build Coastguard Worker        "@bazel_tools//tools/cpp:toolchain_type",
230*1b3f573fSAndroid Build Coastguard Worker    ],
231*1b3f573fSAndroid Build Coastguard Worker    fragments = ["cpp"],
232*1b3f573fSAndroid Build Coastguard Worker)
233