Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions decls/haskell_common.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ def _deps_arg():
from which this rules sources import modules or native linkable rules exporting symbols
this rules sources call into.
"""),
"srcs_deps": attrs.dict(attrs.source(), attrs.list(attrs.source()), default = {}, doc = """
Allows to declare dependencies for sources manually, additionally to the dependencies automatically detected.
"""),
}

def _compiler_flags_arg():
Expand Down
33 changes: 17 additions & 16 deletions haskell/compile.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ PackagesInfo = record(
exposed_package_dbs = field(list[Artifact]),
packagedb_args = cmd_args,
transitive_deps = field(HaskellLibraryInfoTSet),
bin_paths = cmd_args,
)

_Module = record(
Expand Down Expand Up @@ -246,9 +247,6 @@ def target_metadata(

def get_metadata(ctx, _artifacts, resolved, outputs, catalog=catalog):

pkg_deps = resolved[haskell_toolchain.packages.dynamic]
package_db = pkg_deps[DynamicHaskellPackageDbInfo].packages

# Add -package-db and -package/-expose-package flags for each Haskell
# library dependency.

Expand All @@ -265,18 +263,13 @@ def target_metadata(
ghc_args.add("-hide-all-packages")
ghc_args.add(package_flag, "base")

package_dbs = ctx.actions.tset(
HaskellPackageDbTSet,
children = [package_db[name] for name in toolchain_libs if name in package_db]
)

ghc_args.add(cmd_args(toolchain_libs, prepend=package_flag))
ghc_args.add(cmd_args(packages_info.exposed_package_args))
ghc_args.add(cmd_args(packages_info.packagedb_args, prepend = "-package-db"))
ghc_args.add(cmd_args(package_dbs.project_as_args("package_db"), prepend="-package-db"))
ghc_args.add(ctx.attrs.compiler_flags)

md_args = cmd_args(md_gen)
md_args.add(packages_info.bin_paths)
md_args.add("--toolchain-libs", catalog)
md_args.add("--ghc", haskell_toolchain.compiler)
md_args.add(cmd_args(ghc_args, format="--ghc-arg={}"))
Expand Down Expand Up @@ -403,8 +396,10 @@ def get_packages_info(
)

packagedb_args.add(package_db_tset.project_as_args("package_db"))
bin_paths = cmd_args(package_db_tset.project_as_args("path"), format="--bin-path={}/bin")
else:
packagedb_args.add(haskell_toolchain.packages.package_db)
bin_paths = cmd_args()

# Expose only the packages we depend on directly
for lib in haskell_direct_deps_lib_infos:
Expand All @@ -423,6 +418,7 @@ def get_packages_info(
exposed_package_dbs = exposed_package_dbs,
packagedb_args = packagedb_args,
transitive_deps = libs,
bin_paths = bin_paths,
)

def _compile_module(
Expand Down Expand Up @@ -547,20 +543,25 @@ def _compile_module(
compile_args_for_file.add("-o", objects[0].as_output())
compile_args_for_file.add("-ohi", his[0].as_output())
compile_args_for_file.add("-stubdir", stubs.as_output())
compile_args_for_file.add(packages_info.bin_paths)

if link_style in [LinkStyle("static_pic"), LinkStyle("static")]:
compile_args_for_file.add("-dynamic-too")
compile_args_for_file.add("-dyno", objects[1].as_output())
compile_args_for_file.add("-dynohi", his[1].as_output())

compile_args_for_file.add(module.source)
for (path, src) in srcs_to_pairs(ctx.attrs.srcs):
# hs-boot files aren't expected to be an argument to compiler but does need
# to be included in the directory of the associated src file
# TODO(ah) We should not indiscriminately include all non-hs sources,
# but only those that this module actually depends on.
if not is_haskell_src(path):
compile_args_for_file.hidden(src)

aux_deps = ctx.attrs.srcs_deps.get(module.source)
if aux_deps:
compile_args_for_file.hidden(aux_deps)

non_haskell_sources = [src for (path, src) in srcs_to_pairs(ctx.attrs.srcs) if not is_haskell_src(path)]

if non_haskell_sources:
warning("{} specifies non-haskell file in `srcs`, consider using `srcs_deps` instead".format(ctx.label))

compile_args_for_file.hidden(non_haskell_sources)

if haskell_toolchain.use_argsfile:
argsfile = ctx.actions.declare_output(
Expand Down
2 changes: 0 additions & 2 deletions haskell/haskell.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,6 @@ def _build_haskell_lib(
non_profiling_hlib: [HaskellLibBuildOutput, None] = None) -> HaskellLibBuildOutput:
linker_info = ctx.attrs._cxx_toolchain[CxxToolchainInfo].linker_info

toolchain_libs = [dep[HaskellToolchainLibrary].name for dep in ctx.attrs.deps if HaskellToolchainLibrary in dep]

# Link the objects into a library
haskell_toolchain = ctx.attrs._haskell_toolchain[HaskellToolchainInfo]

Expand Down
13 changes: 11 additions & 2 deletions haskell/toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,21 @@ HaskellPackagesInfo = record(
dynamic = DynamicValue,
)

def _haskell_package_info_as_package_db(p: Artifact):
return cmd_args(p)
HaskellPackage = record(
db = Artifact,
path = Artifact,
)

def _haskell_package_info_as_package_db(p: HaskellPackage):
return cmd_args(p.db)

def _haskell_package_info_as_package_path(p: HaskellPackage):
return cmd_args(p.path)

HaskellPackageDbTSet = transitive_set(
args_projections = {
"package_db": _haskell_package_info_as_package_db,
"path": _haskell_package_info_as_package_path,
}
)

Expand Down
19 changes: 16 additions & 3 deletions haskell/tools/generate_target_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ def main():
action="append",
default=[],
help="Package dependencies formated as `NAME:PREFIX_PATH`.")
parser.add_argument(
"--bin-path",
type=Path,
action="append",
default=[],
help="Add given path to PATH.",
)
args = parser.parse_args()

result = obtain_target_metadata(args)
Expand All @@ -82,7 +89,8 @@ def json_default_handler(o):
def obtain_target_metadata(args):
toolchain_packages = load_toolchain_packages(args.toolchain_libs)
ghc_args = fix_ghc_args(args.ghc_arg, toolchain_packages)
ghc_depends, ghc_options = run_ghc_depends(args.ghc, ghc_args, args.source)
paths = [str(binpath) for binpath in args.bin_path if binpath.is_dir()]
ghc_depends, ghc_options = run_ghc_depends(args.ghc, ghc_args, args.source, paths)
th_modules = determine_th_modules(ghc_options, args.source_prefix)
package_prefixes = calc_package_prefixes(args.package)
module_mapping, module_graph, package_deps, toolchain_deps = interpret_ghc_depends(
Expand Down Expand Up @@ -151,7 +159,7 @@ def fix_ghc_args(ghc_args, toolchain_packages):
return result


def run_ghc_depends(ghc, ghc_args, sources):
def run_ghc_depends(ghc, ghc_args, sources, aux_paths):
with tempfile.TemporaryDirectory() as dname:
json_fname = os.path.join(dname, "depends.json")
opt_json_fname = os.path.join(dname, "options.json")
Expand All @@ -165,7 +173,12 @@ def run_ghc_depends(ghc, ghc_args, sources):
"-opt-json", opt_json_fname,
"-dep-makefile", make_fname,
] + ghc_args + sources
subprocess.run(args, check=True)

env = os.environ.copy()
path = env.get("PATH", "")
env["PATH"] = os.pathsep.join([path] + aux_paths)

subprocess.run(args, env=env, check=True)

with open(json_fname) as f, open(opt_json_fname) as o:
return json.load(f), json.load(o)
Expand Down
14 changes: 13 additions & 1 deletion haskell/tools/ghc_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,24 @@ def main():
type=Path,
help="Output path of the abi file to create.",
)
parser.add_argument(
"--bin-path",
type=Path,
action="append",
default=[],
help="Add given path to PATH.",
)

args, ghc_args = parser.parse_known_args()

cmd = [args.ghc] + ghc_args

subprocess.check_call(cmd)
aux_paths = [str(binpath) for binpath in args.bin_path if binpath.is_dir()]
env = os.environ.copy()
path = env.get("PATH", "")
env["PATH"] = os.pathsep.join([path] + aux_paths)

subprocess.check_call(cmd, env=env)

recompute_abi_hash(args.ghc, args.abi_out)

Expand Down