From 76c66a44a4985b4e1d8fc686695a36b27313fff5 Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Fri, 2 Oct 2026 10:15:01 +0100 Subject: [PATCH 1/2] Fix for _resolve_srcs when using generated source files --- haskell.bzl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/haskell.bzl b/haskell.bzl index 2797d9d..9ec3b1b 100644 --- a/haskell.bzl +++ b/haskell.bzl @@ -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. @@ -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, From a0046ae74c0ebc64d54b093237b6fb2137d1b678 Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Fri, 2 Oct 2026 10:16:34 +0100 Subject: [PATCH 2/2] Update thrift.bzl for new srcs format --- thrift.bzl | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/thrift.bzl b/thrift.bzl index ee15ca7..b170014 100644 --- a/thrift.bzl +++ b/thrift.bzl @@ -13,10 +13,10 @@ 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", @@ -24,14 +24,17 @@ load("//buck2:haskell.bzl", "haskell_library") # 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 @@ -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` @@ -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( @@ -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