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

250 lines
11 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.
# Rules for mapping requirements to options
load(
"@prelude//linking:link_info.bzl",
"LinkStyle",
"Linkage", # @unused Used as a type
)
load("@prelude//utils:utils.bzl", "expect")
# --crate-type=
# Excludes `lib` because we want to explicitly choose the library flavour
CrateType = enum(
# Binary
"bin",
# Rust linkage
"rlib",
"dylib",
"proc-macro",
# Native linkage
"cdylib",
"staticlib",
)
# Crate type is intended for consumption by Rust code
def crate_type_rust_linkage(crate_type: CrateType.type) -> bool.type:
return crate_type.value in ("rlib", "dylib", "proc-macro")
# Crate type is intended for native linkage (eg C++)
def crate_type_native_linkage(crate_type: CrateType.type) -> bool.type:
return crate_type.value in ("cdylib", "staticlib")
# Crate type which invokes the linker
def crate_type_linked(crate_type: CrateType.type) -> bool.type:
return crate_type.value in ("bin", "dylib", "proc-macro", "cdylib")
# Crate type which should include transitive deps
def crate_type_transitive_deps(crate_type: CrateType.type) -> bool.type:
return crate_type.value in ("rlib", "dylib", "staticlib") # not sure about staticlib
# Crate type which should always need codegen
def crate_type_codegen(crate_type: CrateType.type) -> bool.type:
return crate_type_linked(crate_type) or crate_type_native_linkage(crate_type)
# -Crelocation-model= from --print relocation-models
RelocModel = enum(
# Common
"static",
"pic",
# Various obscure types
"dynamic-no-pic",
"ropi",
"rwpi",
"ropi-rwpi",
"default",
)
# --emit=
Emit = enum(
"asm",
"llvm-bc",
"llvm-ir",
"obj",
"metadata",
"link",
"dep-info",
"mir",
"save-analysis", # pseudo emit alias for metadata + -Zsave-analysis
"expand", # pseudo emit alias for -Zunpretty=expanded
)
# Emitting this artifact generates code
def emit_needs_codegen(emit: Emit.type) -> bool.type:
return emit.value in ("asm", "llvm-bc", "llvm-ir", "obj", "link", "mir")
BuildParams = record(
crate_type = field(CrateType.type),
reloc_model = field(RelocModel.type),
dep_link_style = field(LinkStyle.type), # what link_style to use for dependencies
# XXX This needs to be OS-specific
prefix = field(str.type),
suffix = field(str.type),
)
RustcFlags = record(
crate_type = field(CrateType.type),
reloc_model = field(RelocModel.type),
dep_link_style = field(LinkStyle.type),
)
# Filenames used for various emitted forms
# `None` for a prefix or suffix means use the build_param version
_EMIT_PREFIX_SUFFIX = {
Emit("asm"): ("", ".s"),
Emit("llvm-bc"): ("", ".bc"),
Emit("llvm-ir"): ("", ".ll"),
Emit("obj"): ("", ".o"),
Emit("metadata"): ("lib", ".rmeta"), # even binaries get called 'libfoo.rmeta'
Emit("link"): (None, None), # crate type and reloc model dependent
Emit("dep-info"): ("", ".d"),
Emit("mir"): (None, ".mir"),
Emit("expand"): (None, ".rs"),
Emit("save-analysis"): (None, ".json"),
}
# Return the filename for a particular emitted artifact type
def output_filename(cratename: str.type, emit: Emit.type, buildparams: BuildParams.type, extra: [str.type, None] = None) -> str.type:
epfx, esfx = _EMIT_PREFIX_SUFFIX[emit]
prefix = epfx if epfx != None else buildparams.prefix
suffix = esfx if esfx != None else buildparams.suffix
return prefix + cratename + (extra or "") + suffix
# Rule type - 'binary' also covers 'test'
RuleType = enum("binary", "library")
# What language we're generating artifacts to be linked with
LinkageLang = enum("rust", "c++")
_BINARY_SHARED = 0
_BINARY_PIE = 1
_BINARY_NON_PIE = 2
_NATIVE_LINKABLE_SHARED_OBJECT = 3
_RUST_DYLIB_SHARED = 4
_RUST_PROC_MACRO = 5
_RUST_STATIC_PIC_LIBRARY = 6
_RUST_STATIC_NON_PIC_LIBRARY = 7
_NATIVE_LINKABLE_STATIC_PIC = 8
_NATIVE_LINKABLE_STATIC_NON_PIC = 9
# FIXME: This isn't right! We should be using the target platform, rather than host_info.
# On Windows the GNU linker emits .exe/.dll, while on Linux it emits nothing/.so, use this variable to switch.
#
# At the moment we don't have anything working on Windows, so trying to get cross-compiling working is a step
# further than we want to take. But this will need cleaning up for Windows hosts to be able to cross-compile.
_FIXME_IS_WINDOWS = host_info().os.is_windows
def _executable_prefix_suffix(platform):
return {
"darwin": ("", ""),
"gnu": ("", ".exe") if _FIXME_IS_WINDOWS else ("", ""),
"windows": ("", ".exe"),
}[platform]
def _library_prefix_suffix(platform):
return {
"darwin": ("lib", ".dylib"),
"gnu": ("", ".dll") if _FIXME_IS_WINDOWS else ("lib", ".so"),
"windows": ("", ".dll"),
}[platform]
_BUILD_PARAMS = {
_BINARY_SHARED: (RustcFlags(crate_type = CrateType("bin"), reloc_model = RelocModel("pic"), dep_link_style = LinkStyle("shared")), _executable_prefix_suffix),
_BINARY_PIE: (RustcFlags(crate_type = CrateType("bin"), reloc_model = RelocModel("pic"), dep_link_style = LinkStyle("static_pic")), _executable_prefix_suffix),
_BINARY_NON_PIE: (RustcFlags(crate_type = CrateType("bin"), reloc_model = RelocModel("static"), dep_link_style = LinkStyle("static")), _executable_prefix_suffix),
_NATIVE_LINKABLE_SHARED_OBJECT: (RustcFlags(crate_type = CrateType("cdylib"), reloc_model = RelocModel("pic"), dep_link_style = LinkStyle("shared")), _library_prefix_suffix),
_RUST_DYLIB_SHARED: (RustcFlags(crate_type = CrateType("dylib"), reloc_model = RelocModel("pic"), dep_link_style = LinkStyle("shared")), _library_prefix_suffix),
_RUST_PROC_MACRO: (RustcFlags(crate_type = CrateType("proc-macro"), reloc_model = RelocModel("pic"), dep_link_style = LinkStyle("static_pic")), _library_prefix_suffix),
_RUST_STATIC_PIC_LIBRARY: (RustcFlags(crate_type = CrateType("rlib"), reloc_model = RelocModel("pic"), dep_link_style = LinkStyle("static_pic")), lambda _: ("lib", ".rlib")),
_RUST_STATIC_NON_PIC_LIBRARY: (RustcFlags(crate_type = CrateType("rlib"), reloc_model = RelocModel("static"), dep_link_style = LinkStyle("static")), lambda _: ("lib", ".rlib")),
_NATIVE_LINKABLE_STATIC_PIC: (RustcFlags(crate_type = CrateType("staticlib"), reloc_model = RelocModel("pic"), dep_link_style = LinkStyle("static_pic")), lambda _: ("lib", "_pic.a")),
_NATIVE_LINKABLE_STATIC_NON_PIC: (RustcFlags(crate_type = CrateType("staticlib"), reloc_model = RelocModel("static"), dep_link_style = LinkStyle("static")), lambda _: ("lib", ".a")),
}
_INPUTS = {
# Binary, shared
("binary", False, "shared", "any", "rust"): _BINARY_SHARED,
("binary", False, "shared", "shared", "rust"): _BINARY_SHARED,
("binary", False, "shared", "static", "rust"): _BINARY_SHARED,
# Binary, PIE
("binary", False, "static_pic", "any", "rust"): _BINARY_PIE,
("binary", False, "static_pic", "shared", "rust"): _BINARY_PIE,
("binary", False, "static_pic", "static", "rust"): _BINARY_PIE,
# Binary, non-PIE
("binary", False, "static", "any", "rust"): _BINARY_NON_PIE,
("binary", False, "static", "shared", "rust"): _BINARY_NON_PIE,
("binary", False, "static", "static", "rust"): _BINARY_NON_PIE,
# Native linkable shared object
("library", False, "shared", "any", "c++"): _NATIVE_LINKABLE_SHARED_OBJECT,
("library", False, "shared", "shared", "c++"): _NATIVE_LINKABLE_SHARED_OBJECT,
("library", False, "static", "shared", "c++"): _NATIVE_LINKABLE_SHARED_OBJECT,
("library", False, "static_pic", "shared", "c++"): _NATIVE_LINKABLE_SHARED_OBJECT,
# Rust dylib shared object
("library", False, "shared", "any", "rust"): _RUST_DYLIB_SHARED,
("library", False, "shared", "shared", "rust"): _RUST_DYLIB_SHARED,
("library", False, "static", "shared", "rust"): _RUST_DYLIB_SHARED,
("library", False, "static_pic", "shared", "rust"): _RUST_DYLIB_SHARED,
# Rust proc-macro
("library", True, "shared", "any", "rust"): _RUST_PROC_MACRO,
("library", True, "shared", "shared", "rust"): _RUST_PROC_MACRO,
("library", True, "shared", "static", "rust"): _RUST_PROC_MACRO,
("library", True, "static", "any", "rust"): _RUST_PROC_MACRO,
("library", True, "static", "shared", "rust"): _RUST_PROC_MACRO,
("library", True, "static", "static", "rust"): _RUST_PROC_MACRO,
("library", True, "static_pic", "any", "rust"): _RUST_PROC_MACRO,
("library", True, "static_pic", "shared", "rust"): _RUST_PROC_MACRO,
("library", True, "static_pic", "static", "rust"): _RUST_PROC_MACRO,
# Rust static_pic library
("library", False, "shared", "static", "rust"): _RUST_STATIC_PIC_LIBRARY,
("library", False, "static_pic", "any", "rust"): _RUST_STATIC_PIC_LIBRARY,
("library", False, "static_pic", "static", "rust"): _RUST_STATIC_PIC_LIBRARY,
# Rust static (non-pic) library
("library", False, "static", "any", "rust"): _RUST_STATIC_NON_PIC_LIBRARY,
("library", False, "static", "static", "rust"): _RUST_STATIC_NON_PIC_LIBRARY,
# Native linkable static_pic
("library", False, "shared", "static", "c++"): _NATIVE_LINKABLE_STATIC_PIC,
("library", False, "static_pic", "any", "c++"): _NATIVE_LINKABLE_STATIC_PIC,
("library", False, "static_pic", "static", "c++"): _NATIVE_LINKABLE_STATIC_PIC,
# Native linkable static non-pic
("library", False, "static", "any", "c++"): _NATIVE_LINKABLE_STATIC_NON_PIC,
("library", False, "static", "static", "c++"): _NATIVE_LINKABLE_STATIC_NON_PIC,
}
# Compute crate type, relocation model and name mapping given what rule we're building,
# whether its a proc-macro, linkage information and language.
def build_params(
rule: RuleType.type,
proc_macro: bool.type,
link_style: LinkStyle.type,
preferred_linkage: Linkage.type,
lang: LinkageLang.type,
linker_type: str.type) -> BuildParams.type:
input = (rule.value, proc_macro, link_style.value, preferred_linkage.value, lang.value)
expect(
input in _INPUTS,
"missing case for rule_type={} proc_macro={} link_style={} preferred_linkage={} lang={}",
rule,
proc_macro,
link_style,
preferred_linkage,
lang,
)
build_kind_key = _INPUTS[input]
(flags, platform_to_affix) = _BUILD_PARAMS[build_kind_key]
(prefix, suffix) = platform_to_affix(linker_type)
return BuildParams(
crate_type = flags.crate_type,
reloc_model = flags.reloc_model,
dep_link_style = flags.dep_link_style,
prefix = prefix,
suffix = suffix,
)