diff --git a/haskell/cabal.bzl b/haskell/cabal.bzl index d25b1368c..6511d29fb 100644 --- a/haskell/cabal.bzl +++ b/haskell/cabal.bzl @@ -140,7 +140,8 @@ def _prepare_cabal_inputs( package_database, verbose, transitive_haddocks, - dynamic_binary = None): + is_library = False, + dynamic_file = None): """Compute Cabal wrapper, arguments, inputs.""" with_profiling = is_profiling_enabled(hs) @@ -212,16 +213,19 @@ def _prepare_cabal_inputs( for arg in ["-package-db", "./" + _dirname(package_db)] ], join_with = " ", format_each = "--ghc-arg=%s", omit_if_empty = False) args.add("--flags=" + " ".join(flags)) - if not hs.toolchain.is_darwin and not hs.toolchain.is_windows: + if dynamic_file: # See Note [No PIE when linking] in haskell/private/actions/link.bzl - args.add("--ghc-option=-optl-no-pie") + if not (hs.toolchain.is_darwin or hs.toolchain.is_windows): + version = [int(x) for x in hs.toolchain.version.split(".")] + if version < [8, 10] or not is_library: + args.add("--ghc-option=-optl-no-pie") args.add_all(hs.toolchain.cabalopts) args.add_all(cabalopts) - if dynamic_binary: + if dynamic_file: args.add_all( [ "--ghc-option=-optl-Wl,-rpath," + create_rpath_entry( - binary = dynamic_binary, + binary = dynamic_file, dependency = lib, keep_filename = False, prefix = relative_rpath_prefix(hs.toolchain.is_darwin), @@ -426,7 +430,8 @@ def _haskell_cabal_library_impl(ctx): cabal_wrapper = ctx.executable._cabal_wrapper, package_database = package_database, verbose = ctx.attr.verbose, - dynamic_binary = dynamic_library, + is_library = True, + dynamic_file = dynamic_library, transitive_haddocks = _gather_transitive_haddocks(ctx.attr.deps), ) outputs = [ @@ -702,7 +707,7 @@ def _haskell_cabal_binary_impl(ctx): cabal_wrapper = ctx.executable._cabal_wrapper, package_database = package_database, verbose = ctx.attr.verbose, - dynamic_binary = binary, + dynamic_file = binary, transitive_haddocks = _gather_transitive_haddocks(ctx.attr.deps), ) ctx.actions.run( diff --git a/haskell/private/actions/compile.bzl b/haskell/private/actions/compile.bzl index cb5b6ece3..90c0cc909 100644 --- a/haskell/private/actions/compile.bzl +++ b/haskell/private/actions/compile.bzl @@ -475,9 +475,12 @@ def compile_library( c = _compilation_defaults(hs, cc, java, posix, dep_info, plugin_dep_info, srcs, import_dir_map, extra_srcs, user_compile_flags, with_profiling, my_pkg_id = my_pkg_id, version = my_pkg_id.version, plugins = plugins, preprocessors = preprocessors) if with_shared: c.args.add("-dynamic-too") + + # See Note [No PIE when linking] in haskell/private/actions/link.bzl if not hs.toolchain.is_darwin and not hs.toolchain.is_windows: - # See Note [No PIE when linking] in haskell/private/actions/link.bzl - c.args.add("-optl-no-pie") + version = [int(x) for x in hs.toolchain.version.split(".")] + if version < [8, 10]: + c.args.add("-optl-no-pie") coverage_data = [] if hs.coverage_enabled: diff --git a/haskell/private/actions/link.bzl b/haskell/private/actions/link.bzl index 0e2f392d8..14dc9e8b2 100644 --- a/haskell/private/actions/link.bzl +++ b/haskell/private/actions/link.bzl @@ -213,7 +213,10 @@ def link_binary( # on this setting GHC would then automatically set `-no-pie`. However, # rules_haskell uses GHC's `-pgmc` flag to point GHC to the CC toolchain's C # compiler. This disables the flags configured in the `setting` file. Instead, -# we have to pass `-no-pie` explicitly. +# we have to pass `-no-pie` explicitly when linking binaries. +# +# In GHC < 8.10, we must always pass -no-pie. In newer compilers, we +# must take care to only pass -no-pie when compiling libraries. # # Ideally, we would determine whether the CC toolchain's C compiler supports # `-no-pie` before setting it. Unfortunately, this is complicated by the fact