Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions haskell.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

load("//buck2:alex_happy.bzl", "alex", "happy")
load("//buck2:hsc2hs.bzl", "hsc2hs")
load("@prelude//haskell/util.bzl", "src_to_module_name")
load("@prelude//paths.bzl", "paths")

# Packages implicitly needed by every Haskell target.
Expand Down Expand Up @@ -226,8 +225,10 @@ def _resolve_src(name, src, deps, hsc_flags):
return src

def _resolve_srcs(name, srcs, deps, hsc_flags):
items = srcs.items() if type(srcs) == type({}) else [(src_to_module_name(src), src) for src in srcs]
return { modl: _resolve_src(name, src, deps, hsc_flags) for modl, src in items }
if type(srcs) == type({}):
return { modl: _resolve_src(name, src, deps, hsc_flags) for modl, src in srcs.items() }
else:
return [ _resolve_src(name, src, deps, hsc_flags) for src in srcs ]

def haskell_library(
name,
Expand Down
32 changes: 22 additions & 10 deletions thrift.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,28 @@ load("//buck2:haskell.bzl", "haskell_library")
# into a directory (`gen-hs2/...` by default) rather than a fixed file.
# `outs`, if given, additionally names known files within that directory
# (as plain module paths, e.g. "Foo/Types.hs" - not gen-hs2-prefixed) and
# exposes each as its own correctly-pathed sub-target artifact (via
# ctx.actions.copy_file() - the same primitive export_file.bzl uses), so a
# caller who already knows what a .thrift file generates can put them
# directly into a haskell_library()'s plain srcs *list*:
# exposes each as its own sub-target artifact (via ctx.actions.copy_file()
# - the same primitive export_file.bzl uses), so a caller who already
# knows what a .thrift file generates can put them directly into a
# haskell_library()'s `srcs` *dict*, keyed by module name:
#
# thrift_compile(
# name = "gen-foo",
# thrift_file = "if/Foo.thrift",
# outs = ["Foo/Types.hs"],
# )
# haskell_library(
# srcs = [":gen-foo[Foo/Types.hs]"],
# srcs = {"Foo.Types": ":gen-foo[Foo/Types.hs]"},
# ...
# )
#
# This isn't just a style choice: haskell_library() derives each module's
# name (for the package db, so cross-target `import`s of it resolve) from
# its source artifact's own path - a bare copy of the whole gen-hs2/
# The dict form (module name -> source) is what haskell_library() wants
# here, rather than a plain list: with a list, each module's name (for
# the package db, so cross-target `import`s of it resolve) is derived from
# its source artifact's own path, and a bare copy of the whole gen-hs2/
# directory would derive "gen.gen-hs2.Foo.Types" instead of "Foo.Types".
# (thrift_srcs()/thrift_library() below do the path -> module name
# conversion for `outs` entries themselves; see _module_name().)

# thrift-compiler's default --gen-prefix; every caller in this repo relies
# on the default, so `outs` entries are resolved as GEN_PREFIX + "/" + out
Expand Down Expand Up @@ -214,6 +217,13 @@ def _thrift_name(thrift_file, full_paths = False):
return native.package_name() + "/" + thrift_file
return thrift_file

def _module_name(path):
# "Foo/Bar/Types.hs" -> "Foo.Bar.Types": the module name a Haskell
# source at that (module-derived) path declares, which is what the
# dict form of a haskell_*() rule's `srcs` is keyed by.
base = path[:path.rindex(".")] if "." in path.split("/")[-1] else path
return base.replace("/", ".")

def _thrift_compile_all(name, thrift_files, thrift_flags, thrift_file_flags, deps, srcs, full_paths):
# Shared by thrift_srcs() and thrift_library() below: declares one
# thrift_compile() per thrift_files entry (each one's own `deps`
Expand All @@ -223,7 +233,9 @@ def _thrift_compile_all(name, thrift_files, thrift_flags, thrift_file_flags, dep
# e.g. tests/if/A.thrift including B/C/D/E.thrift, all declared in the
# same thrift_files dict, just works), and returns the resulting srcs
# dict for a haskell_*() target.
all_srcs = dict(srcs) if type(srcs) == type({}) else {s: s for s in srcs}
# `srcs` is either a list of hand-written sources, whose module names
# are derived from their paths, or a dict keyed by module name already.
all_srcs = dict(srcs) if type(srcs) == type({}) else {_module_name(s): s for s in srcs}
for thrift_file, outs in thrift_files.items():
gen_name = name + "-thrift-" + _thrift_stem(thrift_file)
thrift_compile(
Expand All @@ -236,7 +248,7 @@ def _thrift_compile_all(name, thrift_files, thrift_flags, thrift_file_flags, dep
exec_compatible_with = ["root//buck2/constraints:opt"],
)
for out in outs:
all_srcs[out] = ":{}[{}]".format(gen_name, out)
all_srcs[_module_name(out)] = ":{}[{}]".format(gen_name, out)
return all_srcs

# Lower-level than thrift_library() below: creates the same per-file
Expand Down
Loading