daml/bazel_tools/haskell-cc-wrapper-globbing.patch
Andreas Herrmann cf6814e93b Use cc_wrapper to shorten library and include paths and rpaths (#2791)
* Fix bazel query deps(//...)

* Add rules_haskell cc_wrapper

Updates to latest rules_haskell master and adds the cc_wrapper PR as a
patch, see https://github.com/tweag/rules_haskell/pull/1039.

* Shorten include dirs in cc-wrapper

When using `haskell_cabal_library` GHC constructs unnecessarily long
include directories which can quickly overflow the maximum command-line
length. This patch avoids the issue by normalizing include paths.

* glob --> breadth_first_walk
2019-09-09 15:50:51 +00:00

90 lines
3.4 KiB
Diff

From 59c5965c376ca5a25706046a98271cdbfda9d22f Mon Sep 17 00:00:00 2001
From: Andreas Herrmann <andreas.herrmann@tweag.io>
Date: Mon, 9 Sep 2019 13:00:08 +0200
Subject: [PATCH] glob --> breadth_first_walk
globbing to search for the solib directory can take very long if the
current directory contains a large number of files or directories. This
can be an issue when executing `haskell_repl` targets.
This change uses a breadth first recursive directory walk instead of
`glob`. We are looking for the shortest path matching the solib
directory, the first match in a breadth first search will be the
shortest one.
---
haskell/private/cc_wrapper.bzl | 1 +
haskell/private/cc_wrapper.py.tpl | 31 ++++++++++++++++++++++++++++---
2 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/haskell/private/cc_wrapper.bzl b/haskell/private/cc_wrapper.bzl
index 10102961..f39c6b5f 100644
--- a/haskell/private/cc_wrapper.bzl
+++ b/haskell/private/cc_wrapper.bzl
@@ -20,6 +20,7 @@ def _cc_wrapper_impl(ctx):
is_executable = True,
substitutions = {
"{:cc:}": cc,
+ "{:cpu:}": cc_toolchain.cpu,
"{:workspace:}": ctx.workspace_name,
"{:platform:}": ctx.attr.platform,
},
diff --git a/haskell/private/cc_wrapper.py.tpl b/haskell/private/cc_wrapper.py.tpl
index 92edaa15..2fb4ec73 100644
--- a/haskell/private/cc_wrapper.py.tpl
+++ b/haskell/private/cc_wrapper.py.tpl
@@ -39,6 +39,7 @@ used to avoid command line length limitations.
from bazel_tools.tools.python.runfiles import runfiles as bazel_runfiles
from contextlib import contextmanager
+from collections import deque
import glob
import itertools
import os
@@ -599,6 +600,30 @@ def sort_rpaths(rpaths):
return sorted(rpaths, key=rpath_priority)
+def breadth_first_walk(top):
+ """Walk the directory tree starting from the given directory
+
+ Returns an iterator that will recursively walk through the directory
+ similar to `os.walk`. However, contrary to `os.walk` this function iterates
+ through the directory tree in a breadth first fashion.
+
+ Yields:
+ (root, dirnames, filenames)
+ root: The current directory relative to `top`.
+ dirnames: List of directory names contained in `root`.
+ filenames: List of file names contained in `root`.
+
+ """
+ stack = deque([top])
+ while stack:
+ current = stack.popleft()
+ # os.walk performs the separation of file and directory entries. But,
+ # it iterates depth-first. So, we only use os.walk one level deep.
+ for root, dirs, files in itertools.islice(os.walk(current, followlinks = True), 1):
+ yield (root, dirs, files)
+ stack.extend(os.path.join(root, dirname) for dirname in dirs)
+
+
def find_solib_rpath(rpaths, output):
"""Find the solib directory rpath entry.
@@ -618,9 +643,9 @@ def find_solib_rpath(rpaths, output):
# GHC generates temporary libraries outside the execroot. In that case
# the Bazel generated RPATHs are not forwarded, and the solib directory
# is not visible on the command-line.
- candidates = glob.glob("**/bin/_solib_*", recursive=True)
- if candidates:
- return min(candidates)
+ for (root, dirnames, _) in breadth_first_walk("."):
+ if "_solib_{:cpu:}" in dirnames:
+ return os.path.join(root, "_solib_{:cpu:}")
return None
--
2.21.0