121 lines
4.3 KiB
Python
121 lines
4.3 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.
|
|
|
|
# Providers for OCaml build rules.
|
|
|
|
load("@prelude//utils:utils.bzl", "flatten")
|
|
|
|
OCamlToolchainInfo = provider(fields = [
|
|
"ocaml_compiler",
|
|
# [Note: What is `binutils_ld`?]
|
|
# ------------------------------
|
|
# When the compiler is invoked in partial linking mode (`ocamlopt.opt
|
|
# -output-obj ...`) it makes naked calls to `ld`. In such a case, if we
|
|
# don't arrange to execute `ocamlopt.opt` in an environment where `ld`
|
|
# resolves to an `ld` that is either the `ld` in scope when the compiler was
|
|
# built (or at least compatible with it) it then a call to the system `ld`
|
|
# will result and almost certainly be a mismatch.
|
|
#
|
|
# How the compiler invokes `ld` is established when it's built by its
|
|
# configure script
|
|
# (https://github.com/ocaml/ocaml/blob/f27d671b23f5246d37d91571eeccb802d5399a0b/configure.ac).
|
|
#
|
|
# So far I've found `fbcode//.../binutils:bin/ld` to be a choice that works.
|
|
# It's in `_mk_ocaml_opt` in `ocaml.bzl` where we make use of this.
|
|
"binutils_ld",
|
|
"binutils_as",
|
|
"dep_tool",
|
|
"yacc_compiler",
|
|
"menhir_compiler",
|
|
"lex_compiler",
|
|
"libc", # MergedLinkInfo of libc
|
|
"ocaml_bytecode_compiler",
|
|
"debug",
|
|
"interop_includes",
|
|
"warnings_flags",
|
|
"ocaml_compiler_flags",
|
|
])
|
|
|
|
# Stores "platform"/flavor name used to resolve *platform_* arguments
|
|
OCamlPlatformInfo = provider(fields = [
|
|
"name",
|
|
])
|
|
|
|
# A list of `OCamlLibraryInfo`s.
|
|
OCamlLinkInfo = provider(
|
|
# Contains a list of OCamlLibraryInfo records
|
|
fields = ["info"],
|
|
)
|
|
|
|
# A record of an OCaml library.
|
|
OCamlLibraryInfo = record(
|
|
# The library target name: e.g. "`foo`"
|
|
name = str.type,
|
|
# The full library target: e.g. "`fbcode//...:foo`"
|
|
target = "label",
|
|
# .a (C archives e.g. `libfoo_stubs.a`)
|
|
c_libs = ["artifact"],
|
|
# .o (Native compiler produced stubs)
|
|
stbs_nat = ["artifact"],
|
|
# .o (Bytecode compiler produced stubs)
|
|
stbs_byt = ["artifact"],
|
|
# .cma (Bytecode compiler module archives e.g. `libfoo.cma`)
|
|
cmas = ["artifact"],
|
|
# .cmxa (Native compiler module archives e.g. `libfoo.cmxa`)
|
|
cmxas = ["artifact"],
|
|
# .cmi (Native compiled module interfaces)
|
|
cmis_nat = ["artifact"],
|
|
# .cmi (Bytecode compiled module interfaces)
|
|
cmis_byt = ["artifact"],
|
|
# .cmo (Bytecode compiled modules - bytecode)
|
|
cmos = ["artifact"],
|
|
# .cmx (Compiled modules - native)
|
|
cmxs = ["artifact"],
|
|
# .cmt (Native compiler produced typed abstract syntax trees)
|
|
cmts_nat = ["artifact"],
|
|
# .cmt (Bytecode compiler produced typed abstract syntax trees)
|
|
cmts_byt = ["artifact"],
|
|
# .cmti (Native compiler produced typed abstract syntax trees)
|
|
cmtis_nat = ["artifact"],
|
|
# .cmti (Bytecode compiler produced typed abstract syntax trees)
|
|
cmtis_byt = ["artifact"],
|
|
# Compile flags for native clients who use this library.
|
|
include_dirs_nat = ["cmd_args"],
|
|
# Compile flags for bytecode clients who use this library.
|
|
include_dirs_byt = ["cmd_args"],
|
|
# Native C libs (like `libthreadsnat.a` in the compiler's `threads` package)
|
|
native_c_libs = ["artifact"],
|
|
# Bytecode C libs (like `libthreads.a` in the compiler's `threads` package)
|
|
bytecode_c_libs = ["artifact"],
|
|
)
|
|
|
|
def merge_ocaml_link_infos(lis: ["OCamlLinkInfo"]) -> "OCamlLinkInfo":
|
|
return OCamlLinkInfo(info = dedupe(flatten([li.info for li in lis])))
|
|
|
|
def project_ide(value: {str.type: ["artifact"]}):
|
|
return value["ide"]
|
|
|
|
def project_bytecode(value: {str.type: ["artifact"]}):
|
|
return value["bytecode"]
|
|
|
|
OtherOutputsTSet = transitive_set(
|
|
args_projections = {"bytecode": project_bytecode, "ide": project_ide},
|
|
)
|
|
|
|
OtherOutputsInfo = provider(
|
|
fields = ["info"], # :OtherOutputsTSet
|
|
)
|
|
|
|
def merge_other_outputs_info(ctx: "context", value: {str.type: ["artifact"]}, infos: ["OtherOutputsInfo"]) -> "OtherOutputsInfo":
|
|
return OtherOutputsInfo(
|
|
info =
|
|
ctx.actions.tset(
|
|
OtherOutputsTSet,
|
|
value = value,
|
|
children = [p.info for p in infos],
|
|
),
|
|
)
|