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

Darwin M1 Support #13401

Merged
merged 24 commits into from
Apr 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1eabe95
Update rules_nixpkgs and rules_sh
aherrmann Mar 17, 2022
86c917f
Patch rules_nixpkgs to detect ARM M1
aherrmann Mar 17, 2022
81c7a8a
Patch rules_haskell for ARM M1 compatibility
aherrmann Mar 17, 2022
e1296bc
Detect Darwin M1 in os_info.bzl
aherrmann Mar 17, 2022
63cf7ce
Use the new rules_nixpkgs host platform
aherrmann Mar 17, 2022
fdeb36a
Import the Go toolchain from rules_nixpkgs
aherrmann Mar 17, 2022
e24d4bb
Update nodejs to version 16
aherrmann Mar 17, 2022
c3ed752
Disable Haddock on lsp-types
aherrmann Mar 17, 2022
f1be146
Disable create-daml-app tests on MacOS M1
aherrmann Mar 17, 2022
b10612b
Resign binaries after patching in package-app
aherrmann Mar 17, 2022
68b11f2
Use GHC with LLVM on MacOS M1
aherrmann Mar 17, 2022
fb3ecdc
Update the CC toolchain for MacOS M1 compatibility
aherrmann Mar 17, 2022
9640cc6
Link libc++ in fat_cc_library on MacOS
aherrmann Mar 17, 2022
f939e3c
Build on native ARM M1 instead of Rosetta
aherrmann Mar 17, 2022
15ecb85
Drop unused ghcLLVMWrapper
aherrmann Mar 17, 2022
5539f75
Select ghcWithLLVM within Nix
aherrmann Mar 17, 2022
c0625b4
fmt
aherrmann Mar 17, 2022
3da08a8
Update Node version in compatibility
aherrmann Mar 24, 2022
bd053fd
Expose node in PATH in create-daml-app test
aherrmann Mar 24, 2022
2643e6a
Skip create-daml-app compat tests pre 2.0.0
aherrmann Mar 24, 2022
c7f67c8
Revert "Skip create-daml-app compat tests pre 2.0.0"
aherrmann Mar 24, 2022
7b7960f
Revert "Expose node in PATH in create-daml-app test"
aherrmann Mar 24, 2022
9161060
Revert "Update Node version in compatibility"
aherrmann Mar 24, 2022
afcce40
Keep using NodeJS 14 for the compatibility tests
aherrmann Mar 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ build:linux --action_env=LOCALE_ARCHIVE
build:windows --action_env=JAVA_HOME

# Tell bazel to use the nixpkgs Haskell toolchain on Linux and Darwin
build:linux --host_platform=@rules_haskell//haskell/platforms:linux_x86_64_nixpkgs
build:darwin --host_platform=@rules_haskell//haskell/platforms:darwin_x86_64_nixpkgs
build:linux --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host
build:darwin --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host
# and GHC's gcc on Windows
build:windows --crosstool_top=@rules_haskell_ghc_windows_amd64//:cc_toolchain

Expand Down
40 changes: 10 additions & 30 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -589,38 +589,17 @@ nixpkgs_java_configure(
) if not is_windows else None

# rules_go used here to compile a wrapper around the protoc-gen-scala plugin
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
load("@io_tweag_rules_nixpkgs//nixpkgs:toolchains/go.bzl", "nixpkgs_go_configure")

nixpkgs_package(
name = "go_nix",
attribute_path = "go",
build_file_content = """
filegroup(
name = "sdk",
srcs = glob(["share/go/**"]),
visibility = ["//visibility:public"],
)
""",
nix_file = "//nix:bazel.nix",
nixpkgs_go_configure(
nix_file = "//nix:bazel-go-toolchain.nix",
nix_file_deps = common_nix_file_deps,
repositories = dev_env_nix_repos,
)

# A repository that generates the Go SDK imports, see
# ./bazel_tools/go_sdk/README.md
local_repository(
name = "go_sdk_repo",
path = "bazel_tools/go_sdk",
)
) if not is_windows else None

load("@io_bazel_rules_go//go:deps.bzl", "go_wrap_sdk")
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains")

# On Nix platforms we use the Nix provided Go SDK, on Windows we let Bazel pull
# an upstream one.
go_wrap_sdk(
name = "go_sdk",
root_file = "@go_nix//:share/go/ROOT",
) if not is_windows else None
go_register_toolchains(version = "1.16.9") if is_windows else None

# gazelle:repo bazel_gazelle
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
Expand All @@ -629,9 +608,9 @@ load("//:go_deps.bzl", "go_deps")
# gazelle:repository_macro go_deps.bzl%go_deps
go_deps()

go_rules_dependencies()
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies")

go_register_toolchains() if not is_windows else go_register_toolchains(version = "1.16.9")
go_rules_dependencies()

gazelle_dependencies()

Expand Down Expand Up @@ -721,12 +700,13 @@ dev_env_tool(
load("@build_bazel_rules_nodejs//:index.bzl", "node_repositories", "yarn_install")

node_repositories(
package_json = ["//:package.json"],
# Using `dev_env_tool` introduces an additional layer of symlink
# indirection. Bazel doesn't track dependencies through symbolic links.
# Occasionally, this can cause build failures on CI if a build is not
# invalidated despite a change of an original source. To avoid such issues
# we use the `nixpkgs_package` directly.
node_version = "16.13.0",
package_json = ["//:package.json"],
vendored_node = "@nodejs_dev_env" if is_windows else "@node_nix",
)

Expand Down
1 change: 1 addition & 0 deletions bazel-haskell-deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ haskell_cabal_library(
version = packages["lsp-types"].version,
srcs = glob(["**"]),
deps = packages["lsp-types"].deps,
haddock = False,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do? Is this related to adding M1 support?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It disables building haddocks for that package. We already disable it for others. The haddocks build failed on M1, details are in the commit message.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks for the explanation.

visibility = ["//visibility:public"],
)""",
patch_args = ["-p1"],
Expand Down
2 changes: 1 addition & 1 deletion bazel_tools/fat_cc_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def _fat_cc_library_impl(ctx):
[f.path for f in static_libs] +
ctx.attr.no_whole_archive_flag +
# Some libs seems to depend on libstdc++ implicitely
["-lstdc++"] +
(["-lc++", "-lc++abi"] if is_darwin else ["-lstdc++"]) +
(["-framework", "CoreFoundation"] if is_darwin else []) +
# On Windows we have some extra deps.
(["-lws2_32"] if is_windows else []),
Expand Down
197 changes: 197 additions & 0 deletions bazel_tools/haskell-arm-m1.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
diff --git a/haskell/cabal.bzl b/haskell/cabal.bzl
index 6be79b0d..1e324ec5 100644
--- a/haskell/cabal.bzl
+++ b/haskell/cabal.bzl
@@ -171,10 +171,11 @@ def _cabal_toolchain_info(hs, cc, workspace_name, runghc):
runghc = runghc.path,
ar = ar,
cc = cc.tools.cc,
+ ld = cc.tools.ld,
strip = cc.tools.strip,
is_windows = hs.toolchain.is_windows,
workspace = workspace_name,
- ghc_cc_args = ghc_cc_program_args(hs, "$CC"),
+ ghc_cc_args = ghc_cc_program_args(hs, "$CC", "$LD"),
)

def _prepare_cabal_inputs(
diff --git a/haskell/cc.bzl b/haskell/cc.bzl
index 3726133c..d59f84f7 100644
--- a/haskell/cc.bzl
+++ b/haskell/cc.bzl
@@ -186,11 +186,12 @@ def cc_interop_info(ctx, override_cc_toolchain = None):
]).linking_context.linker_inputs.to_list() for lib in li.libraries],
)

-def ghc_cc_program_args(hs, cc):
+def ghc_cc_program_args(hs, cc, ld):
"""Returns the -pgm* flags required to override cc.

Args:
cc: string, path to the C compiler (cc_wrapper).
+ ld: string, path to the linker (ld).

Returns:
list of string, GHC arguments.
@@ -220,4 +221,11 @@ def ghc_cc_program_args(hs, cc):
]
if hs.toolchain.numeric_version >= [8, 10, 3]:
args.append("-pgmc-supports-no-pie")
+ if hs.toolchain.numeric_version >= [9, 0, 1]:
+ args.extend([
+ "-pgmlm",
+ ld,
+ "-optlm",
+ "-r",
+ ])
return args
diff --git a/haskell/doctest.bzl b/haskell/doctest.bzl
index 1cd3f675..f7a2200a 100644
--- a/haskell/doctest.bzl
+++ b/haskell/doctest.bzl
@@ -98,7 +98,7 @@ def _haskell_doctest_single(target, ctx):
ctx,
override_cc_toolchain = hs.tools_config.maybe_exec_cc_toolchain,
)
- args.add_all(ghc_cc_program_args(hs, cc.tools.cc))
+ args.add_all(ghc_cc_program_args(hs, cc.tools.cc, cc.tools.ld))

doctest_log = ctx.actions.declare_file(
"doctest-log-" + ctx.label.name + "-" + target.label.name,
diff --git a/haskell/nixpkgs.bzl b/haskell/nixpkgs.bzl
index 7ccead78..6692fe6b 100644
--- a/haskell/nixpkgs.bzl
+++ b/haskell/nixpkgs.bzl
@@ -1,5 +1,6 @@
"""Workspace rules (Nixpkgs)"""

+load("@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value")
load(
"@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl",
"nixpkgs_package",
@@ -145,15 +146,21 @@ def _ghc_nixpkgs_toolchain_impl(repository_ctx):
# platform. But they are important to state because Bazel
# toolchain resolution prefers other toolchains with more specific
# constraints otherwise.
- if repository_ctx.attr.target_constraints == [] and repository_ctx.attr.exec_constraints == []:
- target_constraints = ["@platforms//cpu:x86_64"]
- if repository_ctx.os.name == "linux":
- target_constraints.append("@platforms//os:linux")
- elif repository_ctx.os.name == "mac os x":
- target_constraints.append("@platforms//os:osx")
- exec_constraints = list(target_constraints)
+ cpu_value = get_cpu_value(repository_ctx)
+ cpu = {
+ "darwin": "@platforms//cpu:x86_64",
+ "darwin_arm64": "@platforms//cpu:arm64",
+ }.get(cpu_value, "@platforms//cpu:x86_64")
+ os = {
+ "darwin": "@platforms//os:osx",
+ "darwin_arm64": "@platforms//os:osx",
+ }.get(cpu_value, "@platforms//os:linux")
+
+ if not repository_ctx.attr.target_constraints and not repository_ctx.attr.exec_constraints:
+ target_constraints = [cpu, os]
+ exec_constraints = target_constraints
else:
- target_constraints = repository_ctx.attr.target_constraints
+ target_constraints = list(repository_ctx.attr.target_constraints)
exec_constraints = list(repository_ctx.attr.exec_constraints)

exec_constraints.append("@io_tweag_rules_nixpkgs//nixpkgs/constraints:support_nix")
diff --git a/haskell/private/cabal_wrapper.py b/haskell/private/cabal_wrapper.py
index 1ba677b3..b14135f9 100755
--- a/haskell/private/cabal_wrapper.py
+++ b/haskell/private/cabal_wrapper.py
@@ -129,6 +129,7 @@ path_args = json_args["path_args"]

ar = find_exe(toolchain_info["ar"])
cc = find_exe(toolchain_info["cc"])
+ld = find_exe(toolchain_info["ld"])
strip = find_exe(toolchain_info["strip"])

def recache_db():
@@ -261,10 +262,14 @@ with mkdtemp(distdir_prefix()) as distdir:
"--with-hsc2hs=" + hsc2hs,
"--with-ar=" + ar,
"--with-gcc=" + cc,
+ "--with-ld=" + ld,
"--with-strip=" + strip,
"--enable-deterministic", \
] +
- [ "--ghc-option=" + flag.replace("$CC", cc) for flag in toolchain_info["ghc_cc_args"] ] +
+ [ "--ghc-option=" + flag.replace("$CC", cc).replace("$LD", ld) for flag in toolchain_info["ghc_cc_args"] ] +
+ [ "--hsc2hs-option=-c" + cc,
+ "--hsc2hs-option=-l" + cc,
+ ] +
enable_relocatable_flags + \
[ \
# Make `--builddir` a relative path. Using an absolute path would
diff --git a/haskell/private/cc_wrapper.py.tpl b/haskell/private/cc_wrapper.py.tpl
index 311c0f96..9249f30b 100644
--- a/haskell/private/cc_wrapper.py.tpl
+++ b/haskell/private/cc_wrapper.py.tpl
@@ -84,6 +84,7 @@ CC = os.environ.get("CC_WRAPPER_CC_PATH", "{:cc:}")
PLATFORM = os.environ.get("CC_WRAPPER_PLATFORM", "{:platform:}")
CPU = os.environ.get("CC_WRAPPER_CPU", "{:cpu:}")
INSTALL_NAME_TOOL = "/usr/bin/install_name_tool"
+CODESIGN = "/usr/bin/codesign"
OTOOL = "/usr/bin/otool"


@@ -938,6 +939,14 @@ def darwin_rewrite_load_commands(rewrites, output):
args.extend(["-change", old, os.path.join("@rpath", new)])
if args:
subprocess.check_call([INSTALL_NAME_TOOL] + args + [output])
+ # Resign the binary after patching it.
+ # This is necessary on MacOS Monterey on M1.
+ # The moving back and forth is necessary because the OS caches the signature.
+ # See this note from nixpkgs for reference:
+ # https://github.com/NixOS/nixpkgs/blob/5855ff74f511423e3e2646248598b3ffff229223/pkgs/os-specific/darwin/signing-utils/utils.sh#L1-L6
+ os.rename(output, f"{output}.resign")
+ subprocess.check_call([CODESIGN] + ["-f", "-s", "-"] + [f"{output}.resign"])
+ os.rename(f"{output}.resign", output)


# --------------------------------------------------------------------
diff --git a/haskell/repl.bzl b/haskell/repl.bzl
index 6cc44499..0833ec92 100644
--- a/haskell/repl.bzl
+++ b/haskell/repl.bzl
@@ -396,7 +396,12 @@ def _create_repl(hs, cc, posix, ctx, repl_info, output):
"$RULES_HASKELL_EXEC_ROOT",
hs.toolchain.cc_wrapper.executable.path,
)
- args.extend(['"{}"'.format(arg) for arg in ghc_cc_program_args(hs, cc_path)])
+ ld_path = paths.join(
+ "$RULES_HASKELL_EXEC_ROOT",
+ cc.ld_executable,
+ )
+ args.extend(['"{}"'.format(arg) for arg in ghc_cc_program_args(hs, cc_path, ld_path)])
+

# Load source files
# Force loading by source with `:add *...`.
@@ -518,7 +523,8 @@ def _create_hie_bios(hs, cc, posix, ctx, repl_info, path_prefix):
path_prefix = paths.join("", *path_prefix)
args, inputs = _compiler_flags_and_inputs(hs, cc, repl_info, path_prefix = path_prefix, static = True)
cc_path = paths.join(path_prefix, hs.toolchain.cc_wrapper.executable.path)
- args.extend(ghc_cc_program_args(hs, cc_path))
+ ld_path = paths.join(path_prefix, cc.ld_executable)
+ args.extend(ghc_cc_program_args(hs, cc_path, ld_path))
args.extend(hs.toolchain.ghcopts)
args.extend(repl_info.load_info.compiler_flags)

diff --git a/haskell/toolchain.bzl b/haskell/toolchain.bzl
index 2cecc0b8..74f72163 100644
--- a/haskell/toolchain.bzl
+++ b/haskell/toolchain.bzl
@@ -46,7 +46,7 @@ def _run_ghc(hs, cc, inputs, outputs, mnemonic, arguments, env, params_file = No

# XXX: We should also tether Bazel's CC toolchain to GHC's, so that we can properly mix Bazel-compiled
# C libraries with Haskell targets.
- args.add_all(ghc_cc_program_args(hs, cc.tools.cc))
+ args.add_all(ghc_cc_program_args(hs, cc.tools.cc, cc.tools.ld))

compile_flags_file = hs.actions.declare_file("compile_flags_%s_%s_%s" % (hs.name, extra_name, mnemonic))
extra_args_file = hs.actions.declare_file("extra_args_%s_%s_%s" % (hs.name, extra_name, mnemonic))
4 changes: 2 additions & 2 deletions bazel_tools/nixpkgs-disable-http2.patch
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
diff --git a/nixpkgs/nixpkgs.bzl b/nixpkgs/nixpkgs.bzl
index 666948e..8d99441 100644
index 16fe59c..d590d44 100644
--- a/nixpkgs/nixpkgs.bzl
+++ b/nixpkgs/nixpkgs.bzl
@@ -116,7 +116,7 @@ def _nixpkgs_package_impl(repository_ctx):
@@ -136,7 +136,7 @@ def _nixpkgs_package_impl(repository_ctx):
"The NIX_PATH environment variable is not inherited."
)

Expand Down
11 changes: 10 additions & 1 deletion bazel_tools/os_info.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,23 @@ load("@bazel_tools//tools/cpp:lib_cc_configure.bzl", "get_cpu_value")

_os_info_bzl_template = """
cpu_value = "{CPU_VALUE}"
is_darwin = cpu_value == "darwin"
is_darwin = cpu_value == "darwin" or cpu_value == "darwin_arm64"
is_darwin_arm64 = cpu_value == "darwin_arm64"
is_linux = cpu_value == "k8"
is_windows = cpu_value == "x64_windows"
os_name = "macos" if is_darwin else "linux" if is_linux else "windows"
"""

def _os_info_impl(repository_ctx):
cpu = get_cpu_value(repository_ctx)
known_cpu_values = [
"darwin",
"darwin_arm64",
"k8",
"x64_windows",
]
if cpu not in known_cpu_values:
fail("Unknown OS type {}, expected one of {}".format(cpu, ", ".join(known_cpu_values)))
os_info_substitutions = {
"CPU_VALUE": cpu,
}
Expand Down
8 changes: 8 additions & 0 deletions bazel_tools/packaging/package-app.sh
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,14 @@ elif [[ "$(uname -s)" == "Darwin" ]]; then
fi
fi
done

# Resign the binary on MacOS. Requires moving the file back and forth
# because the OS caches the signatore. Refer to the following note in
# nixpkgs for details:
# https://github.com/NixOS/nixpkgs/blob/5855ff74f511423e3e2646248598b3ffff229223/pkgs/os-specific/darwin/signing-utils/utils.sh#L1-L6
mv "$from_copied" "$from_copied.resign"
/usr/bin/codesign -f -s - "$from_copied.resign"
mv "$from_copied.resign" "$from_copied"
}
# Set the dynamic library load path to the relative lib/ directory.
/usr/bin/install_name_tool -add_rpath "@loader_path/lib" $WORKDIR/$NAME/$NAME
Expand Down