Skip to main content
Glama
cxx.bzl33.8 kB
# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under both the MIT license found in the # LICENSE-MIT file in the root directory of this source tree and the Apache # License, Version 2.0 found in the LICENSE-APACHE file in the root directory # of this source tree. load("@prelude//:paths.bzl", "paths") load( "@prelude//android:android_providers.bzl", "merge_android_packageable_info", ) load("@prelude//apple:resource_groups.bzl", "create_resource_graph") load("@prelude//cxx:cxx_sources.bzl", "get_srcs_with_flags") load("@prelude//cxx:cxx_utility.bzl", "cxx_attrs_get_allow_cache_upload") load( "@prelude//cxx:link_groups_types.bzl", "LinkGroupInfo", # @unused Used as a type ) load( "@prelude//cxx:runtime_dependency_handling.bzl", "cxx_attr_runtime_dependency_handling", ) load("@prelude//linking:execution_preference.bzl", "LinkExecutionPreference") load( "@prelude//linking:link_groups.bzl", "merge_link_group_lib_info", ) load( "@prelude//linking:link_info.bzl", "Archive", "ArchiveLinkable", "CxxSanitizerRuntimeInfo", "LibOutputStyle", "LinkArgs", "LinkCommandDebugOutputInfo", "LinkInfo", "LinkInfos", "LinkStrategy", "LinkedObject", "SharedLibLinkable", "create_merged_link_info", "create_merged_link_info_for_propagation", "get_lib_output_style", "get_link_args_for_strategy", "get_output_styles_for_linkage", "subtarget_for_output_style", "to_link_strategy", ) load( "@prelude//linking:linkable_graph.bzl", "DlopenableLibraryInfo", "LinkableGraph", "create_linkable_graph", "create_linkable_graph_node", "create_linkable_node", ) load( "@prelude//linking:linkables.bzl", "linkables", ) load( "@prelude//linking:shared_libraries.bzl", "SharedLibraries", "SharedLibraryInfo", "create_shlib_from_ctx", "extract_soname_from_shlib", "merge_shared_libraries", "to_soname", ) load("@prelude//linking:strip.bzl", "strip_debug_info") load("@prelude//linking:types.bzl", "Linkage") load("@prelude//os_lookup:defs.bzl", "Os", "OsLookup") load("@prelude//python:manifest.bzl", "create_manifest_for_entries") load("@prelude//test:inject_test_run_info.bzl", "inject_test_run_info") load( "@prelude//tests:re_utils.bzl", "get_re_executors_from_props", ) load( "@prelude//third-party:build.bzl", "create_third_party_build_info", ) load("@prelude//unix:providers.bzl", "UnixEnv", "create_unix_env_info") load("@prelude//utils:expect.bzl", "expect") load( "@prelude//utils:utils.bzl", "filter_and_map_idx", "value_or", ) load(":cxx_context.bzl", "get_cxx_toolchain_info") load(":cxx_executable.bzl", "cxx_executable") load( ":cxx_library.bzl", "CxxLibraryOutput", # @unused Used as a type "cxx_library_parameterized", ) load( ":cxx_library_utility.bzl", "cxx_attr_dep_metadata", "cxx_attr_deps", "cxx_attr_exported_deps", "cxx_attr_link_style", "cxx_attr_linker_flags_all", "cxx_attr_preferred_linkage", "cxx_inherited_link_info", "cxx_platform_supported", "cxx_use_shlib_intfs", ) load( ":cxx_types.bzl", "CxxRuleConstructorParams", "CxxRuleProviderParams", "CxxRuleSubTargetParams", ) load( ":groups_types.bzl", "Group", "MATCH_ALL_LABEL", "NO_MATCH_LABEL", ) load( ":headers.bzl", "CPrecompiledHeaderInfo", "cxx_get_regular_cxx_headers_layout", ) load( ":link.bzl", "cxx_link_shared_library", ) load( ":link_groups.bzl", "LinkGroupLibSpec", "get_link_group_info", ) load( ":link_types.bzl", "link_options", ) load( ":linker.bzl", "DUMPBIN_SUB_TARGET", "PDB_SUB_TARGET", "get_dumpbin_providers", "get_link_whole_args", "get_pdb_providers", "get_shared_library_name", "get_shared_library_name_for_param", ) load( ":omnibus.bzl", "create_linkable_root", ) load(":platform.bzl", "cxx_by_platform") load( ":preprocessor.bzl", "CPreprocessor", "CPreprocessorArgs", "cxx_exported_preprocessor_info", "cxx_inherited_preprocessor_infos", "cxx_merge_cpreprocessors", "format_system_include_arg", ) load( ":shared_library_interface.bzl", "shared_library_interface", ) ##################################################################### # Operations def _get_shared_link_style_sub_targets_and_providers( output_style: LibOutputStyle, ctx: AnalysisContext, output: [CxxLibraryOutput, None]) -> (dict[str, list[Provider]], list[Provider]): if output_style != LibOutputStyle("shared_lib") or output == None: return ({}, []) sub_targets = {} providers = [] if output.dwp != None: sub_targets["dwp"] = [DefaultInfo(default_output = output.dwp)] if output.pdb != None: sub_targets[PDB_SUB_TARGET] = get_pdb_providers(pdb = output.pdb, binary = output.default) cxx_toolchain = get_cxx_toolchain_info(ctx) if cxx_toolchain.dumpbin_toolchain_path != None: sub_targets[DUMPBIN_SUB_TARGET] = get_dumpbin_providers(ctx, output.default, cxx_toolchain.dumpbin_toolchain_path) if output.linker_map != None: sub_targets["linker-map"] = [DefaultInfo(default_output = output.linker_map.map, other_outputs = [output.linker_map.binary])] if output.implib != None: sub_targets["implib"] = [DefaultInfo(default_output = output.implib)] return (sub_targets, providers) def cxx_library_impl(ctx: AnalysisContext) -> list[Provider]: if ctx.attrs.can_be_asset and ctx.attrs.used_by_wrap_script: fail("Cannot use `can_be_asset` and `used_by_wrap_script` in the same rule") if ctx.attrs._is_building_android_binary: sub_target_params, provider_params = _get_params_for_android_binary_cxx_library() else: sub_target_params = CxxRuleSubTargetParams() provider_params = CxxRuleProviderParams( third_party_build = True, ) params = CxxRuleConstructorParams( rule_type = "cxx_library", headers_layout = cxx_get_regular_cxx_headers_layout(ctx), srcs = get_srcs_with_flags(ctx), output_style_sub_targets_and_providers_factory = _get_shared_link_style_sub_targets_and_providers, generate_sub_targets = sub_target_params, generate_providers = provider_params, compiler_flags = ctx.attrs.compiler_flags, lang_compiler_flags = ctx.attrs.lang_compiler_flags, platform_compiler_flags = ctx.attrs.platform_compiler_flags, lang_platform_compiler_flags = ctx.attrs.lang_platform_compiler_flags, preprocessor_flags = ctx.attrs.preprocessor_flags, lang_preprocessor_flags = ctx.attrs.lang_preprocessor_flags, platform_preprocessor_flags = ctx.attrs.platform_preprocessor_flags, lang_platform_preprocessor_flags = ctx.attrs.lang_platform_preprocessor_flags, use_header_units = ctx.attrs.use_header_units, export_header_unit = ctx.attrs.export_header_unit, export_header_unit_filter = ctx.attrs.export_header_unit_filter, error_handler = get_cxx_toolchain_info(ctx).cxx_error_handler, ) output = cxx_library_parameterized(ctx, params) return output.providers def _only_shared_mappings(group: Group) -> bool: """ Return whether this group only has explicit "shared" linkage mappings, which indicates a group that re-uses pre-linked libs. """ for mapping in group.mappings: if mapping.preferred_linkage != Linkage("shared"): return False return True def create_shared_lib_link_group_specs(ctx: AnalysisContext, link_group_definitions: list[Group]) -> list[LinkGroupLibSpec]: specs = [] linker_info = get_cxx_toolchain_info(ctx).linker_info for group in link_group_definitions: if group.name in (MATCH_ALL_LABEL, NO_MATCH_LABEL): continue # TODO(agallagher): We should probably add proper handling for "provided" # system handling to avoid needing this special case. if _only_shared_mappings(group): continue specs.append( LinkGroupLibSpec( name = get_shared_library_name(linker_info, group.name, apply_default_prefix = True), is_shared_lib = True, group = group, ), ) return specs def get_auto_link_group_specs(ctx: AnalysisContext, link_group_info: [LinkGroupInfo, None]) -> [list[LinkGroupLibSpec], None]: if link_group_info == None or not ctx.attrs.auto_link_groups: return None return create_shared_lib_link_group_specs(ctx, link_group_info.groups.values()) def cxx_binary_impl(ctx: AnalysisContext) -> list[Provider]: link_strategy = to_link_strategy(cxx_attr_link_style(ctx)) link_group_info = get_link_group_info( ctx, filter_and_map_idx(LinkableGraph, cxx_attr_deps(ctx)), link_strategy, ) params = CxxRuleConstructorParams( rule_type = "cxx_binary", executable_name = ctx.attrs.executable_name, headers_layout = cxx_get_regular_cxx_headers_layout(ctx), srcs = get_srcs_with_flags(ctx), link_group_info = link_group_info, auto_link_group_specs = get_auto_link_group_specs(ctx, link_group_info), prefer_stripped_objects = ctx.attrs.prefer_stripped_objects, exe_allow_cache_upload = cxx_attrs_get_allow_cache_upload(ctx.attrs), extra_link_roots = linkables(ctx.attrs.link_group_deps), compiler_flags = ctx.attrs.compiler_flags, lang_compiler_flags = ctx.attrs.lang_compiler_flags, platform_compiler_flags = ctx.attrs.platform_compiler_flags, lang_platform_compiler_flags = ctx.attrs.lang_platform_compiler_flags, preprocessor_flags = ctx.attrs.preprocessor_flags, lang_preprocessor_flags = ctx.attrs.lang_preprocessor_flags, platform_preprocessor_flags = ctx.attrs.platform_preprocessor_flags, lang_platform_preprocessor_flags = ctx.attrs.lang_platform_preprocessor_flags, use_header_units = ctx.attrs.use_header_units, runtime_dependency_handling = cxx_attr_runtime_dependency_handling(ctx), error_handler = get_cxx_toolchain_info(ctx).cxx_error_handler, ) output = cxx_executable(ctx, params) extra_providers = [] if output.link_command_debug_output: extra_providers.append(LinkCommandDebugOutputInfo(debug_outputs = [output.link_command_debug_output])) if output.sanitizer_runtime_files: extra_providers.append(CxxSanitizerRuntimeInfo(runtime_files = output.sanitizer_runtime_files)) # Unix env provider. extra_providers.append( create_unix_env_info( actions = ctx.actions, env = UnixEnv( label = ctx.label, binaries = [ create_manifest_for_entries( ctx = ctx, name = "unix_env", entries = [ (ctx.label.name, output.binary, ""), ], ), ], ), # TODO(agallagher): We only want to traverse deps when dynamically # linking. #deps = ctx.attrs.deps, ), ) # When an executable is the output of a build, also materialize all the # unpacked external debuginfo that goes with it. This makes `buck2 build # :main` equivalent to `buck2 build :main :main[debuginfo]`. # # This is wasted work if we are building an executable together with its dwp # subtarget (`buck2 build :main :main[dwp]`) in which case a large number of # unpacked debuginfo files can end up being materialized redundantly. LLDB # will ignore them and obtain debuginfo via the single packed debuginfo file # instead. # # But materializing unpacked debuginfo is the right tradeoff because it # means the output of `buck2 build :main` is always immediately usable in a # debugger. # # External debuginfo is *not* materialized when an executable is depended on # by another rule, such as by $(exe ...) or exec_dep. other_outputs = output.runtime_files + output.external_debug_info_artifacts return [ DefaultInfo( default_output = output.binary, other_outputs = other_outputs, sub_targets = output.sub_targets, ), RunInfo(args = cmd_args(output.binary, hidden = output.runtime_files)), output.compilation_db, output.xcode_data, output.dist_info, ] + extra_providers def _prebuilt_item( ctx: AnalysisContext, item: [typing.Any, None], platform_items: [list[(str, typing.Any)], None]) -> [typing.Any, None]: """ Parse the given item that can be specified by regular and platform-specific parameters. """ if item != None: return item if platform_items != None: items = dedupe(cxx_by_platform(ctx, platform_items)) if len(items) == 0: return None if len(items) != 1: fail("expected single platform match: name={}//{}:{}, platform_items={}, items={}".format(ctx.label.cell, ctx.label.package, ctx.label.name, str(platform_items), str(items))) return items[0] return None def _prebuilt_linkage(ctx: AnalysisContext) -> Linkage: """ Construct the preferred linkage to use for the given prebuilt library. """ if ctx.attrs.header_only: return Linkage("any") if ctx.attrs.force_static: return Linkage("static") preferred_linkage = cxx_attr_preferred_linkage(ctx) if preferred_linkage != Linkage("any"): return preferred_linkage if ctx.attrs.provided: return Linkage("shared") return Linkage("any") def prebuilt_cxx_library_impl(ctx: AnalysisContext) -> list[Provider]: # Versioned params should be intercepted and converted away via the stub. expect(not ctx.attrs.versioned_exported_lang_platform_preprocessor_flags) expect(not ctx.attrs.versioned_exported_lang_preprocessor_flags) expect(not ctx.attrs.versioned_exported_platform_preprocessor_flags) expect(not ctx.attrs.versioned_exported_preprocessor_flags) expect(not ctx.attrs.versioned_header_dirs) expect(not ctx.attrs.versioned_shared_lib) expect(not ctx.attrs.versioned_static_lib) expect(not ctx.attrs.versioned_static_pic_lib) if not cxx_platform_supported(ctx): return [DefaultInfo(default_output = None)] providers = [] linker_info = get_cxx_toolchain_info(ctx).linker_info linker_type = linker_info.type # Parse library parameters. static_lib = _prebuilt_item( ctx, ctx.attrs.static_lib, ctx.attrs.platform_static_lib, ) static_pic_lib = _prebuilt_item( ctx, ctx.attrs.static_pic_lib, ctx.attrs.platform_static_pic_lib, ) shared_lib = _prebuilt_item( ctx, ctx.attrs.shared_lib, ctx.attrs.platform_shared_lib, ) header_dirs = _prebuilt_item( ctx, ctx.attrs.header_dirs, ctx.attrs.platform_header_dirs, ) preferred_linkage = _prebuilt_linkage(ctx) # Prepare the stripped static lib. static_lib_stripped = None if not ctx.attrs.prestripped and static_lib != None: static_lib_stripped = strip_debug_info(ctx, static_lib.short_path, static_lib) # Prepare the stripped static PIC lib. If the static PIC lib is the same # artifact as the static lib, then just re-use the stripped static lib. static_pic_lib_stripped = None if not ctx.attrs.prestripped: if static_lib == static_pic_lib: static_pic_lib_stripped = static_lib_stripped elif static_pic_lib != None: static_pic_lib_stripped = strip_debug_info(ctx, static_pic_lib.short_path, static_pic_lib) if ctx.attrs.soname != None: soname = get_shared_library_name_for_param(linker_info, ctx.attrs.soname) elif shared_lib != None and ctx.attrs.extract_soname: soname = extract_soname_from_shlib( actions = ctx.actions, name = "__soname__.txt", shared_lib = shared_lib, ) else: soname = get_shared_library_name(linker_info, ctx.label.name, apply_default_prefix = True) soname = to_soname(soname) # Use ctx.attrs.deps instead of cxx_attr_deps, since prebuilt rules don't have platform_deps. first_order_deps = ctx.attrs.deps exported_first_order_deps = cxx_attr_exported_deps(ctx) # Exported preprocessor info. inherited_pp_infos = cxx_inherited_preprocessor_infos(exported_first_order_deps) generic_exported_pre = cxx_exported_preprocessor_info(ctx, cxx_get_regular_cxx_headers_layout(ctx), []) args = [] compiler_type = get_cxx_toolchain_info(ctx).cxx_compiler_info.compiler_type if header_dirs != None: for x in header_dirs: args.append(format_system_include_arg(cmd_args(x), compiler_type)) exported_items = [generic_exported_pre] if args: exported_items.append(CPreprocessor(args = CPreprocessorArgs(args = args))) propagated_preprocessor = cxx_merge_cpreprocessors( ctx, exported_items, inherited_pp_infos, ) providers.append(propagated_preprocessor) inherited_link = cxx_inherited_link_info(first_order_deps) inherited_exported_link = cxx_inherited_link_info(exported_first_order_deps) linker_flags = cxx_attr_linker_flags_all(ctx) # Gather link infos, outputs, and shared libs for effective link style. outputs = {} libraries = {} solibs = [] sub_targets = {} for output_style in get_output_styles_for_linkage(preferred_linkage): out = None linkable = None linkable_stripped = None # If we have sources to compile, generate the necessary libraries and # add them to the exported link info. if not ctx.attrs.header_only: def archive_linkable(lib): return ArchiveLinkable( archive = Archive(artifact = lib), linker_type = linker_type, link_whole = ctx.attrs.link_whole, supports_lto = ctx.attrs.supports_lto, ) if output_style == LibOutputStyle("archive"): if static_lib: out = static_lib linkable = archive_linkable(static_lib) linkable_stripped = archive_linkable(static_lib_stripped) if static_lib_stripped else None elif output_style == LibOutputStyle("pic_archive"): lib = static_pic_lib or static_lib if lib: out = lib linkable = archive_linkable(lib) linkable_stripped = archive_linkable(static_pic_lib_stripped or static_lib_stripped) if (static_pic_lib_stripped or static_lib_stripped) else None else: # shared # If no shared library was provided, link one from the static libraries. if shared_lib != None: shared_lib = LinkedObject(output = shared_lib, unstripped_output = shared_lib) else: lib = static_pic_lib or static_lib if lib: shlink_args = [] # TODO(T110378143): Support post link flags properly. shlink_args.extend(linker_flags.exported_flags) shlink_args.extend(linker_flags.flags) shlink_args.extend(get_link_whole_args(linker_type, [lib])) link_result = cxx_link_shared_library( ctx = ctx, output = soname.ensure_str(), name = soname.ensure_str(), opts = link_options( links = [ LinkArgs(flags = shlink_args), # TODO(T110378118): As per v1, we always link against "shared" # dependencies when building a shaerd library. get_link_args_for_strategy(ctx, inherited_exported_link, LinkStrategy("shared")), ], link_execution_preference = LinkExecutionPreference("any"), ), ) shared_lib = link_result.linked_object if shared_lib: out = shared_lib.output shared_lib_for_linking = shared_lib.output # Generate a shared library interface if the rule supports it. if ctx.attrs.supports_shared_library_interface and cxx_use_shlib_intfs(ctx): shared_lib_for_linking = shared_library_interface( ctx = ctx, shared_lib = shared_lib.output, ) if ctx.attrs._target_os_type[OsLookup].os == Os("windows"): shared_lib_for_linking = ctx.attrs.import_lib linkable = None if shared_lib_for_linking != None: linkable = SharedLibLinkable( lib = shared_lib_for_linking, # Some prebuilt shared libs don't set a SONAME (e.g. # IntelComposerXE), so we can't link them via just the shared # lib (otherwise, we may embed build-time paths in `DT_NEEDED` # tags). link_without_soname = ctx.attrs.link_without_soname, ) # Provided means something external to the build will provide # the libraries, so we don't need to propagate anything. if not ctx.attrs.provided: solibs.append( create_shlib_from_ctx( ctx = ctx, lib = shared_lib, soname = soname, ), ) # Provide a sub-target that always provides the shared lib # using the soname. if soname and soname.is_str and shared_lib.output.basename != paths.basename(soname.ensure_str()): soname_lib = ctx.actions.copy_file(soname.ensure_str(), shared_lib.output) else: soname_lib = shared_lib.output sub_targets["soname-lib"] = [DefaultInfo(default_output = soname_lib)] if shared_lib.pdb: sub_targets[PDB_SUB_TARGET] = get_pdb_providers(pdb = shared_lib.pdb, binary = shared_lib.output) dumpbin_toolchain_path = get_cxx_toolchain_info(ctx).dumpbin_toolchain_path if dumpbin_toolchain_path != None: sub_targets[DUMPBIN_SUB_TARGET] = get_dumpbin_providers(ctx, shared_lib.output, dumpbin_toolchain_path) if shared_lib.dwp != None: sub_targets["dwp"] = [DefaultInfo(default_output = shared_lib.dwp)] # TODO(cjhopman): is it okay that we sometimes don't have a linkable? outputs[output_style] = out dep_metadata = cxx_attr_dep_metadata(ctx) libraries[output_style] = LinkInfos( default = LinkInfo( name = ctx.attrs.name, pre_flags = linker_flags.exported_flags, post_flags = linker_flags.exported_post_flags, linkables = [linkable] if linkable else [], metadata = dep_metadata, ), stripped = None if linkable_stripped == None else LinkInfo( name = ctx.attrs.name, pre_flags = linker_flags.exported_flags, post_flags = linker_flags.exported_post_flags, linkables = [linkable_stripped], metadata = dep_metadata, ), ) sub_targets[subtarget_for_output_style(output_style)] = [DefaultInfo( default_output = outputs[output_style], )] cxx_toolchain = get_cxx_toolchain_info(ctx) pic_behavior = cxx_toolchain.pic_behavior # Propagate link info provider. providers.append(create_merged_link_info( ctx, pic_behavior, # Add link info for each link style, libraries, preferred_linkage = preferred_linkage, # Export link info from non-exported deps (when necessary). deps = inherited_link, # Export link info from out (exported) deps. exported_deps = inherited_exported_link, )) # Propagate shared libraries up the tree. shared_libs = SharedLibraries(libraries = solibs) providers.append(merge_shared_libraries( ctx.actions, shared_libs, filter(None, [x.get(SharedLibraryInfo) for x in exported_first_order_deps]), )) providers.append( create_unix_env_info( actions = ctx.actions, env = UnixEnv( label = ctx.label, native_libs = [shared_libs], ), deps = ctx.attrs.deps + ctx.attrs.exported_deps, ), ) # Third-party provider. third_party_build_info = create_third_party_build_info( ctx = ctx, paths = [] if header_dirs == None else [(d.short_path, d) for d in header_dirs], cxx_headers = [propagated_preprocessor], shared_libs = shared_libs.libraries, cxx_header_dirs = ["include"] + ([] if header_dirs == None else [d.short_path for d in header_dirs]), deps = ctx.attrs.deps + cxx_attr_exported_deps(ctx), ) providers.append(third_party_build_info) sub_targets["third-party-build"] = [ DefaultInfo( default_output = third_party_build_info.build.root.artifact, sub_targets = dict( manifest = [DefaultInfo(default_output = third_party_build_info.build.manifest)], ), ), ] # Create the default output for the library rule given it's link style and preferred linkage link_strategy = to_link_strategy(cxx_toolchain.linker_info.link_style) actual_output_style = get_lib_output_style(link_strategy, preferred_linkage, pic_behavior) output = outputs[actual_output_style] providers.append(DefaultInfo( default_output = output, sub_targets = sub_targets, )) # Omnibus root provider. if LibOutputStyle("pic_archive") in libraries and (static_pic_lib or static_lib) and not ctx.attrs.header_only and soname.is_str: # TODO(cjhopman): This doesn't support thin archives linkable_root = create_linkable_root( label = ctx.label, name = soname.ensure_str(), link_infos = LinkInfos(default = LinkInfo( name = soname.ensure_str(), pre_flags = ( linker_flags.exported_flags + linker_flags.flags ), linkables = [ArchiveLinkable( archive = Archive( artifact = static_pic_lib or static_lib, ), linker_type = linker_type, link_whole = True, )], post_flags = linker_flags.exported_post_flags, metadata = cxx_attr_dep_metadata(ctx), )), deps = exported_first_order_deps, ) providers.append(linkable_root) # Mark libraries that support `dlopen`. if ctx.attrs.supports_python_dlopen: providers.append(DlopenableLibraryInfo()) linkable_graph = create_linkable_graph( ctx, node = create_linkable_graph_node( ctx, linkable_node = create_linkable_node( ctx = ctx, default_soname = soname.as_str(), preferred_linkage = preferred_linkage, default_link_strategy = to_link_strategy(cxx_toolchain.linker_info.link_style), exported_deps = exported_first_order_deps, # If we don't have link input for this link style, we pass in `None` so # that omnibus knows to avoid it. link_infos = libraries, shared_libs = shared_libs, linker_flags = linker_flags, can_be_asset = getattr(ctx.attrs, "can_be_asset", False) or False, stub = getattr(ctx.attrs, "stub", False), ), excluded = {ctx.label: None} if not value_or(ctx.attrs.supports_merged_linking, True) else {}, ), deps = exported_first_order_deps, ) providers.append(linkable_graph) providers.append( merge_link_group_lib_info( deps = first_order_deps + exported_first_order_deps, ), ) # TODO(T107163344) this shouldn't be in prebuilt_cxx_library itself, use overlays to remove it. providers.append(merge_android_packageable_info(ctx.label, ctx.actions, first_order_deps + exported_first_order_deps)) apple_resource_graph = create_resource_graph( ctx = ctx, labels = ctx.attrs.labels, deps = first_order_deps, exported_deps = exported_first_order_deps, ) providers += [apple_resource_graph] return providers def cxx_precompiled_header_impl(ctx: AnalysisContext) -> list[Provider]: inherited_pp_infos = cxx_inherited_preprocessor_infos(ctx.attrs.deps) inherited_link = cxx_inherited_link_info(ctx.attrs.deps) return [ DefaultInfo(default_output = ctx.attrs.src), cxx_merge_cpreprocessors(ctx, [], inherited_pp_infos), create_merged_link_info_for_propagation(ctx, inherited_link), CPrecompiledHeaderInfo(header = ctx.attrs.src), ] def cxx_test_impl(ctx: AnalysisContext) -> list[Provider]: link_strategy = to_link_strategy(cxx_attr_link_style(ctx)) link_group_info = get_link_group_info( ctx, filter_and_map_idx(LinkableGraph, cxx_attr_deps(ctx)), link_strategy, ) # TODO(T110378115): have the runinfo contain the correct test running args params = CxxRuleConstructorParams( rule_type = "cxx_test", headers_layout = cxx_get_regular_cxx_headers_layout(ctx), srcs = get_srcs_with_flags(ctx), link_group_info = link_group_info, auto_link_group_specs = get_auto_link_group_specs(ctx, link_group_info), prefer_stripped_objects = ctx.attrs.prefer_stripped_objects, extra_link_roots = linkables(ctx.attrs.link_group_deps), compiler_flags = ctx.attrs.compiler_flags, lang_compiler_flags = ctx.attrs.lang_compiler_flags, platform_compiler_flags = ctx.attrs.platform_compiler_flags, lang_platform_compiler_flags = ctx.attrs.lang_platform_compiler_flags, preprocessor_flags = ctx.attrs.preprocessor_flags, lang_preprocessor_flags = ctx.attrs.lang_preprocessor_flags, platform_preprocessor_flags = ctx.attrs.platform_preprocessor_flags, lang_platform_preprocessor_flags = ctx.attrs.lang_platform_preprocessor_flags, use_header_units = ctx.attrs.use_header_units, runtime_dependency_handling = cxx_attr_runtime_dependency_handling(ctx), error_handler = get_cxx_toolchain_info(ctx).cxx_error_handler, ) output = cxx_executable(ctx, params, is_cxx_test = True) command = [cmd_args(output.binary, hidden = output.runtime_files)] + ctx.attrs.args # Setup RE executors based on the `remote_execution` param. re_executor, executor_overrides = get_re_executors_from_props(ctx) return inject_test_run_info( ctx, ExternalRunnerTestInfo( type = "gtest", command = command, env = ctx.attrs.env, labels = ctx.attrs.labels, contacts = ctx.attrs.contacts, default_executor = re_executor, executor_overrides = executor_overrides, # We implicitly make this test via the project root, instead of # the cell root (e.g. fbcode root). run_from_project_root = ( "buck2_run_from_project_root" in (ctx.attrs.labels or []) or re_executor != None ), use_project_relative_paths = re_executor != None, ), ) + [ DefaultInfo( default_output = output.binary, other_outputs = output.runtime_files + output.external_debug_info_artifacts, sub_targets = output.sub_targets, ), output.compilation_db, output.xcode_data, output.dist_info, ] def _get_params_for_android_binary_cxx_library() -> (CxxRuleSubTargetParams, CxxRuleProviderParams): sub_target_params = CxxRuleSubTargetParams( argsfiles = False, compilation_database = False, headers = False, link_group_map = False, xcode_data = False, clang_traces = False, objects = False, bitcode_bundle = False, ) provider_params = CxxRuleProviderParams( compilation_database = False, omnibus_root = False, preprocessor_for_tests = False, cxx_resources_as_apple_resources = False, ) return sub_target_params, provider_params

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server