Skip to content

Commit

Permalink
Bazelify compiler's global package database
Browse files Browse the repository at this point in the history
Exposing GHC's global package database to Bazel enables us to stop
treating prebuilt libraries specially. They now export
a `HaskellLibraryInfo` like any other library. Even better, they now
also export a `CcInfo` provider like any other native code library,
which means that CC rules have a full view of all static archives
needed for linking a binary statically (see the `cc_haskell_import`
test, which no longer requires `linkstatic = False`).

`HaskellPrebuiltPackageInfo` is still there but now has no content.
It's only there to prevent aspects from reaching too far. We'll get
rid of it in future commits.

Fixes #838
  • Loading branch information
mboes committed May 6, 2019
1 parent 4644008 commit a552896
Show file tree
Hide file tree
Showing 28 changed files with 546 additions and 136 deletions.
2 changes: 1 addition & 1 deletion .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Use this configuration when targeting Windows. Eventually this will
# no longer be required:
# https://bazel.build/roadmaps/platforms.html#replace---cpu-and---host_cpu-flags.
build:windows --crosstool_top=@io_tweag_rules_haskell_ghc_windows_amd64//:toolchain -s --verbose_failures --sandbox_debug
build:windows --crosstool_top=@io_tweag_rules_haskell_ghc_windows_amd64//:cc_toolchain -s --verbose_failures --sandbox_debug

build:ci --loading_phase_threads=1
build:ci --jobs=2
Expand Down
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 bash-completion locales
apt-get install -y wget gnupg golang make libgmp3-dev libtinfo-dev 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.24.0/bazel_0.24.0-linux-x86_64.deb"
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
change, because nearly no one uses these functions directly. They
are normally only used transitively via
`haskell_register_toolchains` and related functions.
* It is now possible to statically link Haskell libraries in CC
binaries.

## [0.8] - 2019-01-28

Expand Down
1 change: 0 additions & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ load(
haskell_nixpkgs_package(
name = "ghc",
attribute_path = "haskellPackages.ghc",
build_file = "//haskell:ghc.BUILD",
nix_file = "//tests:ghc.nix",
nix_file_deps = ["//nixpkgs:default.nix"],
# rules_nixpkgs assumes we want to read from `<nixpkgs>` implicitly
Expand Down
4 changes: 4 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ jobs:
pool:
vmImage: 'vs2017-win2016'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.7'
architecture: 'x64'
- bash: |
set -e
curl -LO https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-windows-x86_64.exe
Expand Down
7 changes: 7 additions & 0 deletions haskell/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ exports_files(
"private/haddock_wrapper.sh.tpl",
"private/coverage_wrapper.sh.tpl",
"private/osx_cc_wrapper.sh.tpl",
"private/pkgdb_to_bzl.py",
],
)

Expand All @@ -14,6 +15,12 @@ exports_files(
visibility = ["//tests/unit-tests:__pkg__"],
)

py_binary(
name = "pkgdb_to_bzl",
srcs = ["private/pkgdb_to_bzl.py"],
visibility = ["//visibility:public"],
)

py_binary(
name = "ls_modules",
srcs = ["private/ls_modules.py"],
Expand Down
3 changes: 2 additions & 1 deletion haskell/doctest.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ load(
"@io_tweag_rules_haskell//haskell:providers.bzl",
"HaskellInfo",
"HaskellLibraryInfo",
"HaskellPrebuiltPackageInfo",
)

def _doctest_toolchain_impl(ctx):
Expand Down Expand Up @@ -80,7 +81,7 @@ def _haskell_doctest_single(target, ctx):
File: the doctest log.
"""

if HaskellInfo not in target:
if HaskellInfo not in target or HaskellPrebuiltPackageInfo in target:
return []

hs = haskell_context(ctx, ctx.attr)
Expand Down
83 changes: 0 additions & 83 deletions haskell/ghc.BUILD

This file was deleted.

45 changes: 45 additions & 0 deletions haskell/ghc.BUILD.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
load(
"@io_tweag_rules_haskell//haskell:haskell.bzl",
"haskell_import",
"haskell_toolchain",
)

%{toolchain}

filegroup(
name = "bin",
srcs = glob(["bin/*"]),
)

# Expose embedded MinGW toolchain when on Windows.

filegroup(
name = "empty",
srcs = [],
)

cc_toolchain_suite(
name = "cc_toolchain",
toolchains = {
"x64_windows": ":cc-compiler-mingw64",
"x64_windows|ghc-mingw-gcc": ":cc-compiler-mingw64",
},
visibility = ["//visibility:public"],
)

# Keep in sync with @bazel_tools//cpp:cc-compiler-x64_windows definition.
cc_toolchain(
name = "cc-compiler-mingw64",
all_files = ":empty",
ar_files = ":empty",
as_files = ":empty",
compiler_files = ":empty",
cpu = "x64_windows",
dwp_files = ":empty",
linker_files = ":empty",
objcopy_files = ":empty",
strip_files = ":empty",
supports_param_files = 0,
toolchain_identifier = "ghc_windows_mingw64",
visibility = ["//visibility:public"],
)
60 changes: 43 additions & 17 deletions haskell/ghc_bindist.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ load("@bazel_tools//tools/build_defs/repo:utils.bzl", "patch")
def _ghc_bindist_impl(ctx):
# Avoid rule restart by resolving these labels early. See
# https://github.com/bazelbuild/bazel/blob/master/tools/cpp/lib_cc_configure.bzl#L17.
ghc_build = ctx.path(Label("//haskell:ghc.BUILD"))
crosstool_windows = ctx.path(Label("//haskell:CROSSTOOL.windows"))
crosstool_windows = ctx.path(Label("@io_tweag_rules_haskell//haskell:CROSSTOOL.windows"))
ghc_build = ctx.path(Label("@io_tweag_rules_haskell//haskell:ghc.BUILD.tpl"))

version = ctx.attr.version
target = ctx.attr.target
Expand Down Expand Up @@ -225,30 +225,47 @@ grep -lZ {bindist_dir} bin/* | xargs -0 --verbose \\
))
_execute_fail_loudly(ctx, ["./patch_bins"])

ctx.template(
"BUILD",
executable = False,
content = """
load(
"@io_tweag_rules_haskell//haskell:haskell.bzl",
"haskell_toolchain",
)
# Generate BUILD file entries describing each prebuilt package.
# Cannot use //haskell:pkgdb_to_bzl because that's a generated
# target. ctx.path() only works on source files.
pkgdb_to_bzl = ctx.path(Label("@io_tweag_rules_haskell//haskell:private/pkgdb_to_bzl.py"))
python = _find_python(ctx)
result = ctx.execute([
python,
pkgdb_to_bzl,
ctx.attr.name,
"lib",
])
if result.return_code:
fail("Error executing pkgdb_to_bzl.py: {stderr}".format(stderr = result.stderr))
toolchain_libraries = result.stdout
toolchain = """
{toolchain_libraries}
haskell_toolchain(
name = "toolchain",
name = "toolchain-impl",
tools = [":bin"],
libraries = toolchain_libraries,
version = "{version}",
compiler_flags = {compiler_flags},
haddock_flags = {haddock_flags},
repl_ghci_args = {repl_ghci_args},
visibility = ["//visibility:public"],
)
""".format(
version = ctx.attr.version,
compiler_flags = ctx.attr.compiler_flags,
haddock_flags = ctx.attr.haddock_flags,
repl_ghci_args = ctx.attr.repl_ghci_args,
),
""".format(
toolchain_libraries = toolchain_libraries,
version = ctx.attr.version,
compiler_flags = ctx.attr.compiler_flags,
haddock_flags = ctx.attr.haddock_flags,
repl_ghci_args = ctx.attr.repl_ghci_args,
)
ctx.template(
"BUILD",
ghc_build,
substitutions = {
"%{toolchain}": toolchain,
},
executable = False,
)
ctx.template("CROSSTOOL", crosstool_windows, executable = False)

Expand Down Expand Up @@ -414,3 +431,12 @@ def haskell_register_ghc_bindists(
haddock_flags = haddock_flags,
repl_ghci_args = repl_ghci_args,
)

def _find_python(repository_ctx):
python = repository_ctx.which("python3")
if not python:
python = repository_ctx.which("python")
result = repository_ctx.execute([python, "--version"])
if not result.stdout.startswith("Python 3"):
fail("rules_haskell requires Python >= 3.3.")
return python
3 changes: 2 additions & 1 deletion haskell/haddock.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ load(
"HaddockInfo",
"HaskellInfo",
"HaskellLibraryInfo",
"HaskellPrebuiltPackageInfo",
)
load(":private/context.bzl", "haskell_context", "render_env")
load(":private/set.bzl", "set")
Expand All @@ -22,7 +23,7 @@ def _get_haddock_path(package_id):
return package_id + ".haddock"

def _haskell_doc_aspect_impl(target, ctx):
if HaskellInfo not in target or HaskellLibraryInfo not in target:
if HaskellInfo not in target or HaskellLibraryInfo not in target or HaskellPrebuiltPackageInfo in target:
return []

# Packages imported via `//haskell:import.bzl%haskell_import` already
Expand Down
28 changes: 28 additions & 0 deletions haskell/haskell.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ load(
load(
":private/haskell_impl.bzl",
_haskell_binary_impl = "haskell_binary_impl",
_haskell_import_impl = "haskell_import_impl",
_haskell_library_impl = "haskell_library_impl",
_haskell_test_impl = "haskell_test_impl",
_haskell_toolchain_library_impl = "haskell_toolchain_library_impl",
Expand Down Expand Up @@ -279,6 +280,29 @@ not built by default, but can be built on request. It works the same way as
for `haskell_binary`.
"""

haskell_import = rule(
_haskell_import_impl,
attrs = {
"id": attr.string(),
"version": attr.string(),
"deps": attr.label_list(),
"static_libraries": attr.label_list(allow_files = [".a"]),
"shared_libraries": attr.label_list(allow_files = [".dll", ".dylib", ".so"]),
"static_profiling_libraries": attr.label_list(allow_files = ["_p.a"]),
"linkopts": attr.string_list(),
"hdrs": attr.label_list(allow_files = True),
"includes": attr.string_list(),
"_version_macros": attr.label(
executable = True,
cfg = "host",
default = Label("@io_tweag_rules_haskell//haskell:version_macros"),
),
"_cc_toolchain": attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
),
},
)

haskell_toolchain_library = rule(
_haskell_toolchain_library_impl,
attrs = dict(
Expand All @@ -290,6 +314,10 @@ haskell_toolchain_library = rule(
cfg = "host",
default = Label("@io_tweag_rules_haskell//haskell:version_macros"),
),
# XXX We'll no longer need this once HaskellImportHack is removed.
_cc_toolchain = attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
),
),
toolchains = [
"@io_tweag_rules_haskell//haskell:toolchain",
Expand Down
5 changes: 3 additions & 2 deletions haskell/lint.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ load(
"HaskellInfo",
"HaskellLibraryInfo",
"HaskellLintInfo",
"HaskellPrebuiltPackageInfo",
)
load(":private/context.bzl", "haskell_context", "render_env")
load(":private/packages.bzl", "expose_packages", "pkg_info_to_compile_flags")
Expand All @@ -30,7 +31,7 @@ def _haskell_lint_rule_impl(ctx):
def _haskell_lint_aspect_impl(target, ctx):
hs = haskell_context(ctx, ctx.rule.attr)

if HaskellInfo not in target:
if HaskellInfo not in target or HaskellPrebuiltPackageInfo in target:
return []

hs_info = target[HaskellInfo]
Expand Down Expand Up @@ -58,7 +59,7 @@ def _haskell_lint_aspect_impl(target, ctx):
use_direct = False,
use_my_pkg_id = None,
custom_package_databases = None,
version = ctx.rule.attr.version,
version = getattr(ctx.rule.attr, "version", None),
)))

sources = set.to_list(hs_info.source_files)
Expand Down
Loading

0 comments on commit a552896

Please sign in to comment.