Skip to content

Commit 61d098d

Browse files
committed
cabal: Add provider and rule for cabal settings
Rather than continually proliferate additional settings on haskell_cabal_library, create a rule and provider that can hold cabal specific settings. Add `empty_lib` as the first such setting. When building an empty lib, bazel will look for the package file, instead of for any object files. This will fix several packages that are currently blacklisted. It will also allow the use of packages with sublibraries and an empty main lib. Currently there is no way to use this with a stack snapshot, short of vendoring a package and adding a `haskell_cabal_args` to the vendored build file. A simpler way is planned.
1 parent 04cd138 commit 61d098d

File tree

2 files changed

+71
-24
lines changed

2 files changed

+71
-24
lines changed

haskell/cabal.bzl

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ load(
3737
load(
3838
":providers.bzl",
3939
"HaddockInfo",
40+
"HaskellCabalArgs",
4041
"HaskellInfo",
4142
"HaskellLibraryInfo",
4243
"all_dependencies_package_ids",
@@ -436,6 +437,25 @@ def _shorten_library_symlink(dynamic_library):
436437
basename = dynamic_library.basename
437438
return paths.join(prefix, basename)
438439

440+
def _haskell_cabal_args_impl(ctx):
441+
is_empty = ctx.attr.is_empty
442+
cabal_args = HaskellCabalArgs(
443+
is_empty = is_empty,
444+
)
445+
return [cabal_args]
446+
447+
haskell_cabal_args = rule(
448+
_haskell_cabal_args_impl,
449+
attrs = {
450+
"is_empty": attr.bool(
451+
default = False,
452+
doc = """True if this (sub) library is empty, with only re-exports, and no source files of its own.
453+
It is necessary to set this, otherwise bazel will complain about missing "*libHS.a" files.""",
454+
),
455+
},
456+
provides = [HaskellCabalArgs],
457+
)
458+
439459
def _haskell_cabal_library_impl(ctx):
440460
hs = haskell_context(ctx)
441461
dep_info = gather_dep_info(ctx.attr.name, ctx.attr.deps)
@@ -446,6 +466,10 @@ def _haskell_cabal_library_impl(ctx):
446466
override_cc_toolchain = hs.tools_config.maybe_exec_cc_toolchain,
447467
)
448468

469+
is_empty = False
470+
if ctx.attr.cabal_args:
471+
is_empty = ctx.attr.cabal_args[HaskellCabalArgs].is_empty
472+
449473
# All C and Haskell library dependencies.
450474
cc_info = cc_common.merge_cc_infos(
451475
cc_infos = [dep[CcInfo] for dep in ctx.attr.deps if CcInfo in dep],
@@ -486,7 +510,7 @@ def _haskell_cabal_library_impl(ctx):
486510
"_install/{}_data".format(package_id),
487511
sibling = cabal,
488512
)
489-
with_haddock = ctx.attr.haddock and hs.tools_config.supports_haddock
513+
with_haddock = ctx.attr.haddock and hs.tools_config.supports_haddock and not is_empty
490514
if with_haddock:
491515
haddock_file = hs.actions.declare_file(
492516
"_install/{}_haddock/{}.haddock".format(package_id, package_name),
@@ -499,30 +523,36 @@ def _haskell_cabal_library_impl(ctx):
499523
else:
500524
haddock_file = None
501525
haddock_html_dir = None
502-
vanilla_library = hs.actions.declare_file(
503-
"_install/lib/libHS{}.a".format(package_id),
504-
sibling = cabal,
505-
)
506-
if with_profiling:
507-
profiling_library = hs.actions.declare_file(
508-
"_install/lib/libHS{}_p.a".format(package_id),
509-
sibling = cabal,
510-
)
511-
static_library = profiling_library
512-
else:
526+
if is_empty:
527+
vanilla_library = None
528+
static_library = None
513529
profiling_library = None
514-
static_library = vanilla_library
515-
if hs.toolchain.static_runtime:
516530
dynamic_library = None
517531
else:
518-
dynamic_library = hs.actions.declare_file(
519-
"_install/lib/libHS{}-ghc{}.{}".format(
520-
package_id,
521-
hs.toolchain.version,
522-
_so_extension(hs),
523-
),
532+
vanilla_library = hs.actions.declare_file(
533+
"_install/lib/libHS{}.a".format(package_id),
524534
sibling = cabal,
525535
)
536+
if with_profiling:
537+
profiling_library = hs.actions.declare_file(
538+
"_install/lib/libHS{}_p.a".format(package_id),
539+
sibling = cabal,
540+
)
541+
static_library = profiling_library
542+
else:
543+
profiling_library = None
544+
static_library = vanilla_library
545+
if hs.toolchain.static_runtime:
546+
dynamic_library = None
547+
else:
548+
dynamic_library = hs.actions.declare_file(
549+
"_install/lib/libHS{}-ghc{}.{}".format(
550+
package_id,
551+
hs.toolchain.version,
552+
_so_extension(hs),
553+
),
554+
sibling = cabal,
555+
)
526556
(tool_inputs, tool_input_manifests) = ctx.resolve_tools(tools = ctx.attr.tools)
527557
c = _prepare_cabal_inputs(
528558
hs,
@@ -556,11 +586,12 @@ def _haskell_cabal_library_impl(ctx):
556586
outputs = [
557587
package_database,
558588
interfaces_dir,
559-
vanilla_library,
560589
data_dir,
561590
]
562591
if with_haddock:
563592
outputs.extend([haddock_file, haddock_html_dir])
593+
if vanilla_library != None:
594+
outputs.append(vanilla_library)
564595
if dynamic_library != None:
565596
outputs.append(dynamic_library)
566597
if with_profiling:
@@ -581,8 +612,13 @@ def _haskell_cabal_library_impl(ctx):
581612
progress_message = "HaskellCabalLibrary {}".format(hs.label),
582613
)
583614

615+
if not is_empty:
616+
default_info_libs = depset([static_library] + ([dynamic_library] if dynamic_library != None else []))
617+
else:
618+
default_info_libs = depset([package_database])
619+
584620
default_info = DefaultInfo(
585-
files = depset([static_library] + ([dynamic_library] if dynamic_library != None else [])),
621+
files = default_info_libs,
586622
runfiles = ctx.runfiles(
587623
files = [data_dir],
588624
collect_default = True,
@@ -631,7 +667,7 @@ def _haskell_cabal_library_impl(ctx):
631667
)
632668
linker_input = cc_common.create_linker_input(
633669
owner = ctx.label,
634-
libraries = depset(direct = [
670+
libraries = depset(direct = ([] if is_empty else [
635671
cc_common.create_library_to_link(
636672
actions = ctx.actions,
637673
feature_configuration = feature_configuration,
@@ -641,7 +677,7 @@ def _haskell_cabal_library_impl(ctx):
641677
static_library = static_library,
642678
cc_toolchain = cc_toolchain,
643679
),
644-
]),
680+
])),
645681
)
646682
compilation_context = cc_common.create_compilation_context()
647683
linking_context = cc_common.create_linking_context(
@@ -750,6 +786,10 @@ haskell_cabal_library = rule(
750786
library symlink underneath `_solib_<cpu>` will be shortened to
751787
avoid exceeding the MACH-O header size limit on MacOS.""",
752788
),
789+
"cabal_args": attr.label(
790+
doc = """A haskell_cabal_args target with cabal specific settings for this package.""",
791+
providers = [[HaskellCabalArgs]],
792+
),
753793
},
754794
toolchains = use_cc_toolchain() + [
755795
"@rules_haskell//haskell:toolchain",

haskell/providers.bzl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ HaskellLibraryInfo = provider(
3434
},
3535
)
3636

37+
HaskellCabalArgs = provider(
38+
doc = "Settings for a haskell_cabal_library",
39+
fields = {
40+
"is_empty": "True if this (sub) library is empty, with only re-exports, and no source files of its own.",
41+
},
42+
)
43+
3744
def all_package_ids(lib_info):
3845
return lib_info.exports.to_list()
3946

0 commit comments

Comments
 (0)