@@ -126,21 +126,6 @@ main = defaultMain
126
126
127
127
_CABAL_TOOLS = ["alex" , "c2hs" , "cpphs" , "doctest" , "happy" ]
128
128
129
- # Some old packages are empty compatibility shims. Empty packages
130
- # cause Cabal to not produce the outputs it normally produces. Instead
131
- # of detecting that, we blacklist the offending packages, on the
132
- # assumption that such packages are old and rare.
133
- #
134
- # TODO: replace this with a more general solution.
135
- _EMPTY_PACKAGES_BLACKLIST = [
136
- "bytestring-builder" ,
137
- "fail" ,
138
- "ghc-byteorder" ,
139
- "haskell-gi-overloading" ,
140
- "mtl-compat" ,
141
- "nats" ,
142
- ]
143
-
144
129
def _cabal_tool_flag (tool ):
145
130
"""Return a --with-PROG=PATH flag if input is a recognized Cabal tool. None otherwise."""
146
131
if tool .basename in _CABAL_TOOLS :
@@ -1133,8 +1118,10 @@ def _parse_components(package, components, spec):
1133
1118
exe: list of string, List of executables.
1134
1119
"""
1135
1120
lib = False
1121
+ empty_lib = False
1136
1122
exe = []
1137
1123
sublibs = []
1124
+ empty_sublibs = []
1138
1125
1139
1126
for component in components :
1140
1127
if component == "lib" :
@@ -1144,6 +1131,15 @@ def _parse_components(package, components, spec):
1144
1131
lib = True
1145
1132
else :
1146
1133
sublibs .append (component [4 :])
1134
+ elif component == "empty_lib" :
1135
+ lib = True
1136
+ empty_lib = True
1137
+ elif component .startswith ("empty_lib:" ):
1138
+ if component == "empty_lib:%s" % package :
1139
+ lib = True
1140
+ empty_lib = True
1141
+ else :
1142
+ empty_sublibs .append (component [4 :])
1147
1143
1148
1144
elif component == "exe" :
1149
1145
exe .append (package )
@@ -1158,14 +1154,21 @@ def _parse_components(package, components, spec):
1158
1154
if not lib or exe != []:
1159
1155
fail ("Invalid core package components: %s" % package , "components" )
1160
1156
1161
- return struct (lib = lib , exe = exe , sublibs = sublibs )
1157
+ return struct (lib = lib , empty_lib = empty_lib , exe = exe , sublibs = sublibs , empty_sublibs = empty_sublibs )
1162
1158
1163
1159
_default_components = {
1164
- "alex" : struct (lib = False , exe = ["alex" ], sublibs = []),
1165
- "c2hs" : struct (lib = False , exe = ["c2hs" ], sublibs = []),
1166
- "cpphs" : struct (lib = True , exe = ["cpphs" ], sublibs = []),
1167
- "doctest" : struct (lib = True , exe = ["doctest" ], sublibs = []),
1168
- "happy" : struct (lib = False , exe = ["happy" ], sublibs = []),
1160
+ "alex" : struct (lib = False , empty_lib = False , exe = ["alex" ], sublibs = [], empty_sublibs = []),
1161
+ "c2hs" : struct (lib = False , empty_lib = False , exe = ["c2hs" ], sublibs = [], empty_sublibs = []),
1162
+ "cpphs" : struct (lib = True , empty_lib = False , exe = ["cpphs" ], sublibs = [], empty_sublibs = []),
1163
+ "doctest" : struct (lib = True , empty_lib = False , exe = ["doctest" ], sublibs = [], empty_sublibs = []),
1164
+ "happy" : struct (lib = False , empty_lib = False , exe = ["happy" ], sublibs = [], empty_sublibs = []),
1165
+ # Below are compatibility libraries that produce an empty cabal library.
1166
+ "bytestring-builder" : struct (lib = True , empty_lib = True , exe = [], sublibs = [], empty_sublibs = []),
1167
+ "fail" : struct (lib = True , empty_lib = True , exe = [], sublibs = [], empty_sublibs = []),
1168
+ "ghc-byteorder" : struct (lib = True , empty_lib = True , exe = [], sublibs = [], empty_sublibs = []),
1169
+ "haskell-gi-overloading" : struct (lib = True , empty_lib = True , exe = [], sublibs = [], empty_sublibs = []),
1170
+ "mtl-compat" : struct (lib = True , empty_lib = True , exe = [], sublibs = [], empty_sublibs = []),
1171
+ "nats" : struct (lib = True , empty_lib = True , exe = [], sublibs = [], empty_sublibs = []),
1169
1172
}
1170
1173
1171
1174
def _get_components (components , package ):
@@ -1175,7 +1178,7 @@ def _get_components(components, package):
1175
1178
will be taken from the `_default_components`. If it is not listed
1176
1179
there then it will default to a library and no executable components.
1177
1180
"""
1178
- return components .get (package , _default_components .get (package , struct (lib = True , exe = [], sublibs = [])))
1181
+ return components .get (package , _default_components .get (package , struct (lib = True , empty_lib = False , exe = [], sublibs = [], empty_sublibs = [])))
1179
1182
1180
1183
def _parse_json_field (json , field , ty , errmsg ):
1181
1184
"""Read and type-check a field from a JSON object.
@@ -2054,7 +2057,7 @@ packages = {
2054
2057
# Write out the dependency graph as a BUILD file.
2055
2058
build_file_builder = []
2056
2059
build_file_builder .append ("""
2057
- load("@rules_haskell//haskell:cabal.bzl", "haskell_cabal_binary", "haskell_cabal_library")
2060
+ load("@rules_haskell//haskell:cabal.bzl", "haskell_cabal_args", " haskell_cabal_binary", "haskell_cabal_library")
2058
2061
load("@rules_haskell//haskell:defs.bzl", "haskell_library", "haskell_toolchain_library")
2059
2062
""" )
2060
2063
for (name , spec ) in resolved .items ():
@@ -2075,20 +2078,6 @@ alias(name = "{name}", actual = "{actual}", visibility = {visibility})
2075
2078
haskell_toolchain_library(name = "{name}", visibility = {visibility})
2076
2079
""" .format (name = name , visibility = visibility ),
2077
2080
)
2078
- elif name in _EMPTY_PACKAGES_BLACKLIST :
2079
- build_file_builder .append (
2080
- """
2081
- haskell_library(
2082
- name = "{name}",
2083
- version = "{version}",
2084
- visibility = {visibility},
2085
- )
2086
- """ .format (
2087
- name = name ,
2088
- version = version ,
2089
- visibility = visibility ,
2090
- ),
2091
- )
2092
2081
else :
2093
2082
library_deps = [
2094
2083
dep
@@ -2119,6 +2108,26 @@ haskell_library(
2119
2108
)).relative (label ))
2120
2109
for label in repository_ctx .attr .setup_deps .get (name , [])
2121
2110
]
2111
+
2112
+ wrote_cabal_args = False
2113
+ cabal_args = "cabal_args = \" _{name}_cabal_args\" ," .format (name = name )
2114
+ def add_cabal_args (written ):
2115
+ if not written :
2116
+ build_file_builder .append (
2117
+ """
2118
+ haskell_cabal_args(
2119
+ name = "_{name}_cabal_args",
2120
+ is_empty = True,
2121
+ )
2122
+ """ .format (name = name )
2123
+ )
2124
+ return True
2125
+
2126
+ lib_cabal_args = ""
2127
+ if all_components [name ].empty_lib :
2128
+ wrote_cabal_args = add_cabal_args (wrote_cabal_args )
2129
+ lib_cabal_args = cabal_args
2130
+
2122
2131
if all_components [name ].lib :
2123
2132
build_file_builder .append (
2124
2133
"""
@@ -2134,6 +2143,7 @@ haskell_cabal_library(
2134
2143
visibility = {visibility},
2135
2144
cabalopts = ["--ghc-option=-w", "--ghc-option=-optF=-w"],
2136
2145
verbose = {verbose},
2146
+ {lib_cabal_args}
2137
2147
unique_name = True,
2138
2148
)
2139
2149
""" .format (
@@ -2224,6 +2234,46 @@ haskell_cabal_library(
2224
2234
visibility = visibility ,
2225
2235
),
2226
2236
)
2237
+ for sublib in all_components [name ].empty_sublibs :
2238
+ sublib_component_deps = [
2239
+ _resolve_component_target_name (name , c )
2240
+ for c in package_components_dependencies .get ("lib:{}" .format (sublib ), [])
2241
+ ]
2242
+ wrote_cabal_args = add_cabal_args (wrote_cabal_args )
2243
+ build_file_builder .append (
2244
+ """
2245
+ haskell_cabal_library(
2246
+ name = "_{name}_lib_{sublib}",
2247
+ package_name = "{name}",
2248
+ version = "{version}",
2249
+ haddock = {haddock},
2250
+ sublibrary_name = "{sublib}",
2251
+ flags = {flags},
2252
+ srcs = glob(["{dir}/**"]),
2253
+ deps = {deps},
2254
+ setup_deps = {setup_deps},
2255
+ tools = {tools},
2256
+ visibility = {visibility},
2257
+ cabalopts = ["--ghc-option=-w", "--ghc-option=-optF=-w"],
2258
+ verbose = {verbose},
2259
+ {cabal_args},
2260
+ )
2261
+ """ .format (
2262
+ name = name ,
2263
+ version = version ,
2264
+ haddock = repr (repository_ctx .attr .haddock ),
2265
+ sublib = sublib ,
2266
+ flags = repository_ctx .attr .flags .get (name , []),
2267
+ dir = package ,
2268
+ deps = library_deps + sublib_component_deps ,
2269
+ setup_deps = setup_deps ,
2270
+ tools = library_tools ,
2271
+ verbose = repr (repository_ctx .attr .verbose ),
2272
+ visibility = visibility ,
2273
+ cabal_args = cabal_args ,
2274
+ ),
2275
+ )
2276
+
2227
2277
build_file_content = "\n " .join (build_file_builder )
2228
2278
repository_ctx .file ("BUILD.bazel" , build_file_content , executable = False )
2229
2279
0 commit comments