Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support GHC with static RTS #970

Merged
merged 3 commits into from
Jul 10, 2019
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
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
name: Setup test environment
command: |
apt-get update
apt-get install -y wget gnupg golang make libgmp3-dev libtinfo-dev pkg-config zip g++ zlib1g-dev unzip python python3 bash-completion locales
apt-get install -y wget gnupg golang make libgmp3-dev libtinfo-dev libtinfo5 pkg-config zip g++ zlib1g-dev unzip python python3 bash-completion locales
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
wget "https://github.com/bazelbuild/bazel/releases/download/0.27.0/bazel_0.27.0-linux-x86_64.deb"
Expand Down
38 changes: 17 additions & 21 deletions haskell/cabal.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,17 @@ load(":private/context.bzl", "haskell_context", "render_env")
load(":private/dependencies.bzl", "gather_dep_info")
load(":private/mode.bzl", "is_profiling_enabled")
load(":private/set.bzl", "set")
load(
":private/workspace_utils.bzl",
_execute_or_fail_loudly = "execute_or_fail_loudly",
)
load(
":providers.bzl",
"HaskellInfo",
"HaskellLibraryInfo",
"get_ghci_extra_libs",
)

def _as_string(v):
if type(v) == "string":
return v
else:
return repr(v)

def _execute_or_fail_loudly(repository_ctx, arguments):
exec_result = repository_ctx.execute(arguments)
if exec_result.return_code != 0:
arguments = [_as_string(x) for x in arguments]
fail("\n".join(["Command failed: " + " ".join(arguments), exec_result.stderr]))
return exec_result

def _so_extension(hs):
return "dylib" if hs.toolchain.is_darwin else "so"

Expand Down Expand Up @@ -177,10 +168,13 @@ def _haskell_cabal_library_impl(ctx):
static_library_filename,
sibling = cabal,
)
dynamic_library = hs.actions.declare_file(
"_install/lib/libHS{}-ghc{}.{}".format(name, hs.toolchain.version, _so_extension(hs)),
sibling = cabal,
)
if hs.toolchain.is_static:
dynamic_library = None
else:
dynamic_library = hs.actions.declare_file(
"_install/lib/libHS{}-ghc{}.{}".format(name, hs.toolchain.version, _so_extension(hs)),
sibling = cabal,
)
(tool_inputs, tool_input_manifests) = ctx.resolve_tools(tools = ctx.attr.tools)
c = _prepare_cabal_inputs(
hs,
Expand All @@ -204,17 +198,16 @@ def _haskell_cabal_library_impl(ctx):
package_database,
interfaces_dir,
static_library,
dynamic_library,
data_dir,
],
] + ([dynamic_library] if dynamic_library != None else []),
env = c.env,
mnemonic = "HaskellCabalLibrary",
progress_message = "HaskellCabalLibrary {}".format(hs.label),
use_default_shell_env = True,
)

default_info = DefaultInfo(
files = depset([static_library, dynamic_library]),
files = depset([static_library] + ([dynamic_library] if dynamic_library != None else [])),
runfiles = ctx.runfiles(
files = [data_dir],
collect_default = True,
Expand All @@ -231,7 +224,10 @@ def _haskell_cabal_library_impl(ctx):
transitive = [dep_info.static_libraries],
order = "topological",
),
dynamic_libraries = depset([dynamic_library], transitive = [dep_info.dynamic_libraries]),
dynamic_libraries = depset(
direct = [dynamic_library] if dynamic_library != None else [],
transitive = [dep_info.dynamic_libraries],
),
interface_dirs = depset([interfaces_dir], transitive = [dep_info.interface_dirs]),
compile_flags = [],
)
Expand Down
3 changes: 3 additions & 0 deletions haskell/ghc_bindist.bzl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Workspace rules (GHC binary distributions)"""

load("@bazel_tools//tools/build_defs/repo:utils.bzl", "patch")
load("@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value")

_GHC_DEFAULT_VERSION = "8.6.5"

Expand Down Expand Up @@ -253,6 +254,7 @@ haskell_toolchain(
tools = [":bin"],
libraries = toolchain_libraries,
version = "{version}",
is_static = {is_static},
compiler_flags = {compiler_flags},
haddock_flags = {haddock_flags},
repl_ghci_args = {repl_ghci_args},
Expand All @@ -261,6 +263,7 @@ haskell_toolchain(
""".format(
toolchain_libraries = toolchain_libraries,
version = ctx.attr.version,
is_static = os == "windows",
compiler_flags = ctx.attr.compiler_flags,
haddock_flags = ctx.attr.haddock_flags,
repl_ghci_args = ctx.attr.repl_ghci_args,
Expand Down
5 changes: 5 additions & 0 deletions haskell/nixpkgs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ haskell_toolchain(
tools = {tools},
libraries = toolchain_libraries,
version = "{version}",
is_static = {is_static},
compiler_flags = {compiler_flags} + {compiler_flags_select},
haddock_flags = {haddock_flags},
repl_ghci_args = {repl_ghci_args},
Expand All @@ -76,6 +77,7 @@ haskell_toolchain(
toolchain_libraries = toolchain_libraries,
tools = ["@io_tweag_rules_haskell_ghc_nixpkgs//:bin"],
version = repository_ctx.attr.version,
is_static = repository_ctx.attr.is_static,
compiler_flags = repository_ctx.attr.compiler_flags,
compiler_flags_select = compiler_flags_select,
haddock_flags = repository_ctx.attr.haddock_flags,
Expand All @@ -91,6 +93,7 @@ _ghc_nixpkgs_haskell_toolchain = repository_rule(
# These attributes just forward to haskell_toolchain.
# They are documented there.
"version": attr.string(),
"is_static": attr.bool(),
"compiler_flags": attr.string_list(),
"compiler_flags_select": attr.string_list_dict(),
"haddock_flags": attr.string_list(),
Expand Down Expand Up @@ -144,6 +147,7 @@ _ghc_nixpkgs_toolchain = repository_rule(_ghc_nixpkgs_toolchain_impl)

def haskell_register_ghc_nixpkgs(
version,
is_static = False,
build_file = None,
build_file_content = None,
compiler_flags = None,
Expand Down Expand Up @@ -209,6 +213,7 @@ def haskell_register_ghc_nixpkgs(
_ghc_nixpkgs_haskell_toolchain(
name = haskell_toolchain_repo_name,
version = version,
is_static = is_static,
compiler_flags = compiler_flags,
compiler_flags_select = compiler_flags_select,
haddock_flags = haddock_flags,
Expand Down
5 changes: 5 additions & 0 deletions haskell/private/actions/compile.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ def _compilation_defaults(hs, cc, java, dep_info, plugin_dep_info, cc_info, srcs
# to debug issues in non-sandboxed builds.
"-Wmissing-home-modules",
])
if hs.toolchain.is_static and not hs.toolchain.is_windows:
# A static GHC RTS requires -fPIC. However, on Unix we also require
# -fexternal-dynamic-refs, otherwise GHC still generates R_X86_64_PC32
# relocations which prevents loading these static libraries as PIC.
args.add("-fexternal-dynamic-refs")

# Output directories
args.add_all([
Expand Down
8 changes: 4 additions & 4 deletions haskell/private/haskell_impl.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,11 @@ def _haskell_binary_common_impl(ctx, is_test):
inspect_coverage = _should_inspect_coverage(ctx, hs, is_test)

dynamic = not ctx.attr.linkstatic
if with_profiling or hs.toolchain.is_windows:
if with_profiling or hs.toolchain.is_static:
# NOTE We can't have profiling and dynamic code at the
# same time, see:
# https://ghc.haskell.org/trac/ghc/ticket/15394
# Also, GHC on Windows doesn't support dynamic code
# Also, static GHC doesn't support dynamic code
dynamic = False

plugins = [_resolve_plugin_tools(ctx, plugin[GhcPluginInfo]) for plugin in ctx.attr.plugins]
Expand Down Expand Up @@ -388,11 +388,11 @@ def haskell_library_impl(ctx):
srcs_files, import_dir_map = _prepare_srcs(ctx.attr.srcs)

with_shared = not ctx.attr.linkstatic
if with_profiling or hs.toolchain.is_windows:
if with_profiling or hs.toolchain.is_static:
# NOTE We can't have profiling and dynamic code at the
# same time, see:
# https://ghc.haskell.org/trac/ghc/ticket/15394
# Also, GHC on Windows doesn't support dynamic code
# Also, static GHC doesn't support dynamic code
with_shared = False

package_name = getattr(ctx.attr, "package_name", None)
Expand Down
42 changes: 42 additions & 0 deletions haskell/private/workspace_utils.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
load("@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value")

def execute_or_fail_loudly(repository_ctx, arguments):
"""Execute the given command

Fails if the command does not exit with exit-code 0.

Args:
arguments: List, the command line to execute.

Returns:
exec_result: The output of the command.

"""
exec_result = repository_ctx.execute(arguments)
if exec_result.return_code != 0:
arguments = [_as_string(x) for x in arguments]
fail("\n".join(["Command failed: " + " ".join(arguments), exec_result.stderr]))
return exec_result

def _as_string(v):
if type(v) == "string":
return v
else:
return repr(v)

def _find_ghc(repository_ctx):
"""Find the GHC executable in the current workspace.

Returns:
path, The path to the GHC executable.

"""
if get_cpu_value(repository_ctx) == "x64_windows":
ghc = repository_ctx.path("bin/ghc.exe")
else:
ghc = repository_ctx.path("bin/ghc")

if not ghc.exists:
fail("Cannot find GHC executable in {}.".format(ghc))

return ghc
4 changes: 2 additions & 2 deletions haskell/providers.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ def get_extra_libs(hs, cc_info, dynamic = False, pic = None, fixup_dir = "_libs"
if pic == None:
pic = dynamic

# PIC is irrelevant on Windows.
pic_required = pic and not hs.toolchain.is_windows
# PIC is irrelevant on static GHC.
pic_required = pic and not hs.toolchain.is_static
for lib_to_link in libs_to_link:
dynamic_lib = None
if lib_to_link.dynamic_library:
Expand Down
7 changes: 7 additions & 0 deletions haskell/toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ fi
libraries = libraries,
is_darwin = ctx.attr.is_darwin,
is_windows = ctx.attr.is_windows,
is_static = ctx.attr.is_static,
version = ctx.attr.version,
# Pass through the version_file, that it can be required as
# input in _run_ghc, to make every call to GHC depend on a
Expand Down Expand Up @@ -237,6 +238,9 @@ _haskell_toolchain = rule(
doc = "Whether compile on and for Windows.",
mandatory = True,
),
"is_static": attr.bool(
doc = "Whether GHC was linked statically.",
),
"locale": attr.string(
default = "en_US.UTF-8",
doc = "Locale that will be set during compiler invocations.",
Expand All @@ -257,6 +261,7 @@ Label pointing to the locale archive file to use. Mostly useful on NixOS.
def haskell_toolchain(
name,
version,
is_static,
tools,
libraries,
compiler_flags = [],
Expand All @@ -279,6 +284,7 @@ def haskell_toolchain(
haskell_toolchain(
name = "ghc",
version = "1.2.3",
is_static = is_static,
tools = ["@sys_ghc//:bin"],
compiler_flags = ["-Wall"],
)
Expand All @@ -300,6 +306,7 @@ def haskell_toolchain(
_haskell_toolchain(
name = name,
version = version,
is_static = is_static,
tools = tools,
libraries = libraries,
compiler_flags = compiler_flags,
Expand Down