fwd/vendor/cxx/tools/buck/prelude/rules_impl.bzl
John Doty 9c435dc440 Vendor dependencies
Let's see how I like this workflow.
2022-12-19 08:38:22 -08:00

675 lines
32 KiB
Python

# 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.
# Android
load("@prelude//android:android.bzl", _android_extra_attributes = "extra_attributes", _android_implemented_rules = "implemented_rules")
load("@prelude//android:configuration.bzl", "is_building_android_binary_attr")
# Apple
load("@prelude//apple:apple_rules_impl.bzl", _apple_extra_attributes = "extra_attributes", _apple_implemented_rules = "implemented_rules")
# Configuration
load("@prelude//configurations:rules.bzl", _config_extra_attributes = "extra_attributes", _config_implemented_rules = "implemented_rules")
load("@prelude//cxx:cxx.bzl", "cxx_binary_impl", "cxx_library_impl", "cxx_precompiled_header_impl", "cxx_test_impl", "prebuilt_cxx_library_impl")
load("@prelude//cxx:cxx_toolchain.bzl", "cxx_toolchain_impl")
load("@prelude//cxx:cxx_toolchain_types.bzl", "CxxPlatformInfo", "CxxToolchainInfo", "DistLtoToolsInfo")
load("@prelude//cxx:debug.bzl", "SplitDebugMode")
# C++
load("@prelude//cxx:headers.bzl", "CPrecompiledHeaderInfo")
load("@prelude//cxx:omnibus.bzl", "omnibus_environment_attr")
load("@prelude//cxx:prebuilt_cxx_library_group.bzl", "prebuilt_cxx_library_group_impl")
load("@prelude//cxx/user:link_group_map.bzl", "link_group_map_attr")
load("@prelude//go:cgo_library.bzl", "cgo_library_impl")
load("@prelude//go:coverage.bzl", "GoCoverageMode")
# Go
load("@prelude//go:go_binary.bzl", "go_binary_impl")
load("@prelude//go:go_library.bzl", "go_library_impl")
load("@prelude//go:go_test.bzl", "go_test_impl")
load("@prelude//go:toolchain.bzl", "GoToolchainInfo")
# Haskell
load("@prelude//haskell:haskell.bzl", "HaskellLibraryProvider", "HaskellPlatformInfo", "HaskellToolchainInfo", "haskell_binary_impl", "haskell_library_impl", "haskell_prebuilt_library_impl")
load("@prelude//haskell:haskell_ghci.bzl", "haskell_ghci_impl")
load("@prelude//haskell:haskell_haddock.bzl", "haskell_haddock_impl")
load("@prelude//haskell:haskell_ide.bzl", "haskell_ide_impl")
# Http archive
load("@prelude//http_archive:http_archive.bzl", "http_archive_impl")
# Java
load("@prelude//java:java.bzl", _java_extra_attributes = "extra_attributes", _java_implemented_rules = "implemented_rules")
# JavaScript
load("@prelude//js:js.bzl", _js_extra_attributes = "extra_attributes", _js_implemented_rules = "implemented_rules")
# Kotlin
load("@prelude//kotlin:kotlin.bzl", _kotlin_extra_attributes = "extra_attributes", _kotlin_implemented_rules = "implemented_rules")
load("@prelude//linking:link_info.bzl", "LinkOrdering")
# Lua
load("@prelude//lua:cxx_lua_extension.bzl", "cxx_lua_extension_impl")
load("@prelude//lua:lua_binary.bzl", "lua_binary_impl")
load("@prelude//lua:lua_library.bzl", "lua_library_impl")
# OCaml
load("@prelude//ocaml:ocaml.bzl", "ocaml_binary_impl", "ocaml_library_impl", "ocaml_object_impl", "prebuilt_ocaml_library_impl")
load("@prelude//ocaml:providers.bzl", "OCamlPlatformInfo", "OCamlToolchainInfo")
# Python
load("@prelude//python:cxx_python_extension.bzl", "cxx_python_extension_impl")
load("@prelude//python:prebuilt_python_library.bzl", "prebuilt_python_library_impl")
load("@prelude//python:python_binary.bzl", "python_binary_impl")
load("@prelude//python:python_library.bzl", "python_library_impl")
load("@prelude//python:python_needed_coverage_test.bzl", "python_needed_coverage_test_impl")
load("@prelude//python:python_test.bzl", "python_test_impl")
load("@prelude//python:toolchain.bzl", "PythonPlatformInfo", "PythonToolchainInfo")
# Python Bootstrap
load("@prelude//python_bootstrap:python_bootstrap.bzl", "PythonBootstrapSources", "PythonBootstrapToolchainInfo", "python_bootstrap_binary_impl", "python_bootstrap_library_impl")
# Rust
load("@prelude//rust:rust_binary.bzl", "rust_binary_impl", "rust_test_impl")
load("@prelude//rust:rust_library.bzl", "prebuilt_rust_library_impl", "rust_library_impl")
load("@prelude//rust:rust_toolchain.bzl", "RustPlatformInfo", "RustToolchainInfo")
# Zip file
load("@prelude//zip_file:zip_file.bzl", _zip_file_extra_attributes = "extra_attributes", _zip_file_implemented_rules = "implemented_rules")
# General
load(":alias.bzl", "alias_impl", "configured_alias_impl", "versioned_alias_impl")
load(":attributes.bzl", "IncludeType", "LinkableDepType", "Linkage", "Platform", "attributes")
load(":command_alias.bzl", "command_alias_impl")
load(":export_file.bzl", "export_file_impl")
load(":filegroup.bzl", "filegroup_impl")
load(":genrule.bzl", "genrule_attributes", "genrule_impl")
load(":http_file.bzl", "http_file_impl")
load(":remote_file.bzl", "remote_file_impl")
load(":sh_binary.bzl", "sh_binary_impl")
load(":sh_test.bzl", "sh_test_impl")
load(":test_suite.bzl", "test_suite_impl")
# Other
load(":worker_tool.bzl", "worker_tool")
def _merge_dictionaries(dicts):
result = {}
for d in dicts:
for key, value in d.items():
if key in result:
fail("Duplicate key: '{}' while merging dictionaries".format(key))
result[key] = value
return result
implemented_rules = struct(
#common rules
alias = alias_impl,
command_alias = command_alias_impl,
configured_alias = configured_alias_impl,
export_file = export_file_impl,
filegroup = filegroup_impl,
genrule = genrule_impl,
http_archive = http_archive_impl,
http_file = http_file_impl,
remote_file = remote_file_impl,
sh_binary = sh_binary_impl,
sh_test = sh_test_impl,
test_suite = test_suite_impl,
versioned_alias = versioned_alias_impl,
worker_tool = worker_tool,
#c++
cxx_binary = cxx_binary_impl,
cxx_test = cxx_test_impl,
cxx_toolchain = cxx_toolchain_impl,
cxx_genrule = genrule_impl,
cxx_library = cxx_library_impl,
cxx_precompiled_header = cxx_precompiled_header_impl,
cxx_python_extension = cxx_python_extension_impl,
prebuilt_cxx_library = prebuilt_cxx_library_impl,
prebuilt_cxx_library_group = prebuilt_cxx_library_group_impl,
#go
cgo_library = cgo_library_impl,
go_binary = go_binary_impl,
go_library = go_library_impl,
go_test = go_test_impl,
#haskell
haskell_library = haskell_library_impl,
haskell_binary = haskell_binary_impl,
haskell_ghci = haskell_ghci_impl,
haskell_haddock = haskell_haddock_impl,
haskell_ide = haskell_ide_impl,
haskell_prebuilt_library = haskell_prebuilt_library_impl,
#lua
cxx_lua_extension = cxx_lua_extension_impl,
lua_binary = lua_binary_impl,
lua_library = lua_library_impl,
#ocaml
ocaml_binary = ocaml_binary_impl,
ocaml_object = ocaml_object_impl,
ocaml_library = ocaml_library_impl,
prebuilt_ocaml_library = prebuilt_ocaml_library_impl,
#python
prebuilt_python_library = prebuilt_python_library_impl,
python_binary = python_binary_impl,
python_library = python_library_impl,
python_test = python_test_impl,
python_needed_coverage_test = python_needed_coverage_test_impl,
#python bootstrap
python_bootstrap_binary = python_bootstrap_binary_impl,
python_bootstrap_library = python_bootstrap_library_impl,
#rust
rust_binary = rust_binary_impl,
rust_library = rust_library_impl,
prebuilt_rust_library = prebuilt_rust_library_impl,
rust_test = rust_test_impl,
#merged **kwargs
**_merge_dictionaries([
_android_implemented_rules,
_apple_implemented_rules,
_config_implemented_rules,
_java_implemented_rules,
_js_implemented_rules,
_kotlin_implemented_rules,
_zip_file_implemented_rules,
])
)
def _cxx_python_extension_attrs():
# cxx_python_extension is a subset of cxx_library, plus a base_module.
# So we can reuse cxx_library, we augment it with the additional attributes it defines.
# This isn't the ideal way to reuse it (we'd rather cxx_library was split it multiple reusable parts),
# but it's the pragmatic way of getting it working for now.
library = attributes["cxx_library"]
me = attributes["cxx_python_extension"]
res = {k: attrs.default_only(library[k]) for k in library if k not in me}
res.update({
"allow_embedding": attrs.bool(default = True),
# Copied from cxx_library.
"allow_huge_dwp": attrs.bool(default = False),
"allow_suffixing": attrs.bool(default = True),
"link_whole": attrs.default_only(attrs.bool(default = True)),
"precompiled_header": attrs.option(attrs.dep(providers = [CPrecompiledHeaderInfo]), default = None),
"preferred_linkage": attrs.default_only(attrs.string(default = "any")),
"use_link_groups": attrs.bool(default = False),
"_cxx_hacks": attrs.default_only(attrs.dep(default = "prelude//cxx/tools:cxx_hacks")),
"_cxx_toolchain": _cxx_toolchain(),
"_omnibus_environment": omnibus_environment_attr(),
# Copied from python_library.
"_python_toolchain": _python_toolchain(),
})
return res
def _python_test_attrs():
return {
"allow_huge_dwp": attrs.bool(default = False),
"bundled_runtime": attrs.bool(default = False),
"enable_distributed_thinlto": attrs.bool(default = False),
"package_split_dwarf_dwp": attrs.bool(default = False),
"remote_execution": attrs.option(attrs.dict(key = attrs.string(), value = attrs.string(), sorted = False)),
"resources": attrs.named_set(attrs.one_of(attrs.dep(), attrs.source(allow_directory = True)), sorted = True, default = []),
"_create_manifest_for_source_dir": _create_manifest_for_source_dir(),
"_cxx_hacks": attrs.default_only(attrs.dep(default = "prelude//cxx/tools:cxx_hacks")),
"_cxx_toolchain": _cxx_toolchain(),
"_omnibus_environment": omnibus_environment_attr(),
"_python_toolchain": _python_toolchain(),
"_target_os_type": _target_os_type(),
"_test_main": attrs.source(default = "prelude//python/tools:__test_main__.py"),
}
def _cxx_binary_and_test_attrs():
return {
"allow_huge_dwp": attrs.bool(default = False),
"auto_link_groups": attrs.bool(default = False),
# Linker flags that only apply to the executable link, used for link
# strategies (e.g. link groups) which may link shared libraries from
# top-level binary context.
"binary_linker_flags": attrs.list(attrs.arg(), default = []),
"bolt_flags": attrs.list(attrs.arg(), default = []),
"bolt_gdb_index": attrs.option(attrs.source(), default = None),
"bolt_profile": attrs.option(attrs.source(), default = None),
"enable_distributed_thinlto": attrs.bool(default = False),
"link_group_map": link_group_map_attr(),
"link_whole": attrs.default_only(attrs.bool(default = False)),
"precompiled_header": attrs.option(attrs.dep(providers = [CPrecompiledHeaderInfo]), default = None),
"resources": attrs.named_set(attrs.one_of(attrs.dep(), attrs.source(allow_directory = True)), sorted = True, default = []),
"use_link_groups": attrs.bool(default = False),
"_cxx_hacks": attrs.dep(default = "prelude//cxx/tools:cxx_hacks"),
"_cxx_toolchain": _cxx_toolchain(),
}
NativeLinkStrategy = ["separate", "native", "merged"]
def _package_python_binary_remotely():
return select({
"DEFAULT": False,
"ovr_config//os/constraints:android": True,
})
def _python_binary_attrs():
cxx_binary_attrs = {k: v for k, v in attributes["cxx_binary"].items()}
cxx_binary_attrs.update(_cxx_binary_and_test_attrs())
python_binary_attrs = attributes["python_binary"]
updated_attrs = {k: attrs.default_only(cxx_binary_attrs[k]) for k in cxx_binary_attrs if k not in python_binary_attrs}
# allow non-default value for the args below
updated_attrs.update({
"allow_huge_dwp": attrs.bool(default = False),
"auto_link_groups": attrs.bool(default = False),
"bundled_runtime": attrs.bool(default = False),
"cxx_main": attrs.option(attrs.source(), default = None),
"enable_distributed_thinlto": attrs.bool(default = False),
"executable_deps": attrs.list(attrs.dep(), default = []),
"executable_name": attrs.option(attrs.string(), default = None),
"link_group_map": link_group_map_attr(),
"link_style": attrs.enum(LinkableDepType, default = "static"),
"native_link_strategy": attrs.option(attrs.enum(NativeLinkStrategy), default = None),
"package_split_dwarf_dwp": attrs.bool(default = False),
"par_style": attrs.option(attrs.string(), default = None),
"use_link_groups": attrs.bool(default = False),
"_create_manifest_for_source_dir": _create_manifest_for_source_dir(),
"_cxx_hacks": attrs.default_only(attrs.dep(default = "prelude//cxx/tools:cxx_hacks")),
"_cxx_toolchain": _cxx_toolchain(),
"_omnibus_environment": omnibus_environment_attr(),
"_package_remotely": attrs.bool(default = _package_python_binary_remotely()),
"_python_toolchain": _python_toolchain(),
"_target_os_type": _target_os_type(),
})
return updated_attrs
def _toolchain(lang: str.type, providers: [""]) -> "attribute":
return attrs.default_only(attrs.toolchain_dep(default = "toolchains//:" + lang, providers = providers))
def _cxx_toolchain():
return _toolchain("cxx", [CxxToolchainInfo, CxxPlatformInfo])
def _haskell_toolchain():
return _toolchain("haskell", [HaskellToolchainInfo, HaskellPlatformInfo])
def _rust_toolchain():
return _toolchain("rust", [RustToolchainInfo, RustPlatformInfo])
def _go_toolchain():
return _toolchain("go", [GoToolchainInfo])
def _ocaml_toolchain():
return _toolchain("ocaml", [OCamlToolchainInfo, OCamlPlatformInfo])
def _python_toolchain():
return _toolchain("python", [PythonToolchainInfo, PythonPlatformInfo])
def _python_bootstrap_toolchain():
return _toolchain("python_bootstrap", [PythonBootstrapToolchainInfo])
def _target_os_type() -> "attribute":
# FIXME: prelude// should be standalone (not refer to ovr_config//)
return attrs.enum(Platform, default = select({
"DEFAULT": "linux",
"ovr_config//os:macos": "macos",
"ovr_config//os:windows": "windows",
}))
def _create_manifest_for_source_dir():
return attrs.exec_dep(default = "prelude//python/tools:create_manifest_for_source_dir")
inlined_extra_attributes = {
# go
"cgo_library": {
"_cxx_toolchain": _cxx_toolchain(),
"_go_toolchain": _go_toolchain(),
},
"command_alias": {
"_find_and_replace_bat": attrs.default_only(attrs.exec_dep(default = "prelude//tools:find_and_replace.bat")),
"_target_os_type": _target_os_type(),
},
# The 'actual' attribute of configured_alias is a configured_label, which is
# currently unimplemented. Map it to dep so we can simply forward the providers.
"configured_alias": {
# TODO(nga): "actual" attribute exists here only to display it in query,
# actual `actual` attribute used in rule implementation is named `configured_actual`.
# Logically this should be `attrs.configuration_label`, but `configuration_label`
# is currently an alias for `attrs.dep`, which makes non-transitioned dependency
# also a dependency along with transitioned dependency. (See D40255132).
"actual": attrs.label(),
# We use a separate field instead of re-purposing `actual`, as we want
# to keep output format compatibility with v1.
"configured_actual": attrs.option(attrs.configured_dep()),
# If `configured_actual` is `None`, fallback to this unconfigured dep.
"fallback_actual": attrs.option(attrs.dep()),
"platform": attrs.option(attrs.configuration_label()),
},
"cxx_binary": _cxx_binary_and_test_attrs(),
#c++
"cxx_genrule": genrule_attributes() | {
"_cxx_toolchain": _cxx_toolchain(),
"_target_os_type": _target_os_type(),
},
"cxx_library": {
"allow_huge_dwp": attrs.bool(default = False),
"deps_query": attrs.option(attrs.query(), default = None),
"extra_xcode_sources": attrs.list(attrs.source(allow_directory = True), default = []),
"force_emit_omnibus_shared_root": attrs.bool(default = False),
"link_deps_query_whole": attrs.bool(default = False),
"link_group_map": link_group_map_attr(),
"precompiled_header": attrs.option(attrs.dep(providers = [CPrecompiledHeaderInfo]), default = None),
"prefer_stripped_objects": attrs.bool(default = False),
"preferred_linkage": attrs.enum(Linkage, default = "any"),
"resources": attrs.named_set(attrs.one_of(attrs.dep(), attrs.source(allow_directory = True)), sorted = True, default = []),
"supports_python_dlopen": attrs.option(attrs.bool(), default = None),
"use_link_groups": attrs.bool(default = False),
"_cxx_hacks": attrs.default_only(attrs.dep(default = "prelude//cxx/tools:cxx_hacks")),
"_cxx_toolchain": _cxx_toolchain(),
"_is_building_android_binary": is_building_android_binary_attr(),
"_omnibus_environment": omnibus_environment_attr(),
},
"cxx_python_extension": _cxx_python_extension_attrs(),
"cxx_test": dict(
remote_execution = attrs.option(attrs.dict(key = attrs.string(), value = attrs.string(), sorted = False)),
**_cxx_binary_and_test_attrs()
),
"cxx_toolchain": {
"archiver": attrs.dep(providers = [RunInfo]),
"archiver_supports_argfiles": attrs.bool(default = False),
"asm_compiler": attrs.option(attrs.dep(providers = [RunInfo]), default = None),
"asm_preprocessor": attrs.option(attrs.dep(providers = [RunInfo]), default = None),
"assembler": attrs.dep(providers = [RunInfo]),
"assembler_preprocessor": attrs.option(attrs.dep(providers = [RunInfo]), default = None),
"bolt_enabled": attrs.bool(default = False),
"c_compiler": attrs.dep(providers = [RunInfo]),
"cxx_compiler": attrs.dep(providers = [RunInfo]),
"link_ordering": attrs.enum(LinkOrdering.values(), default = "preorder"),
"linker": attrs.dep(providers = [RunInfo]),
"nm": attrs.dep(providers = [RunInfo]),
"objcopy_for_shared_library_interface": attrs.dep(providers = [RunInfo]),
# Used for resolving any 'platform_*' attributes.
"platform_name": attrs.option(attrs.string(), default = None),
"private_headers_symlinks_enabled": attrs.bool(default = True),
"public_headers_symlinks_enabled": attrs.bool(default = True),
"ranlib": attrs.option(attrs.dep(providers = [RunInfo]), default = None),
"requires_objects": attrs.bool(default = False),
"split_debug_mode": attrs.enum(SplitDebugMode.values(), default = "none"),
"strip": attrs.dep(providers = [RunInfo]),
"supports_distributed_thinlto": attrs.bool(default = False),
"use_archiver_flags": attrs.bool(default = True),
"use_dep_files": attrs.option(attrs.bool(), default = None),
"_dep_files_processor": attrs.dep(providers = [RunInfo], default = "prelude//cxx/tools:makefile_to_dep_file"),
"_dist_lto_tools": attrs.default_only(attrs.dep(providers = [DistLtoToolsInfo], default = "prelude//cxx/dist_lto/tools:dist_lto_tools")),
"_mk_comp_db": attrs.default_only(attrs.dep(providers = [RunInfo], default = "prelude//cxx/tools:make_comp_db")),
# FIXME: prelude// should be standalone (not refer to fbsource//)
"_mk_hmap": attrs.default_only(attrs.dep(providers = [RunInfo], default = "fbsource//xplat/buck2/tools/cxx:hmap_wrapper")),
},
"export_file": {
"src": attrs.source(allow_directory = True),
},
"filegroup": {
"srcs": attrs.named_set(attrs.source(allow_directory = True), sorted = False, default = []),
},
"genrule": genrule_attributes() | {
"env": attrs.dict(key = attrs.string(), value = attrs.arg(), sorted = False, default = {}),
"srcs": attrs.named_set(attrs.source(allow_directory = True), sorted = False, default = []),
"_target_os_type": _target_os_type(),
},
"go_binary": {
"resources": attrs.list(attrs.one_of(attrs.dep(), attrs.source(allow_directory = True)), default = []),
"_go_toolchain": _go_toolchain(),
},
"go_library": {
"_go_toolchain": _go_toolchain(),
},
"go_test": {
"coverage_mode": attrs.option(attrs.enum(GoCoverageMode.values()), default = None),
"resources": attrs.list(attrs.source(allow_directory = True), default = []),
"_go_toolchain": _go_toolchain(),
"_testmaingen": attrs.default_only(attrs.exec_dep(default = "prelude//go/tools:testmaingen")),
},
# groovy
"groovy_library": {
"resources_root": attrs.option(attrs.string(), default = None),
},
"groovy_test": {
"resources_root": attrs.option(attrs.string(), default = None),
},
"haskell_binary": {
"template_deps": attrs.list(attrs.exec_dep(providers = [HaskellLibraryProvider]), default = []),
"_cxx_toolchain": _cxx_toolchain(),
"_haskell_toolchain": _haskell_toolchain(),
},
"haskell_library": {
"preferred_linkage": attrs.enum(Linkage, default = "any"),
"template_deps": attrs.list(attrs.exec_dep(providers = [HaskellLibraryProvider]), default = []),
"_cxx_toolchain": _cxx_toolchain(),
"_haskell_toolchain": _haskell_toolchain(),
},
# http things get only 1 hash in v1 but in v2 we allow multiple. Also,
# don't default hashes to empty strings.
"http_archive": {
"sha1": attrs.option(attrs.string()),
"sha256": attrs.option(attrs.string()),
"_create_exclusion_list": attrs.default_only(attrs.exec_dep(default = "prelude//http_archive/tools:create_exclusion_list")),
},
"http_file": {
"sha1": attrs.option(attrs.string()),
"sha256": attrs.option(attrs.string()),
},
#ocaml
"ocaml_binary": {
"_cxx_toolchain": _cxx_toolchain(),
"_ocaml_toolchain": _ocaml_toolchain(),
},
"ocaml_library": {
"_cxx_toolchain": _cxx_toolchain(),
"_ocaml_toolchain": _ocaml_toolchain(),
},
"ocaml_object": {
"bytecode_only": attrs.option(attrs.bool(), default = None),
"compiler_flags": attrs.list(attrs.arg(), default = []),
"contacts": attrs.list(attrs.string(), default = []),
"default_host_platform": attrs.option(attrs.configuration_label(), default = None),
"deps": attrs.list(attrs.dep(), default = []),
"labels": attrs.list(attrs.string(), default = []),
"licenses": attrs.list(attrs.source(), default = []),
"linker_flags": attrs.list(attrs.string(), default = []),
"ocamldep_flags": attrs.list(attrs.arg(), default = []),
"platform": attrs.option(attrs.string(), default = None),
"platform_deps": attrs.list(attrs.tuple(attrs.regex(), attrs.set(attrs.dep(), sorted = True)), default = []),
"platform_linker_flags": attrs.list(attrs.tuple(attrs.regex(), attrs.list(attrs.string())), default = []),
"srcs": attrs.option(attrs.named_set(attrs.source(), sorted = False), default = None),
"warnings_flags": attrs.option(attrs.string(), default = None),
"within_view": attrs.option(attrs.list(attrs.string())),
"_cxx_toolchain": _cxx_toolchain(),
"_ocaml_toolchain": _ocaml_toolchain(),
},
"prebuilt_cxx_library": {
"exported_header_style": attrs.enum(IncludeType, default = "system"),
"header_dirs": attrs.option(attrs.list(attrs.source(allow_directory = True)), default = None),
"platform_header_dirs": attrs.option(attrs.list(attrs.tuple(attrs.regex(), attrs.list(attrs.source(allow_directory = True)))), default = None),
"preferred_linkage": attrs.enum(Linkage, default = "any"),
"public_include_directories": attrs.set(attrs.string(), sorted = True, default = []),
"public_system_include_directories": attrs.set(attrs.string(), sorted = True, default = []),
"raw_headers": attrs.set(attrs.source(), sorted = True, default = []),
"supports_python_dlopen": attrs.option(attrs.bool(), default = None),
"versioned_header_dirs": attrs.option(attrs.versioned(attrs.list(attrs.source(allow_directory = True))), default = None),
"_cxx_toolchain": _cxx_toolchain(),
"_omnibus_environment": omnibus_environment_attr(),
},
"prebuilt_ocaml_library": {
# These fields in 'attributes.bzl' are wrong.
#
# There they are defined in terms of `attrs.string()`. This
# block overrides/corrects them here so as to be in terms of
# `attrs.source()`.
"bytecode_c_libs": attrs.list(attrs.source(), default = []),
"bytecode_lib": attrs.option(attrs.source()),
"c_libs": attrs.list(attrs.source(), default = []),
"include_dir": attrs.option(attrs.source(allow_directory = True)),
"lib_dir": attrs.option(attrs.source(allow_directory = True)),
"native_c_libs": attrs.list(attrs.source(), default = []),
"native_lib": attrs.option(attrs.source()),
},
#python
"prebuilt_python_library": {
"_create_manifest_for_source_dir": _create_manifest_for_source_dir(),
"_extract": attrs.default_only(attrs.exec_dep(default = "prelude//python/tools:extract")),
"_python_toolchain": _python_toolchain(),
},
"prebuilt_rust_library": {
"_cxx_toolchain": _cxx_toolchain(),
"_rust_toolchain": _rust_toolchain(),
},
"python_binary": _python_binary_attrs(),
#python bootstrap
"python_bootstrap_binary": {
"deps": attrs.list(attrs.dep(providers = [PythonBootstrapSources]), default = []),
"main": attrs.source(),
"_python_bootstrap_toolchain": _python_bootstrap_toolchain(),
"_target_os_type": _target_os_type(),
"_win_python_wrapper": attrs.default_only(attrs.exec_dep(default = "prelude//python_bootstrap/tools:win_python_wrapper")),
},
"python_bootstrap_library": {
"srcs": attrs.list(attrs.source()),
},
"python_library": {
"allow_huge_dwp": attrs.bool(default = False),
"resources": attrs.named_set(attrs.one_of(attrs.dep(), attrs.source(allow_directory = True)), sorted = True, default = []),
"_create_manifest_for_source_dir": _create_manifest_for_source_dir(),
"_cxx_toolchain": _cxx_toolchain(),
"_python_toolchain": _python_toolchain(),
},
"python_needed_coverage_test": {
"contacts": attrs.list(attrs.string(), default = []),
"env": attrs.dict(key = attrs.string(), value = attrs.arg(), sorted = False, default = {}),
"labels": attrs.list(attrs.string(), default = []),
"needed_coverage": attrs.list(attrs.tuple(attrs.int(), attrs.dep(), attrs.option(attrs.string())), default = []),
"remote_execution": attrs.option(attrs.dict(key = attrs.string(), value = attrs.string(), sorted = False)),
"test": attrs.dep(providers = [ExternalRunnerTestInfo]),
},
"python_test": _python_test_attrs(),
"remote_file": {
"sha1": attrs.option(attrs.string()),
"sha256": attrs.option(attrs.string()),
"_unzip_tool": attrs.default_only(attrs.exec_dep(providers = [RunInfo], default = "prelude//zip_file/tools:unzip")),
},
#rust
"rust_binary": {
"incremental_build_mode": attrs.option(attrs.string()),
"incremental_enabled": attrs.bool(default = False),
"resources": attrs.named_set(attrs.one_of(attrs.dep(), attrs.source()), sorted = True, default = []),
"_cxx_toolchain": _cxx_toolchain(),
"_rust_toolchain": _rust_toolchain(),
},
"rust_library": {
# linker_flags weren't supported for rust_library in Buck v1 but the
# fbcode macros pass them anyway. They're typically empty since the
# config-level flags don't get injected, but it doesn't hurt to accept
# them and it simplifies the implementation of Rust rules since they
# don't have to know whether we're building a rust_binary or a
# rust_library.
"incremental_build_mode": attrs.option(attrs.string()),
"incremental_enabled": attrs.bool(default = False),
"linker_flags": attrs.list(attrs.arg(), default = []),
"preferred_linkage": attrs.enum(Linkage, default = "any"),
"resources": attrs.named_set(attrs.one_of(attrs.dep(), attrs.source()), sorted = True, default = []),
"supports_python_dlopen": attrs.option(attrs.bool(), default = None),
"_cxx_toolchain": _cxx_toolchain(),
"_omnibus_environment": omnibus_environment_attr(),
"_rust_toolchain": _rust_toolchain(),
},
"rust_test": {
"framework": attrs.bool(default = True),
"incremental_build_mode": attrs.option(attrs.string()),
"incremental_enabled": attrs.bool(default = False),
"remote_execution": attrs.option(attrs.dict(key = attrs.string(), value = attrs.string(), sorted = False)),
"resources": attrs.named_set(attrs.one_of(attrs.dep(), attrs.source()), sorted = True, default = []),
"_cxx_toolchain": _cxx_toolchain(),
"_rust_toolchain": _rust_toolchain(),
},
# scala
"scala_library": {
"resources_root": attrs.option(attrs.string(), default = None),
},
"scala_test": {
"resources_root": attrs.option(attrs.string(), default = None),
},
"sh_binary": {
"resources": attrs.list(attrs.source(allow_directory = True), default = []),
"_target_os_type": _target_os_type(),
},
"sh_test": {
"list_args": attrs.option(attrs.list(attrs.string()), default = None),
"list_env": attrs.option(attrs.dict(key = attrs.string(), value = attrs.string(), sorted = False), default = None),
"run_args": attrs.list(attrs.string(), default = []),
"run_env": attrs.dict(key = attrs.string(), value = attrs.string(), sorted = False, default = {}),
"test": attrs.option(attrs.one_of(attrs.dep(), attrs.source()), default = None),
},
"test_suite": {
# On buck1 query, tests attribute on test_suite is treated as deps, while on buck2 it is not.
# While buck2's behavior makes more sense, we want to preserve buck1 behavior on test_suite for now to make TD behavior match between buck1 and buck2.
# This diff makes the behaviors match by adding a test_deps attribute to test_suite on buck2 that is used as a deps attribute. In the macro layer, we set test_deps = tests if we are using buck2.
# For more context: https://fb.prod.workplace.com/groups/603286664133355/posts/682567096205311/?comment_id=682623719532982&reply_comment_id=682650609530293
"test_deps": attrs.list(attrs.dep(), default = []),
},
"worker_tool": {
# overridden to handle buck1's use of @Value.Default
"args": attrs.one_of(attrs.arg(), attrs.list(attrs.arg()), default = []),
# FIXME: prelude// should be standalone (not refer to fbsource//)
"_worker_tool_runner": attrs.default_only(attrs.dep(default = "fbsource//xplat/buck2/tools/worker:worker_tool_runner")),
},
}
all_extra_attributes = _merge_dictionaries([
inlined_extra_attributes,
_android_extra_attributes,
_apple_extra_attributes,
_config_extra_attributes,
_java_extra_attributes,
_js_extra_attributes,
_kotlin_extra_attributes,
_zip_file_extra_attributes,
])
# Inject test toolchain in all tests.
for rule in [
"sh_test",
"rust_test",
"python_test",
"python_needed_coverage_test",
"java_test",
"go_test",
"cxx_test",
"apple_test",
"android_instrumentation_test",
"kotlin_test",
"robolectric_test",
]:
# NOTE: We make this a `dep` not an `exec_dep` even though we'll execute
# it, because it needs to execute in the same platform as the test itself
# (we run tests in the target platform not the exec platform, since the
# goal is to test the code that is being built!).
all_extra_attributes[rule] = _merge_dictionaries([all_extra_attributes[rule], {
"_inject_test_env": attrs.default_only(attrs.dep(default = "prelude//test/tools:inject_test_env")),
}])
extra_attributes = struct(**all_extra_attributes)