Fix packaging of ghc-pkg on Unix systems (#666)

This also changes --package-db to --global-package-db since ghc-pkg
will otherwise try to find a global package db itself.
This commit is contained in:
Moritz Kiefer 2019-04-25 13:10:28 +02:00 committed by GitHub
parent 1a1a1c81e0
commit 26d0dcfc8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 7 deletions

View File

@ -198,6 +198,19 @@ filegroup(
repositories = dev_env_nix_repos,
) if is_linux else None
# This is used to get ghc-pkg on Linux.
nixpkgs_package(
name = "ghc_nix",
attribute_path = "ghc.ghc",
build_file_content = """
package(default_visibility = ["//visibility:public"])
exports_files(glob(["lib/**/*"]))
""",
nix_file = "//nix:bazel.nix",
nix_file_deps = common_nix_file_deps,
repositories = dev_env_nix_repos,
) if not is_windows else None
# Used by Darwin and Linux
haskell_register_ghc_nixpkgs(
attribute_path = "ghcWithC2hs",

View File

@ -16,7 +16,7 @@
# On Windows we only handle statically linked binaries
# (Haskell binaries are linked statically on Windows) so we
# just copy the binary and the resources and create a tarball from that.
set -e
set -eou pipefail
WORKDIR="$(mktemp -d)"
trap "rm -rf $WORKDIR" EXIT
@ -26,13 +26,19 @@ OUT=$2
shift 2
NAME=$(basename $SRC)
mkdir -p $WORKDIR/$NAME/lib
export ORIGIN=$(dirname $SRC) # for rpaths relative to binary
export ORIGIN=$(dirname $(readlink -f $SRC)) # for rpaths relative to binary
# Copy in resources, if any.
if [ $# -gt 0 ]; then
mkdir -p $WORKDIR/$NAME/resources
for res in $*; do
cp -aL "$res" "$WORKDIR/$NAME/resources"
if [[ "$res" == *.tar.gz ]]; then
# If a resource is a tarball, e.g., because it originates from another
# rule we extract it.
tar xf "$res" --strip-components=1 -C "$WORKDIR/$NAME/resources"
else
cp -aL "$res" "$WORKDIR/$NAME/resources"
fi
done
fi
@ -111,11 +117,34 @@ elif [[ "$(uname -s)" == "Darwin" ]]; then
chmod u+w $WORKDIR/$NAME/$NAME
function copy_deps() {
local from=$1
local needed="$(/usr/bin/otool -L "$from" | sed -n -e '1d' -e '/\/nix\/store/ s/^.*\(\/nix\/store[^ ]*\).*/\1/p')"
local needed="$(/usr/bin/otool -L "$from" | sed -n -e '1d' -e 's/^\s*\([^ ]*\).*$/\1/p')"
loader_path="$ORIGIN"
local rpaths="$(/usr/bin/otool -l $from | sed -n '/cmd LC_RPATH/{n;n;p;}' | sed -n -e 's/^.*path \([^ ]*\).*$/\1/p' | sed -e "s|@loader_path|$loader_path|")"
for lib in $needed; do
local libName="$(basename $lib)"
if [[ "$libName" == "libSystem.B.dylib" ]]; then
/usr/bin/install_name_tool -change "$lib" "/usr/lib/$libName" "$from"
/usr/bin/install_name_tool -change "$lib" "/usr/lib/$libName" "$from"
elif [[ "$lib" == @rpath/* ]]; then
libName="${lib#@rpath/}"
local to="$WORKDIR/$NAME/lib/$libName"
if [[ ! -f "$to" ]]; then
libOK=0
for rpath in $rpaths; do
if [[ -e "$rpath/$libName" ]]; then
libOK=1
cp "$rpath/$libName" "$to"
chmod 0755 "$to"
/usr/bin/install_name_tool -add_rpath "@loader_path/lib" "$to"
copy_deps "$to"
break
fi
done
if [[ $libOK -ne 1 ]]; then
echo "ERROR: Dynamic library $lib for $from not found from RPATH!"
echo "RPATH=$rpaths"
return 1
fi
fi
else
/usr/bin/install_name_tool -change "$lib" "@rpath/$libName" "$from"

View File

@ -67,6 +67,7 @@ package_app = rule(
"binary": attr.label(
cfg = "target",
executable = True,
allow_files = True,
),
"resources": attr.label_list(
allow_files = True,

View File

@ -378,7 +378,9 @@ createProjectPackageDb lfVersion fps = do
unwords
[ sdkRoot </> "damlc/resources/ghc-pkg"
, "recache"
, "--package-db=" ++ dbPath
-- ghc-pkg insists on using a global package db and will trie
-- to find one automatically if we dont specify it here.
, "--global-package-db=" ++ dbPath
, "--expand-pkgroot"
]

View File

@ -54,15 +54,26 @@ package_app(
name = "damlc-dist",
binary = ":da-hs-damlc-app",
resources = [
":ghc-pkg-dist",
"//compiler/scenario-service/server:scenario_service_jar",
"//daml-foundations/daml-ghc/package-database:gen-daml-prim.dar",
"//daml-foundations/daml-ghc/package-database:package-db",
"@io_tweag_rules_haskell_ghc_windows_amd64//:bin/ghc-pkg.exe" if is_windows else "@io_tweag_rules_haskell_ghc-nixpkgs//:bin/ghc-pkg",
],
tags = ["no-cache"],
visibility = ["//visibility:public"],
)
# ghc-pkg is linked dynamically on Linux by default so we need to run it through package_app
# before we distribute it.
package_app(
name = "ghc-pkg-dist",
# bin/ghc-pkg is actually a wrapper script on Unix systems so it is
# important that we use lib/ghc-8.6.4/bin/ghc-pkg instead which is the
# actual executable.
binary = "@io_tweag_rules_haskell_ghc_windows_amd64//:bin/ghc-pkg.exe" if is_windows else "@ghc_nix//:lib/ghc-8.6.4/bin/ghc-pkg",
visibility = ["//visibility:public"],
)
sh_test(
name = "dist-test",
srcs = ["test/check-dist.sh"],