Skip to content

Commit b06c915

Browse files
aherrmannmergify-bot
authored andcommitted
RUNPATH and runfiles for transitive C libs
GHC passes `-l` flags for all transitive C library dependencies when linking. Accordingly, we need to provide `RUNPATH` entries for all transitive C libraries. Also, to ensure that binaries can find their dynamic library dependencies, we add them to the `runfiles` attribute of the `DefaultInfo` provider.
1 parent b1cea20 commit b06c915

File tree

1 file changed

+30
-3
lines changed

1 file changed

+30
-3
lines changed

haskell/cabal.bzl

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ load(
3232
load(
3333
":private/cc_libraries.bzl",
3434
"deps_HaskellCcLibrariesInfo",
35+
"get_cc_libraries",
3536
"get_ghci_library_files",
37+
"get_library_files",
3638
"haskell_cc_libraries_aspect",
3739
)
3840

@@ -110,6 +112,9 @@ def _cabal_tool_flag(tool):
110112
def _binary_paths(binaries):
111113
return [binary.dirname for binary in binaries.to_list()]
112114

115+
def _concat(sequences):
116+
return [item for sequence in sequences for item in sequence]
117+
113118
def _prepare_cabal_inputs(
114119
hs,
115120
cc,
@@ -139,7 +144,26 @@ def _prepare_cabal_inputs(
139144
# to add libraries and headers for direct C library dependencies to the
140145
# command line.
141146
direct_libs = get_ghci_library_files(hs, cc.cc_libraries_info, cc.cc_libraries)
142-
transitive_libs = get_ghci_library_files(hs, cc.cc_libraries_info, cc.transitive_libraries)
147+
148+
# The regular Haskell rules perform mostly static linking, i.e. where
149+
# possible all C library dependencies are linked statically. Cabal has no
150+
# such mode, and since we have to provide dynamic C libraries for
151+
# compilation, they will also be used for linking. Hence, we need to add
152+
# RUNPATH flags for all dynamic C library dependencies.
153+
(_, dynamic_libs) = get_library_files(
154+
hs,
155+
cc.cc_libraries_info,
156+
get_cc_libraries(cc.cc_libraries_info, cc.transitive_libraries),
157+
dynamic = True,
158+
)
159+
160+
# The regular Haskell rules have separate actions for linking and
161+
# compilation to which we pass different sets of libraries as inputs. The
162+
# Cabal rules, in contrast, only have a single action for compilation and
163+
# linking, so we must provide both sets of libraries as inputs to the same
164+
# action.
165+
transitive_compile_libs = get_ghci_library_files(hs, cc.cc_libraries_info, cc.transitive_libraries)
166+
transitive_link_libs = _concat(get_library_files(hs, cc.cc_libraries_info, cc.transitive_libraries))
143167
env = dict(hs.env)
144168
env["PATH"] = join_path_list(hs, _binary_paths(tool_inputs) + posix.paths)
145169
if hs.toolchain.is_darwin:
@@ -169,7 +193,7 @@ def _prepare_cabal_inputs(
169193
keep_filename = False,
170194
prefix = relative_rpath_prefix(hs.toolchain.is_darwin),
171195
)
172-
for lib in direct_libs
196+
for lib in dynamic_libs
173197
],
174198
uniquify = True,
175199
)
@@ -190,7 +214,8 @@ def _prepare_cabal_inputs(
190214
depset(cc.files),
191215
package_databases,
192216
transitive_headers,
193-
depset(transitive_libs),
217+
depset(transitive_compile_libs),
218+
depset(transitive_link_libs),
194219
dep_info.interface_dirs,
195220
dep_info.static_libraries,
196221
dep_info.dynamic_libraries,
@@ -205,6 +230,7 @@ def _prepare_cabal_inputs(
205230
inputs = inputs,
206231
input_manifests = input_manifests,
207232
env = env,
233+
runfiles = depset(direct = dynamic_libs),
208234
)
209235

210236
def _haskell_cabal_library_impl(ctx):
@@ -572,6 +598,7 @@ def _haskell_cabal_binary_impl(ctx):
572598
executable = binary,
573599
runfiles = ctx.runfiles(
574600
files = [data_dir],
601+
transitive_files = c.runfiles,
575602
collect_default = True,
576603
),
577604
)

0 commit comments

Comments
 (0)