Skip to content

Commit 5d39195

Browse files
committed
cabal: Add support for empty libraries
Previously, an empty library that only exported modules from another library failed to build. Bazel would error out when the .a file wasn't created. These libraries are becoming more common in the Haskell ecosystem, so we need to support them. There is a straightforward way to handle these libraries. We make the package database the default output. We avoid creating an output file for any libraries if the library is marked as empty. This is all straightforward bazel dependency/output management. Adjust the cabal wrapper to fix up the package database even in the case that there is no library. Otherwise we end up with an empty package database, which isn't what we're looking for.
1 parent 6e31297 commit 5d39195

File tree

2 files changed

+42
-25
lines changed

2 files changed

+42
-25
lines changed

haskell/cabal.bzl

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ def _haskell_cabal_library_impl(ctx):
483483
"_install/{}_data".format(package_id),
484484
sibling = cabal,
485485
)
486-
with_haddock = ctx.attr.haddock and hs.tools_config.supports_haddock
486+
with_haddock = ctx.attr.haddock and hs.tools_config.supports_haddock and not ctx.attr.empty_library
487487
if with_haddock:
488488
haddock_file = hs.actions.declare_file(
489489
"_install/{}_haddock/{}.haddock".format(package_id, package_name),
@@ -496,30 +496,36 @@ def _haskell_cabal_library_impl(ctx):
496496
else:
497497
haddock_file = None
498498
haddock_html_dir = None
499-
vanilla_library = hs.actions.declare_file(
500-
"_install/lib/libHS{}.a".format(package_id),
501-
sibling = cabal,
502-
)
503-
if with_profiling:
504-
profiling_library = hs.actions.declare_file(
505-
"_install/lib/libHS{}_p.a".format(package_id),
506-
sibling = cabal,
507-
)
508-
static_library = profiling_library
509-
else:
499+
if ctx.attr.empty_library:
500+
vanilla_library = None
501+
static_library = None
510502
profiling_library = None
511-
static_library = vanilla_library
512-
if hs.toolchain.static_runtime:
513503
dynamic_library = None
514504
else:
515-
dynamic_library = hs.actions.declare_file(
516-
"_install/lib/libHS{}-ghc{}.{}".format(
517-
package_id,
518-
hs.toolchain.version,
519-
_so_extension(hs),
520-
),
505+
vanilla_library = hs.actions.declare_file(
506+
"_install/lib/libHS{}.a".format(package_id),
521507
sibling = cabal,
522508
)
509+
if with_profiling:
510+
profiling_library = hs.actions.declare_file(
511+
"_install/lib/libHS{}_p.a".format(package_id),
512+
sibling = cabal,
513+
)
514+
static_library = profiling_library
515+
else:
516+
profiling_library = None
517+
static_library = vanilla_library
518+
if hs.toolchain.static_runtime:
519+
dynamic_library = None
520+
else:
521+
dynamic_library = hs.actions.declare_file(
522+
"_install/lib/libHS{}-ghc{}.{}".format(
523+
package_id,
524+
hs.toolchain.version,
525+
_so_extension(hs),
526+
),
527+
sibling = cabal,
528+
)
523529
(tool_inputs, tool_input_manifests) = ctx.resolve_tools(tools = ctx.attr.tools)
524530
c = _prepare_cabal_inputs(
525531
hs,
@@ -553,11 +559,12 @@ def _haskell_cabal_library_impl(ctx):
553559
outputs = [
554560
package_database,
555561
interfaces_dir,
556-
vanilla_library,
557562
data_dir,
558563
]
559564
if with_haddock:
560565
outputs.extend([haddock_file, haddock_html_dir])
566+
if vanilla_library != None:
567+
outputs.append(vanilla_library)
561568
if dynamic_library != None:
562569
outputs.append(dynamic_library)
563570
if with_profiling:
@@ -578,8 +585,13 @@ def _haskell_cabal_library_impl(ctx):
578585
progress_message = "HaskellCabalLibrary {}".format(hs.label),
579586
)
580587

588+
if not ctx.attr.empty_library:
589+
default_info_libs = depset([static_library] + ([dynamic_library] if dynamic_library != None else []))
590+
else:
591+
default_info_libs = depset([package_database])
592+
581593
default_info = DefaultInfo(
582-
files = depset([static_library] + ([dynamic_library] if dynamic_library != None else [])),
594+
files = default_info_libs,
583595
runfiles = ctx.runfiles(
584596
files = [data_dir],
585597
collect_default = True,
@@ -628,7 +640,7 @@ def _haskell_cabal_library_impl(ctx):
628640
)
629641
linker_input = cc_common.create_linker_input(
630642
owner = ctx.label,
631-
libraries = depset(direct = [
643+
libraries = depset(direct = ([] if ctx.attr.empty_library else [
632644
cc_common.create_library_to_link(
633645
actions = ctx.actions,
634646
feature_configuration = feature_configuration,
@@ -638,7 +650,7 @@ def _haskell_cabal_library_impl(ctx):
638650
static_library = static_library,
639651
cc_toolchain = cc_toolchain,
640652
),
641-
]),
653+
])),
642654
)
643655
compilation_context = cc_common.create_compilation_context()
644656
linking_context = cc_common.create_linking_context(
@@ -747,6 +759,11 @@ haskell_cabal_library = rule(
747759
library symlink underneath `_solib_<cpu>` will be shortened to
748760
avoid exceeding the MACH-O header size limit on MacOS.""",
749761
),
762+
"empty_library": attr.bool(
763+
default = False,
764+
doc = """Whether the main cabal library is empty and merely re-exports from other sub libraries.
765+
It is necessary to set this, otherwise bazel will complain about missing "*libHS.a" files.""",
766+
),
750767
},
751768
toolchains = use_cc_toolchain() + [
752769
"@rules_haskell//haskell:toolchain",

haskell/private/cabal_wrapper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ def make_relative_to_pkgroot(matchobj):
392392
line = re.sub(re.escape(cfg_execroot) + r'\S*', make_relative_to_pkgroot, line)
393393
return line
394394

395-
if libraries != [] and os.path.isfile(package_conf_file):
395+
if os.path.isfile(package_conf_file):
396396
for lib in libraries:
397397
os.rename(lib, os.path.join(dynlibdir, os.path.basename(lib)))
398398

0 commit comments

Comments
 (0)