Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Jun 10, 2022
2 parents e05b545 + d3caf0c commit b62ea9e
Show file tree
Hide file tree
Showing 10 changed files with 478 additions and 39 deletions.
1 change: 1 addition & 0 deletions haskell/experimental/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ load(
)
load("//haskell:private/cc_libraries.bzl", "haskell_cc_libraries_aspect")

# TODO[GL] should we have repl_ghci_args here?
_haskell_module = rule(
_haskell_module_impl,
# NOTE: Documentation needs to be added to the wrapper macros below.
Expand Down
60 changes: 53 additions & 7 deletions haskell/experimental/private/module.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ load(
"//haskell:private/plugins.bzl",
"resolve_plugin_tools",
)
load("//haskell:private/set.bzl", "set")
load(
"//haskell:providers.bzl",
"GhcPluginInfo",
Expand Down Expand Up @@ -109,7 +110,7 @@ def _build_haskell_module(
narrowed_objects,
extra_ldflags_file,
module):
"""Build a module
"""Build a module. Returns data needed by haskell_repl.
Args:
ctx: The context of the binary, library, or test rule using the module
Expand All @@ -130,6 +131,13 @@ def _build_haskell_module(
narrowed_objects: A depset containing the narrowed object files needed as arguments to ghc.
extra_ldflags_file: A File with flags for ld or None.
module: The Target of the haskell_module rule
Returns:
struct(source_file, boot_file, import_dir, user_compile_flags):
source_file: The file that contains the Haskell module. None if it's a boot file.
boot_file: The file that contains the boot Haskell module. None if it's not a boot file.
import_dir: A possibly (e.g. due to hsc) newly generated import directory.
user_compile_flags: Compiler flags specified by the user in this module after location expansion.
"""

moduleAttr = module[HaskellModuleInfo].attr
Expand All @@ -148,15 +156,17 @@ def _build_haskell_module(
moduleAttr.tools,
]

user_ghcopts += expand_make_variables("ghcopts", ctx, moduleAttr.ghcopts, module_extra_attrs)
user_compile_flags = expand_make_variables("ghcopts", ctx, moduleAttr.ghcopts, module_extra_attrs)
user_ghcopts += user_compile_flags

import_dir = None
if src.extension == "hsc":
# TODO[AH] Support version macros
hsc_flags, hsc_inputs = preprocess_hsc_flags_and_inputs(dep_info, user_ghcopts, None)

# TODO[GL] Use idir when providing HaskellReplLoadInfo
hs_out, idir = process_hsc_file(hs, cc, hsc_flags, hsc_inputs, src)
src = hs_out
import_dir = idir

# Note [Plugin order]
plugin_decl = reversed(ctx.attr.plugins + moduleAttr.plugins)
Expand Down Expand Up @@ -342,6 +352,14 @@ def _build_haskell_module(
extra_name = module.label.package.replace("/", "_") + "_" + module.label.name,
)

is_boot = _is_boot(src.path)
return struct(
source_file = None if is_boot else src,
boot_file = src if is_boot else None,
import_dir = import_dir,
user_compile_flags = user_compile_flags,
)

def get_module_path_from_target(module):
module_name = module[HaskellModuleInfo].attr.module_name
if module_name:
Expand All @@ -358,11 +376,14 @@ def get_module_path_from_target(module):

return paths.split_extension(paths.relativize(src, prefix_path))[0]

def _is_boot(path):
return paths.split_extension(path)[1] in [".hs-boot", ".lhs-boot"]

def _declare_module_outputs(hs, with_profiling, with_shared, hidir, odir, module):
module_path = get_module_path_from_target(module)

src = module[HaskellModuleInfo].attr.src.files.to_list()[0].path
hs_boot = paths.split_extension(src)[1] in [".hs-boot", ".lhs-boot"]
hs_boot = _is_boot(src)
extension_template = "%s"
if hs_boot:
extension_template = extension_template + "-boot"
Expand Down Expand Up @@ -540,7 +561,8 @@ def build_haskell_modules(
hidir,
odir):
""" Build all the modules of haskell_module rules in ctx.attr.modules
and in their dependencies
and in their dependencies. The repl_info returned here aggregates data
from all the haskell_modules being run here.
Args:
ctx: The context of the rule with module dependencies
Expand All @@ -555,7 +577,7 @@ def build_haskell_modules(
odir: The directory in which to output object files
Returns:
struct(his, dyn_his, os, dyn_os, per_module_transitive_interfaces, per_module_transitive_objects, per_module_transitive_dyn_objects):
struct(his, dyn_his, os, dyn_os, per_module_transitive_interfaces, per_module_transitive_objects, per_module_transitive_dyn_objects, repl_info):
his: interface files of all modules in ctx.attr.modules
dyn_his: dynamic interface files of all modules in ctx.attr.modules
os: object files of all modules in ctx.attr.modules
Expand All @@ -567,6 +589,11 @@ def build_haskell_modules(
object files and the object files of their transitive module
dependencies. See Note [Narrowed Dependencies].
per_module_transitive_dyn_objects: like per_module_transitive_objects but for dyn_o files
repl_info: struct(source_files, boot_files, import_dirs, user_compile_flags):
source_files: Depset of files that contain Haskell modules.
boot_files: Depset of files that contain Haskell boot modules.
import_dirs: Set of newly generated import directories. hsc2hs generates these.
user_compile_flags: Compiler flags specified by the user, after location expansion.
"""
per_module_maps = _merge_narrowed_deps_dicts(ctx.label, ctx.attr.narrowed_deps)

Expand All @@ -584,6 +611,12 @@ def build_haskell_modules(
module_interfaces = {}
module_objects = {}
module_dyn_objects = {}

source_files = []
boot_files = []
import_dirs = []
user_compile_flags = []

for dep in transitive_module_deps:
# called in all cases to validate cross_library_deps, although the output
# might be ignored when disabling narrowing
Expand Down Expand Up @@ -611,7 +644,7 @@ def build_haskell_modules(
_collect_module_inputs(module_dyn_objects, narrowed_objects, dyn_os, dep),
])

_build_haskell_module(
module_output = _build_haskell_module(
ctx,
hs,
cc,
Expand All @@ -631,6 +664,13 @@ def build_haskell_modules(
extra_ldflags_file,
dep,
)
if module_output.source_file:
source_files.append(module_output.source_file)
if module_output.boot_file:
boot_files.append(module_output.boot_file)
if module_output.import_dir:
import_dirs.append(module_output.import_dir)
user_compile_flags += module_output.user_compile_flags

module_outputs_list = module_outputs.values()
hi_set = depset([outputs.hi for outputs in module_outputs_list])
Expand Down Expand Up @@ -676,6 +716,12 @@ def build_haskell_modules(
per_module_transitive_interfaces = per_module_transitive_interfaces0,
per_module_transitive_objects = per_module_transitive_objects0,
per_module_transitive_dyn_objects = per_module_transitive_dyn_objects0,
repl_info = struct(
source_files = depset(source_files),
boot_files = depset(boot_files),
import_dirs = set.from_list(import_dirs),
user_compile_flags = user_compile_flags,
),
)

def haskell_module_impl(ctx):
Expand Down
2 changes: 1 addition & 1 deletion haskell/private/cc_libraries.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ def _haskell_cc_libraries_aspect_impl(target, ctx):

haskell_cc_libraries_aspect = aspect(
implementation = _haskell_cc_libraries_aspect_impl,
attr_aspects = ["deps", "exports", "plugins"],
attr_aspects = ["deps", "narrowed_deps", "exports", "plugins"],
provides = [HaskellCcLibrariesInfo],
required_aspect_providers = [HaskellProtobufInfo],
toolchains = [
Expand Down
16 changes: 8 additions & 8 deletions haskell/private/haskell_impl.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -286,16 +286,16 @@ def _haskell_binary_common_impl(ctx, is_test):
hs_info = HaskellInfo(
package_databases = all_deps_info.package_databases,
version_macros = set.empty(),
source_files = c.source_files,
boot_files = c.boot_files,
source_files = depset(transitive = [c.source_files, module_outputs.repl_info.source_files]),
boot_files = depset(transitive = [c.boot_files, module_outputs.repl_info.boot_files]),
extra_source_files = c.extra_source_files,
import_dirs = c.import_dirs,
import_dirs = set.mutable_union(c.import_dirs, module_outputs.repl_info.import_dirs),
hs_libraries = all_deps_info.hs_libraries,
deps_hs_libraries = all_deps_info.deps_hs_libraries,
interface_dirs = all_deps_info.interface_dirs,
deps_interface_dirs = all_deps_info.deps_interface_dirs,
compile_flags = c.compile_flags,
user_compile_flags = user_compile_flags,
user_compile_flags = user_compile_flags + module_outputs.repl_info.user_compile_flags,
user_repl_flags = haskell_library_expand_make_variables("repl_ghci_args", ctx, ctx.attr.repl_ghci_args),
)
cc_info = cc_common.merge_cc_infos(
Expand Down Expand Up @@ -616,10 +616,10 @@ def haskell_library_impl(ctx):
order = "preorder",
),
version_macros = version_macros,
source_files = c.source_files,
boot_files = c.boot_files,
source_files = depset(transitive = [c.source_files, module_outputs.repl_info.source_files]),
boot_files = depset(transitive = [c.boot_files, module_outputs.repl_info.boot_files]),
extra_source_files = c.extra_source_files,
import_dirs = set.mutable_union(c.import_dirs, export_infos.import_dirs),
import_dirs = set.mutable_union(c.import_dirs, set.mutable_union(export_infos.import_dirs, module_outputs.repl_info.import_dirs)),
hs_libraries = depset(
direct = [lib for lib in [static_library, dynamic_library] if lib],
transitive = [all_deps_info.hs_libraries],
Expand All @@ -634,7 +634,7 @@ def haskell_library_impl(ctx):
interface_dirs = depset(transitive = [interface_dirs, export_infos.interface_dirs]),
deps_interface_dirs = depset(transitive = [dep_info.interface_dirs, narrowed_deps_info.deps_interface_dirs]),
compile_flags = c.compile_flags,
user_compile_flags = user_compile_flags,
user_compile_flags = user_compile_flags + module_outputs.repl_info.user_compile_flags,
user_repl_flags = haskell_library_expand_make_variables("repl_ghci_args", ctx, ctx.attr.repl_ghci_args),
per_module_transitive_interfaces = module_outputs.per_module_transitive_interfaces,
per_module_transitive_objects = module_outputs.per_module_transitive_objects,
Expand Down
2 changes: 1 addition & 1 deletion haskell/providers.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ HaskellInfo = provider(
"package_databases": "Depset of package cache files.",
"empty_lib_package_databases": "Depset of package cache files corresponding to empty libraries.",
"version_macros": "Depset of version macro files.",
"import_dirs": "Import hierarchy roots.",
"import_dirs": "Set of import hierarchy roots.",
"source_files": "Depset of files that contain Haskell modules.",
"boot_files": "Depset of Haskell boot files",
"extra_source_files": "Depset of non-Haskell source files.",
Expand Down
56 changes: 34 additions & 22 deletions haskell/repl.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ HaskellReplLoadInfo = provider(
Information to a Haskell target to load into the REPL as source.
""",
fields = {
"source_files": "Set of files that contain Haskell modules.",
"boot_files": "Set of Haskell boot files.",
"import_dirs": "Set of Haskell import directories.",
"source_files": "Depset of files that contain Haskell modules.",
"boot_files": "Depset of Haskell boot files.",
"import_dirs": "Depset of Haskell import directories.",
"cc_libraries_info": "HaskellCcLibrariesInfo of transitive C dependencies.",
"cc_info": "CcInfo of transitive C dependencies.",
"compiler_flags": "Flags to pass to the Haskell compiler.",
Expand Down Expand Up @@ -183,24 +183,32 @@ def _create_HaskellReplCollectInfo(target, ctx):
hs_info = target[HaskellInfo]

if not HaskellToolchainLibraryInfo in target:
java_deps_list = []

if hasattr(ctx.rule.attr, "deps"):
java_deps = java_interop_info(ctx.rule.attr.deps).inputs
else:
java_deps = depset()
java_deps_list += [java_interop_info(ctx.rule.attr.deps).inputs]

# TODO[GL]: add tests for the java deps in narrowed_deps
if hasattr(ctx.rule.attr, "narrowed_deps"):
java_deps_list += [java_interop_info(ctx.rule.attr.narrowed_deps).inputs]

java_deps = depset(transitive = java_deps_list)

# TODO[GL]: add tests for CcInfo deps in narrowed_deps
ccInfoDeps = [
dep
for dep in getattr(ctx.rule.attr, "deps", []) + getattr(ctx.rule.attr, "narrowed_deps", [])
if CcInfo in dep and not HaskellInfo in dep
]
load_infos[target.label] = HaskellReplLoadInfo(
source_files = hs_info.source_files,
boot_files = hs_info.boot_files,
import_dirs = set.to_depset(hs_info.import_dirs),
cc_libraries_info = deps_HaskellCcLibrariesInfo([
dep
for dep in getattr(ctx.rule.attr, "deps", [])
if CcInfo in dep and not HaskellInfo in dep
]),
cc_libraries_info = deps_HaskellCcLibrariesInfo(ccInfoDeps),
cc_info = cc_common.merge_cc_infos(cc_infos = [
# Collect pure C library dependencies, no Haskell dependencies.
dep[CcInfo]
for dep in getattr(ctx.rule.attr, "deps", [])
if CcInfo in dep and not HaskellInfo in dep
for dep in ccInfoDeps
]),
compiler_flags = hs_info.user_compile_flags,
repl_ghci_args = hs_info.user_repl_flags,
Expand Down Expand Up @@ -546,18 +554,19 @@ def _create_hie_bios(hs, cc, posix, ctx, repl_info, path_prefix):
return [OutputGroupInfo(hie_bios = [args_link])]

def _haskell_repl_aspect_impl(target, ctx):
# TODO[GL]: try removing this and using required_providers, once we're on a newer version of bazel
if HaskellInfo not in target:
return []

target_info = _create_HaskellReplCollectInfo(target, ctx)
if hasattr(ctx.rule.attr, "deps"):
deps_infos = [
dep[HaskellReplCollectInfo]
for dep in ctx.rule.attr.deps
if HaskellReplCollectInfo in dep
]
else:
deps_infos = []

deps_infos = [
dep[HaskellReplCollectInfo]
for deps_field_name in ["deps", "narrowed_deps"]
for dep in getattr(ctx.rule.attr, deps_field_name, [])
if HaskellReplCollectInfo in dep
]

collect_info = _merge_HaskellReplCollectInfo([target_info] + deps_infos)

# This aspect currently does not generate an executable REPL script by
Expand All @@ -566,9 +575,12 @@ def _haskell_repl_aspect_impl(target, ctx):

return [collect_info]

# We don't have a provides field here, since we might not actually return HaskellReplCollectInfo,
# if the target doesn't have a HaskellInfo.
# TODO[GL]: try adding it once we can use required_providers.
haskell_repl_aspect = aspect(
implementation = _haskell_repl_aspect_impl,
attr_aspects = ["deps"],
attr_aspects = ["deps", "narrowed_deps"],
required_aspect_providers = [HaskellCcLibrariesInfo],
doc = """\
Haskell REPL aspect.
Expand Down
1 change: 1 addition & 0 deletions tests/haskell_module/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ filegroup(
"//tests/haskell_module/th:all_files",
"//tests/haskell_module/tools:all_files",
"//tests/haskell_module/hsc:all_files",
"//tests/haskell_module/repl:all_files",
],
visibility = ["//visibility:public"],
)
32 changes: 32 additions & 0 deletions tests/haskell_module/repl/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
load("//tests:integration_tests.bzl", "integration_test")

package(default_testonly = 1)

integration_test(
name = "haskell_module_repl_test",
size = "small",
bazel = "//tests:bazel",
tags = [
# See https://github.com/tweag/rules_haskell/issues/1486
"dont_test_on_darwin_with_bindist",
"dont_test_on_windows",
],
)

integration_test(
name = "haskell_module_repl_cross_library_deps_test",
size = "small",
bazel = "//tests:bazel",
tags = [
# See https://github.com/tweag/rules_haskell/issues/1486
"dont_test_on_darwin_with_bindist",
"dont_test_on_windows",
],
)

filegroup(
name = "all_files",
testonly = True,
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)
Loading

0 comments on commit b62ea9e

Please sign in to comment.