1*9e965d6fSRomain Jobredeaux# Copyright 2022 The Bazel Authors. All rights reserved. 2*9e965d6fSRomain Jobredeaux# 3*9e965d6fSRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License"); 4*9e965d6fSRomain Jobredeaux# you may not use this file except in compliance with the License. 5*9e965d6fSRomain Jobredeaux# You may obtain a copy of the License at 6*9e965d6fSRomain Jobredeaux# 7*9e965d6fSRomain Jobredeaux# http://www.apache.org/licenses/LICENSE-2.0 8*9e965d6fSRomain Jobredeaux# 9*9e965d6fSRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software 10*9e965d6fSRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS, 11*9e965d6fSRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9e965d6fSRomain Jobredeaux# See the License for the specific language governing permissions and 13*9e965d6fSRomain Jobredeaux# limitations under the License. 14*9e965d6fSRomain Jobredeaux 15*9e965d6fSRomain Jobredeaux""" 16*9e965d6fSRomain JobredeauxDefines the native libs processing and an aspect to collect build configuration 17*9e965d6fSRomain Jobredeauxof split deps 18*9e965d6fSRomain Jobredeaux""" 19*9e965d6fSRomain Jobredeaux 20*9e965d6fSRomain Jobredeauxload("//rules:common.bzl", "common") 21*9e965d6fSRomain Jobredeaux 22*9e965d6fSRomain JobredeauxSplitConfigInfo = provider( 23*9e965d6fSRomain Jobredeaux doc = "Provides information about configuration for a split config dep", 24*9e965d6fSRomain Jobredeaux fields = dict( 25*9e965d6fSRomain Jobredeaux build_config = "The build configuration of the dep.", 26*9e965d6fSRomain Jobredeaux android_config = "Select fields from the android configuration of the dep.", 27*9e965d6fSRomain Jobredeaux target_platform = "The target platform label of the dep.", 28*9e965d6fSRomain Jobredeaux ), 29*9e965d6fSRomain Jobredeaux) 30*9e965d6fSRomain Jobredeaux 31*9e965d6fSRomain Jobredeauxdef _split_config_aspect_impl(__, ctx): 32*9e965d6fSRomain Jobredeaux android_cfg = ctx.fragments.android 33*9e965d6fSRomain Jobredeaux return SplitConfigInfo( 34*9e965d6fSRomain Jobredeaux build_config = ctx.configuration, 35*9e965d6fSRomain Jobredeaux android_config = struct( 36*9e965d6fSRomain Jobredeaux incompatible_use_toolchain_resolution = android_cfg.incompatible_use_toolchain_resolution, 37*9e965d6fSRomain Jobredeaux android_cpu = android_cfg.android_cpu, 38*9e965d6fSRomain Jobredeaux hwasan = android_cfg.hwasan, 39*9e965d6fSRomain Jobredeaux ), 40*9e965d6fSRomain Jobredeaux target_platform = ctx.fragments.platform.platform, 41*9e965d6fSRomain Jobredeaux ) 42*9e965d6fSRomain Jobredeaux 43*9e965d6fSRomain Jobredeauxsplit_config_aspect = aspect( 44*9e965d6fSRomain Jobredeaux implementation = _split_config_aspect_impl, 45*9e965d6fSRomain Jobredeaux fragments = ["android"], 46*9e965d6fSRomain Jobredeaux) 47*9e965d6fSRomain Jobredeaux 48*9e965d6fSRomain Jobredeauxdef _get_libs_dir_name(android_config, target_platform): 49*9e965d6fSRomain Jobredeaux if android_config.incompatible_use_toolchain_resolution: 50*9e965d6fSRomain Jobredeaux name = target_platform.name 51*9e965d6fSRomain Jobredeaux else: 52*9e965d6fSRomain Jobredeaux # Legacy builds use the CPU as the name. 53*9e965d6fSRomain Jobredeaux name = android_config.android_cpu 54*9e965d6fSRomain Jobredeaux if android_config.hwasan: 55*9e965d6fSRomain Jobredeaux name = name + "-hwasan" 56*9e965d6fSRomain Jobredeaux return name 57*9e965d6fSRomain Jobredeaux 58*9e965d6fSRomain Jobredeauxdef process(ctx, filename, merged_native_libs = {}): 59*9e965d6fSRomain Jobredeaux """ Links native deps into a shared library 60*9e965d6fSRomain Jobredeaux 61*9e965d6fSRomain Jobredeaux Args: 62*9e965d6fSRomain Jobredeaux ctx: The context. 63*9e965d6fSRomain Jobredeaux filename: String. The name of the artifact containing the name of the 64*9e965d6fSRomain Jobredeaux linked shared library 65*9e965d6fSRomain Jobredeaux merged_native_libs: A dict that maps cpu to merged native libraries. This maps to empty 66*9e965d6fSRomain Jobredeaux lists if native library merging is not enabled. 67*9e965d6fSRomain Jobredeaux 68*9e965d6fSRomain Jobredeaux Returns: 69*9e965d6fSRomain Jobredeaux Tuple of (libs, libs_name) where libs is a depset of all native deps 70*9e965d6fSRomain Jobredeaux and libs_name is a File containing the basename of the linked shared 71*9e965d6fSRomain Jobredeaux library 72*9e965d6fSRomain Jobredeaux """ 73*9e965d6fSRomain Jobredeaux actual_target_name = ctx.label.name.removesuffix(common.PACKAGED_RESOURCES_SUFFIX) 74*9e965d6fSRomain Jobredeaux native_libs_basename = None 75*9e965d6fSRomain Jobredeaux libs_name = None 76*9e965d6fSRomain Jobredeaux libs = dict() 77*9e965d6fSRomain Jobredeaux for key, deps in ctx.split_attr.deps.items(): 78*9e965d6fSRomain Jobredeaux cc_toolchain_dep = ctx.split_attr._cc_toolchain_split[key] 79*9e965d6fSRomain Jobredeaux cc_toolchain = cc_toolchain_dep[cc_common.CcToolchainInfo] 80*9e965d6fSRomain Jobredeaux build_config = cc_toolchain_dep[SplitConfigInfo].build_config 81*9e965d6fSRomain Jobredeaux libs_dir_name = _get_libs_dir_name( 82*9e965d6fSRomain Jobredeaux cc_toolchain_dep[SplitConfigInfo].android_config, 83*9e965d6fSRomain Jobredeaux cc_toolchain_dep[SplitConfigInfo].target_platform, 84*9e965d6fSRomain Jobredeaux ) 85*9e965d6fSRomain Jobredeaux linker_input = cc_common.create_linker_input( 86*9e965d6fSRomain Jobredeaux owner = ctx.label, 87*9e965d6fSRomain Jobredeaux user_link_flags = ["-Wl,-soname=lib" + actual_target_name], 88*9e965d6fSRomain Jobredeaux ) 89*9e965d6fSRomain Jobredeaux cc_info = cc_common.merge_cc_infos( 90*9e965d6fSRomain Jobredeaux cc_infos = _concat( 91*9e965d6fSRomain Jobredeaux [CcInfo(linking_context = cc_common.create_linking_context( 92*9e965d6fSRomain Jobredeaux linker_inputs = depset([linker_input]), 93*9e965d6fSRomain Jobredeaux ))], 94*9e965d6fSRomain Jobredeaux [dep[JavaInfo].cc_link_params_info for dep in deps if JavaInfo in dep], 95*9e965d6fSRomain Jobredeaux [dep[AndroidCcLinkParamsInfo].link_params for dep in deps if AndroidCcLinkParamsInfo in dep], 96*9e965d6fSRomain Jobredeaux [dep[CcInfo] for dep in deps if CcInfo in dep], 97*9e965d6fSRomain Jobredeaux ), 98*9e965d6fSRomain Jobredeaux ) 99*9e965d6fSRomain Jobredeaux libraries = [] 100*9e965d6fSRomain Jobredeaux if merged_native_libs: 101*9e965d6fSRomain Jobredeaux libraries.extend(merged_native_libs[key]) 102*9e965d6fSRomain Jobredeaux 103*9e965d6fSRomain Jobredeaux native_deps_lib = _link_native_deps_if_present(ctx, cc_info, cc_toolchain, build_config, actual_target_name) 104*9e965d6fSRomain Jobredeaux if native_deps_lib: 105*9e965d6fSRomain Jobredeaux libraries.append(native_deps_lib) 106*9e965d6fSRomain Jobredeaux native_libs_basename = native_deps_lib.basename 107*9e965d6fSRomain Jobredeaux 108*9e965d6fSRomain Jobredeaux libraries.extend(_filter_unique_shared_libs(libraries, cc_info)) 109*9e965d6fSRomain Jobredeaux 110*9e965d6fSRomain Jobredeaux if libraries: 111*9e965d6fSRomain Jobredeaux libs[libs_dir_name] = depset(libraries) 112*9e965d6fSRomain Jobredeaux 113*9e965d6fSRomain Jobredeaux if libs and native_libs_basename: 114*9e965d6fSRomain Jobredeaux libs_name = ctx.actions.declare_file("nativedeps_filename/" + actual_target_name + "/" + filename) 115*9e965d6fSRomain Jobredeaux ctx.actions.write(output = libs_name, content = native_libs_basename) 116*9e965d6fSRomain Jobredeaux 117*9e965d6fSRomain Jobredeaux transitive_native_libs = _get_transitive_native_libs(ctx) 118*9e965d6fSRomain Jobredeaux return AndroidBinaryNativeLibsInfo(libs, libs_name, transitive_native_libs) 119*9e965d6fSRomain Jobredeaux 120*9e965d6fSRomain Jobredeaux# Collect all native shared libraries across split transitions. Some AARs 121*9e965d6fSRomain Jobredeaux# contain shared libraries across multiple architectures, e.g. x86 and 122*9e965d6fSRomain Jobredeaux# armeabi-v7a, and need to be packed into the APK. 123*9e965d6fSRomain Jobredeauxdef _get_transitive_native_libs(ctx): 124*9e965d6fSRomain Jobredeaux return depset( 125*9e965d6fSRomain Jobredeaux transitive = [ 126*9e965d6fSRomain Jobredeaux dep[AndroidNativeLibsInfo].native_libs 127*9e965d6fSRomain Jobredeaux for deps in ctx.split_attr.deps.values() 128*9e965d6fSRomain Jobredeaux for dep in deps 129*9e965d6fSRomain Jobredeaux if AndroidNativeLibsInfo in dep 130*9e965d6fSRomain Jobredeaux ], 131*9e965d6fSRomain Jobredeaux ) 132*9e965d6fSRomain Jobredeaux 133*9e965d6fSRomain Jobredeauxdef _all_inputs(cc_info): 134*9e965d6fSRomain Jobredeaux return [ 135*9e965d6fSRomain Jobredeaux lib 136*9e965d6fSRomain Jobredeaux for input in cc_info.linking_context.linker_inputs.to_list() 137*9e965d6fSRomain Jobredeaux for lib in input.libraries 138*9e965d6fSRomain Jobredeaux ] 139*9e965d6fSRomain Jobredeaux 140*9e965d6fSRomain Jobredeauxdef _filter_unique_shared_libs(linked_libs, cc_info): 141*9e965d6fSRomain Jobredeaux basenames = {} 142*9e965d6fSRomain Jobredeaux artifacts = {} 143*9e965d6fSRomain Jobredeaux if linked_libs: 144*9e965d6fSRomain Jobredeaux basenames = { 145*9e965d6fSRomain Jobredeaux linked_lib.basename: linked_lib 146*9e965d6fSRomain Jobredeaux for linked_lib in linked_libs 147*9e965d6fSRomain Jobredeaux } 148*9e965d6fSRomain Jobredeaux artifacts = { 149*9e965d6fSRomain Jobredeaux linked_lib: None 150*9e965d6fSRomain Jobredeaux for linked_lib in linked_libs 151*9e965d6fSRomain Jobredeaux } 152*9e965d6fSRomain Jobredeaux for input in _all_inputs(cc_info): 153*9e965d6fSRomain Jobredeaux if input.pic_static_library or input.static_library: 154*9e965d6fSRomain Jobredeaux # This is not a shared library and will not be loaded by Android, so skip it. 155*9e965d6fSRomain Jobredeaux continue 156*9e965d6fSRomain Jobredeaux 157*9e965d6fSRomain Jobredeaux artifact = None 158*9e965d6fSRomain Jobredeaux if input.interface_library: 159*9e965d6fSRomain Jobredeaux if input.resolved_symlink_interface_library: 160*9e965d6fSRomain Jobredeaux artifact = input.resolved_symlink_interface_library 161*9e965d6fSRomain Jobredeaux else: 162*9e965d6fSRomain Jobredeaux artifact = input.interface_library 163*9e965d6fSRomain Jobredeaux elif input.resolved_symlink_dynamic_library: 164*9e965d6fSRomain Jobredeaux artifact = input.resolved_symlink_dynamic_library 165*9e965d6fSRomain Jobredeaux else: 166*9e965d6fSRomain Jobredeaux artifact = input.dynamic_library 167*9e965d6fSRomain Jobredeaux 168*9e965d6fSRomain Jobredeaux if not artifact: 169*9e965d6fSRomain Jobredeaux fail("Should never happen: did not find artifact for link!") 170*9e965d6fSRomain Jobredeaux 171*9e965d6fSRomain Jobredeaux if artifact in artifacts: 172*9e965d6fSRomain Jobredeaux # We have already reached this library, e.g., through a different solib symlink. 173*9e965d6fSRomain Jobredeaux continue 174*9e965d6fSRomain Jobredeaux artifacts[artifact] = None 175*9e965d6fSRomain Jobredeaux basename = artifact.basename 176*9e965d6fSRomain Jobredeaux if basename in basenames: 177*9e965d6fSRomain Jobredeaux old_artifact = basenames[basename] 178*9e965d6fSRomain Jobredeaux fail( 179*9e965d6fSRomain Jobredeaux "Each library in the transitive closure must have a " + 180*9e965d6fSRomain Jobredeaux "unique basename to avoid name collisions when packaged into " + 181*9e965d6fSRomain Jobredeaux "an apk, but two libraries have the basename '" + basename + 182*9e965d6fSRomain Jobredeaux "': " + str(artifact) + " and " + str(old_artifact) + ( 183*9e965d6fSRomain Jobredeaux " (the library already seen by this target)" if old_artifact in linked_libs else "" 184*9e965d6fSRomain Jobredeaux ), 185*9e965d6fSRomain Jobredeaux ) 186*9e965d6fSRomain Jobredeaux else: 187*9e965d6fSRomain Jobredeaux basenames[basename] = artifact 188*9e965d6fSRomain Jobredeaux 189*9e965d6fSRomain Jobredeaux return artifacts.keys() 190*9e965d6fSRomain Jobredeaux 191*9e965d6fSRomain Jobredeauxdef _contains_code_to_link(input): 192*9e965d6fSRomain Jobredeaux if not input.static_library and not input.pic_static_library: 193*9e965d6fSRomain Jobredeaux # this is a shared library so we're going to have to copy it 194*9e965d6fSRomain Jobredeaux return False 195*9e965d6fSRomain Jobredeaux if input.objects: 196*9e965d6fSRomain Jobredeaux object_files = input.objects 197*9e965d6fSRomain Jobredeaux elif input.pic_objects: 198*9e965d6fSRomain Jobredeaux object_files = input.pic_objects 199*9e965d6fSRomain Jobredeaux elif _is_any_source_file(input.static_library, input.pic_static_library): 200*9e965d6fSRomain Jobredeaux # this is an opaque library so we're going to have to link it 201*9e965d6fSRomain Jobredeaux return True 202*9e965d6fSRomain Jobredeaux else: 203*9e965d6fSRomain Jobredeaux # if we reach here, this is a cc_library without sources generating an 204*9e965d6fSRomain Jobredeaux # empty archive which does not need to be linked 205*9e965d6fSRomain Jobredeaux # TODO(hvd): replace all such cc_library with exporting_cc_library 206*9e965d6fSRomain Jobredeaux return False 207*9e965d6fSRomain Jobredeaux for obj in object_files: 208*9e965d6fSRomain Jobredeaux if not _is_shared_library(obj): 209*9e965d6fSRomain Jobredeaux # this library was built with a non-shared-library object so we should link it 210*9e965d6fSRomain Jobredeaux return True 211*9e965d6fSRomain Jobredeaux return False 212*9e965d6fSRomain Jobredeaux 213*9e965d6fSRomain Jobredeauxdef _is_any_source_file(*files): 214*9e965d6fSRomain Jobredeaux for file in files: 215*9e965d6fSRomain Jobredeaux if file and file.is_source: 216*9e965d6fSRomain Jobredeaux return True 217*9e965d6fSRomain Jobredeaux return False 218*9e965d6fSRomain Jobredeaux 219*9e965d6fSRomain Jobredeauxdef _is_shared_library(lib_artifact): 220*9e965d6fSRomain Jobredeaux if (lib_artifact.extension in ["so", "dll", "dylib"]): 221*9e965d6fSRomain Jobredeaux return True 222*9e965d6fSRomain Jobredeaux 223*9e965d6fSRomain Jobredeaux lib_name = lib_artifact.basename 224*9e965d6fSRomain Jobredeaux 225*9e965d6fSRomain Jobredeaux # validate against the regex "^.+\\.((so)|(dylib))(\\.\\d\\w*)+$", 226*9e965d6fSRomain Jobredeaux # must match VERSIONED_SHARED_LIBRARY. 227*9e965d6fSRomain Jobredeaux for ext in (".so.", ".dylib."): 228*9e965d6fSRomain Jobredeaux name, _, version = lib_name.rpartition(ext) 229*9e965d6fSRomain Jobredeaux if name and version: 230*9e965d6fSRomain Jobredeaux version_parts = version.split(".") 231*9e965d6fSRomain Jobredeaux for part in version_parts: 232*9e965d6fSRomain Jobredeaux if not part[0].isdigit(): 233*9e965d6fSRomain Jobredeaux return False 234*9e965d6fSRomain Jobredeaux for c in part[1:].elems(): 235*9e965d6fSRomain Jobredeaux if not (c.isalnum() or c == "_"): 236*9e965d6fSRomain Jobredeaux return False 237*9e965d6fSRomain Jobredeaux return True 238*9e965d6fSRomain Jobredeaux return False 239*9e965d6fSRomain Jobredeaux 240*9e965d6fSRomain Jobredeauxdef _is_stamping_enabled(ctx): 241*9e965d6fSRomain Jobredeaux if ctx.configuration.is_tool_configuration(): 242*9e965d6fSRomain Jobredeaux return 0 243*9e965d6fSRomain Jobredeaux return getattr(ctx.attr, "stamp", 0) 244*9e965d6fSRomain Jobredeaux 245*9e965d6fSRomain Jobredeauxdef _get_build_info(ctx, cc_toolchain): 246*9e965d6fSRomain Jobredeaux if _is_stamping_enabled(ctx): 247*9e965d6fSRomain Jobredeaux return cc_toolchain.build_info_files().non_redacted_build_info_files.to_list() 248*9e965d6fSRomain Jobredeaux else: 249*9e965d6fSRomain Jobredeaux return cc_toolchain.build_info_files().redacted_build_info_files.to_list() 250*9e965d6fSRomain Jobredeaux 251*9e965d6fSRomain Jobredeauxdef _get_shared_native_deps_path( 252*9e965d6fSRomain Jobredeaux linker_inputs, 253*9e965d6fSRomain Jobredeaux link_opts, 254*9e965d6fSRomain Jobredeaux linkstamps, 255*9e965d6fSRomain Jobredeaux build_info_artifacts, 256*9e965d6fSRomain Jobredeaux features, 257*9e965d6fSRomain Jobredeaux is_test_target_partially_disabled_thin_lto): 258*9e965d6fSRomain Jobredeaux fp = [] 259*9e965d6fSRomain Jobredeaux for artifact in linker_inputs: 260*9e965d6fSRomain Jobredeaux fp.append(artifact.short_path) 261*9e965d6fSRomain Jobredeaux fp.append(str(len(link_opts))) 262*9e965d6fSRomain Jobredeaux for opt in link_opts: 263*9e965d6fSRomain Jobredeaux fp.append(opt) 264*9e965d6fSRomain Jobredeaux for artifact in linkstamps: 265*9e965d6fSRomain Jobredeaux fp.append(artifact.short_path) 266*9e965d6fSRomain Jobredeaux for artifact in build_info_artifacts: 267*9e965d6fSRomain Jobredeaux fp.append(artifact.short_path) 268*9e965d6fSRomain Jobredeaux for feature in features: 269*9e965d6fSRomain Jobredeaux fp.append(feature) 270*9e965d6fSRomain Jobredeaux 271*9e965d6fSRomain Jobredeaux fp.append("1" if is_test_target_partially_disabled_thin_lto else "0") 272*9e965d6fSRomain Jobredeaux 273*9e965d6fSRomain Jobredeaux fingerprint = "%x" % hash("".join(fp)) 274*9e965d6fSRomain Jobredeaux return "_nativedeps/" + fingerprint 275*9e965d6fSRomain Jobredeaux 276*9e965d6fSRomain Jobredeauxdef _get_static_mode_params_for_dynamic_library_libraries(libs): 277*9e965d6fSRomain Jobredeaux linker_inputs = [] 278*9e965d6fSRomain Jobredeaux for lib in libs: 279*9e965d6fSRomain Jobredeaux if lib.pic_static_library: 280*9e965d6fSRomain Jobredeaux linker_inputs.append(lib.pic_static_library) 281*9e965d6fSRomain Jobredeaux elif lib.static_library: 282*9e965d6fSRomain Jobredeaux linker_inputs.append(lib.static_library) 283*9e965d6fSRomain Jobredeaux elif lib.interface_library: 284*9e965d6fSRomain Jobredeaux linker_inputs.append(lib.interface_library) 285*9e965d6fSRomain Jobredeaux else: 286*9e965d6fSRomain Jobredeaux linker_inputs.append(lib.dynamic_library) 287*9e965d6fSRomain Jobredeaux return linker_inputs 288*9e965d6fSRomain Jobredeaux 289*9e965d6fSRomain Jobredeauxdef _link_native_deps_if_present(ctx, cc_info, cc_toolchain, build_config, actual_target_name, is_test_rule_class = False): 290*9e965d6fSRomain Jobredeaux needs_linking = False 291*9e965d6fSRomain Jobredeaux all_inputs = _all_inputs(cc_info) 292*9e965d6fSRomain Jobredeaux for input in all_inputs: 293*9e965d6fSRomain Jobredeaux needs_linking = needs_linking or _contains_code_to_link(input) 294*9e965d6fSRomain Jobredeaux 295*9e965d6fSRomain Jobredeaux if not needs_linking: 296*9e965d6fSRomain Jobredeaux return None 297*9e965d6fSRomain Jobredeaux 298*9e965d6fSRomain Jobredeaux # This does not need to be shareable, but we use this API to specify the 299*9e965d6fSRomain Jobredeaux # custom file root (matching the configuration) 300*9e965d6fSRomain Jobredeaux output_lib = ctx.actions.declare_shareable_artifact( 301*9e965d6fSRomain Jobredeaux ctx.label.package + "/nativedeps/" + actual_target_name + "/lib" + actual_target_name + ".so", 302*9e965d6fSRomain Jobredeaux build_config.bin_dir, 303*9e965d6fSRomain Jobredeaux ) 304*9e965d6fSRomain Jobredeaux 305*9e965d6fSRomain Jobredeaux linker_inputs = cc_info.linking_context.linker_inputs.to_list() 306*9e965d6fSRomain Jobredeaux 307*9e965d6fSRomain Jobredeaux link_opts = [] 308*9e965d6fSRomain Jobredeaux for linker_input in linker_inputs: 309*9e965d6fSRomain Jobredeaux for flag in linker_input.user_link_flags: 310*9e965d6fSRomain Jobredeaux link_opts.append(flag) 311*9e965d6fSRomain Jobredeaux 312*9e965d6fSRomain Jobredeaux linkstamps = [] 313*9e965d6fSRomain Jobredeaux for linker_input in linker_inputs: 314*9e965d6fSRomain Jobredeaux linkstamps.extend(linker_input.linkstamps) 315*9e965d6fSRomain Jobredeaux linkstamps_dict = {linkstamp: None for linkstamp in linkstamps} 316*9e965d6fSRomain Jobredeaux 317*9e965d6fSRomain Jobredeaux build_info_artifacts = _get_build_info(ctx, cc_toolchain) if linkstamps_dict else [] 318*9e965d6fSRomain Jobredeaux requested_features = ["static_linking_mode", "native_deps_link"] 319*9e965d6fSRomain Jobredeaux requested_features.extend(ctx.features) 320*9e965d6fSRomain Jobredeaux if not "legacy_whole_archive" in ctx.disabled_features: 321*9e965d6fSRomain Jobredeaux requested_features.append("legacy_whole_archive") 322*9e965d6fSRomain Jobredeaux requested_features = sorted(requested_features) 323*9e965d6fSRomain Jobredeaux feature_config = cc_common.configure_features( 324*9e965d6fSRomain Jobredeaux ctx = ctx, 325*9e965d6fSRomain Jobredeaux cc_toolchain = cc_toolchain, 326*9e965d6fSRomain Jobredeaux requested_features = requested_features, 327*9e965d6fSRomain Jobredeaux unsupported_features = ctx.disabled_features, 328*9e965d6fSRomain Jobredeaux ) 329*9e965d6fSRomain Jobredeaux partially_disabled_thin_lto = ( 330*9e965d6fSRomain Jobredeaux cc_common.is_enabled( 331*9e965d6fSRomain Jobredeaux feature_name = "thin_lto_linkstatic_tests_use_shared_nonlto_backends", 332*9e965d6fSRomain Jobredeaux feature_configuration = feature_config, 333*9e965d6fSRomain Jobredeaux ) and not cc_common.is_enabled( 334*9e965d6fSRomain Jobredeaux feature_name = "thin_lto_all_linkstatic_use_shared_nonlto_backends", 335*9e965d6fSRomain Jobredeaux feature_configuration = feature_config, 336*9e965d6fSRomain Jobredeaux ) 337*9e965d6fSRomain Jobredeaux ) 338*9e965d6fSRomain Jobredeaux test_only_target = ctx.attr.testonly or is_test_rule_class 339*9e965d6fSRomain Jobredeaux share_native_deps = ctx.fragments.cpp.share_native_deps() 340*9e965d6fSRomain Jobredeaux 341*9e965d6fSRomain Jobredeaux linker_inputs = _get_static_mode_params_for_dynamic_library_libraries(all_inputs) 342*9e965d6fSRomain Jobredeaux 343*9e965d6fSRomain Jobredeaux if share_native_deps: 344*9e965d6fSRomain Jobredeaux shared_path = _get_shared_native_deps_path( 345*9e965d6fSRomain Jobredeaux linker_inputs, 346*9e965d6fSRomain Jobredeaux link_opts, 347*9e965d6fSRomain Jobredeaux [linkstamp.file() for linkstamp in linkstamps_dict], 348*9e965d6fSRomain Jobredeaux build_info_artifacts, 349*9e965d6fSRomain Jobredeaux requested_features, 350*9e965d6fSRomain Jobredeaux test_only_target and partially_disabled_thin_lto, 351*9e965d6fSRomain Jobredeaux ) 352*9e965d6fSRomain Jobredeaux linked_lib = ctx.actions.declare_shareable_artifact(shared_path + ".so", build_config.bin_dir) 353*9e965d6fSRomain Jobredeaux else: 354*9e965d6fSRomain Jobredeaux linked_lib = output_lib 355*9e965d6fSRomain Jobredeaux 356*9e965d6fSRomain Jobredeaux cc_common.link( 357*9e965d6fSRomain Jobredeaux name = ctx.label.name, 358*9e965d6fSRomain Jobredeaux actions = ctx.actions, 359*9e965d6fSRomain Jobredeaux linking_contexts = [cc_info.linking_context], 360*9e965d6fSRomain Jobredeaux output_type = "dynamic_library", 361*9e965d6fSRomain Jobredeaux never_link = True, 362*9e965d6fSRomain Jobredeaux native_deps = True, 363*9e965d6fSRomain Jobredeaux feature_configuration = feature_config, 364*9e965d6fSRomain Jobredeaux cc_toolchain = cc_toolchain, 365*9e965d6fSRomain Jobredeaux test_only_target = test_only_target, 366*9e965d6fSRomain Jobredeaux stamp = getattr(ctx.attr, "stamp", 0), 367*9e965d6fSRomain Jobredeaux main_output = linked_lib, 368*9e965d6fSRomain Jobredeaux use_shareable_artifact_factory = True, 369*9e965d6fSRomain Jobredeaux build_config = build_config, 370*9e965d6fSRomain Jobredeaux ) 371*9e965d6fSRomain Jobredeaux 372*9e965d6fSRomain Jobredeaux if (share_native_deps): 373*9e965d6fSRomain Jobredeaux ctx.actions.symlink( 374*9e965d6fSRomain Jobredeaux output = output_lib, 375*9e965d6fSRomain Jobredeaux target_file = linked_lib, 376*9e965d6fSRomain Jobredeaux ) 377*9e965d6fSRomain Jobredeaux return output_lib 378*9e965d6fSRomain Jobredeaux else: 379*9e965d6fSRomain Jobredeaux return linked_lib 380*9e965d6fSRomain Jobredeaux 381*9e965d6fSRomain Jobredeauxdef _concat(*list_of_lists): 382*9e965d6fSRomain Jobredeaux res = [] 383*9e965d6fSRomain Jobredeaux for list in list_of_lists: 384*9e965d6fSRomain Jobredeaux res.extend(list) 385*9e965d6fSRomain Jobredeaux return res 386