Improve Haskell language support
Removes the need to call setup_ghc_compilers in every Haskell language formula, by automatically calling fails_with. Adds a :home option to the cabal_sandbox method. This option allows a specific temporary HOME to be used instead of the current working directory, and in turn allows a single Cabal package database to be reused between multiple calls to this method. Avoids updating the Cabal package database more than once if cabal_sandbox is called multiple times. Removes the need to call cabal_clean_lib whenever cabal_sandbox is called, by automatically cleaning the lib directory. Adds a :keep_lib option to the cabal_sandbox method. This option allows opting out of the automatic cleaning. Ensures build products are always removed from the current working directory. Removes a workaround for versions of cabal-install older than 1.20.0.0. Adds a cabal_sandbox_add_source method. Adds a :using option to the install_cabal_package method. This option allows specifying the Haskell language tools that are required to install a particular formula, and in turn allows formulae to be simplified by replacing calls to multiple methods with a single call to this method. Allows customizing the call to install_cabal_package by giving a block. Removes empty method shells. Closes Homebrew/homebrew#47293. Signed-off-by: Mike McQuaid <mike@mikemcquaid.com>
This commit is contained in:
parent
0f86677ffc
commit
68361be36c
@ -1,79 +1,77 @@
|
|||||||
module Language
|
module Language
|
||||||
module Haskell
|
module Haskell
|
||||||
# module for formulae using cabal-install as build tool
|
|
||||||
module Cabal
|
module Cabal
|
||||||
module ClassMethods
|
def self.included(base)
|
||||||
def setup_ghc_compilers
|
# use llvm-gcc on Lion or below, as when building GHC)
|
||||||
# Use llvm-gcc on Lion or below (same compiler used when building GHC).
|
|
||||||
fails_with(:clang) if MacOS.version <= :lion
|
fails_with(:clang) if MacOS.version <= :lion
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def self.included(base)
|
def cabal_sandbox(options = {})
|
||||||
base.extend ClassMethods
|
|
||||||
end
|
|
||||||
|
|
||||||
def cabal_sandbox
|
|
||||||
pwd = Pathname.pwd
|
pwd = Pathname.pwd
|
||||||
# force cabal to put its stuff here instead of the home directory by
|
home = options[:home] || pwd
|
||||||
# pretending the home is here. This also avoid to deal with many options
|
|
||||||
# to configure cabal. Note this is also useful with cabal sandbox to
|
|
||||||
# avoid touching ~/.cabal
|
|
||||||
home = ENV["HOME"]
|
|
||||||
ENV["HOME"] = pwd
|
|
||||||
|
|
||||||
# use cabal's sandbox feature if available
|
# pretend HOME is elsewhere, so that ~/.cabal is kept as untouched
|
||||||
cabal_version = `cabal --version`[/[0-9.]+/].split(".").collect(&:to_i)
|
# as possible (except for ~/.cabal/setup-exe-cache)
|
||||||
if (cabal_version <=> [1, 20]) > -1
|
# https://github.com/haskell/cabal/issues/1234
|
||||||
system "cabal", "sandbox", "init"
|
saved_home = ENV["HOME"]
|
||||||
cabal_sandbox_bin = pwd/".cabal-sandbox/bin"
|
|
||||||
else
|
|
||||||
# no or broken sandbox feature - just use the HOME trick
|
|
||||||
cabal_sandbox_bin = pwd/".cabal/bin"
|
|
||||||
end
|
|
||||||
# cabal may build useful tools that should be found in the PATH
|
|
||||||
mkdir_p cabal_sandbox_bin
|
|
||||||
path = ENV["PATH"]
|
|
||||||
ENV.prepend_path "PATH", cabal_sandbox_bin
|
|
||||||
# update cabal package database
|
|
||||||
system "cabal", "update"
|
|
||||||
yield
|
|
||||||
# restore the environment
|
|
||||||
if (cabal_version <=> [1, 20]) > -1
|
|
||||||
system "cabal", "sandbox", "delete"
|
|
||||||
end
|
|
||||||
ENV["HOME"] = home
|
ENV["HOME"] = home
|
||||||
ENV["PATH"] = path
|
|
||||||
|
system "cabal", "sandbox", "init"
|
||||||
|
cabal_sandbox_bin = pwd/".cabal-sandbox"/"bin"
|
||||||
|
mkdir_p cabal_sandbox_bin
|
||||||
|
|
||||||
|
# make available any tools that will be installed in the sandbox
|
||||||
|
saved_path = ENV["PATH"]
|
||||||
|
ENV.prepend_path "PATH", cabal_sandbox_bin
|
||||||
|
|
||||||
|
# avoid updating the cabal package database more than once
|
||||||
|
system "cabal", "update" unless (home/".cabal"/"packages").exist?
|
||||||
|
|
||||||
|
yield
|
||||||
|
|
||||||
|
# remove the sandbox and all build products
|
||||||
|
rm_rf [".cabal-sandbox", "cabal.sandbox.config", "dist"]
|
||||||
|
|
||||||
|
# avoid installing any Haskell libraries, as a matter of policy
|
||||||
|
rm_rf lib unless options[:keep_lib]
|
||||||
|
|
||||||
|
# restore the environment
|
||||||
|
ENV["HOME"] = saved_home
|
||||||
|
ENV["PATH"] = saved_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def cabal_install(*opts)
|
def cabal_sandbox_add_source(*args)
|
||||||
system "cabal", "install", "--jobs=#{ENV.make_jobs}", *opts
|
system "cabal", "sandbox", "add-source", *args
|
||||||
end
|
end
|
||||||
|
|
||||||
# install the tools passed in parameter and remove the packages that where
|
def cabal_install(*args)
|
||||||
# used so they won't be in the way of the dependency solver for the main
|
system "cabal", "install", "--jobs=#{ENV.make_jobs}", *args
|
||||||
# package. The tools are installed sequentially in order to make possible
|
|
||||||
# to install several tools that depends on each other
|
|
||||||
def cabal_install_tools(*opts)
|
|
||||||
opts.each { |t| cabal_install t }
|
|
||||||
rm_rf Dir[".cabal*/*packages.conf.d/"]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# remove the development files from the lib directory. cabal-install should
|
def cabal_install_tools(*tools)
|
||||||
# be used instead to install haskell packages
|
# install tools sequentially, as some tools can depend on other tools
|
||||||
def cabal_clean_lib
|
tools.each { |tool| cabal_install tool }
|
||||||
# a better approach may be needed here
|
|
||||||
rm_rf lib
|
# unregister packages installed as dependencies for the tools, so
|
||||||
|
# that they can't cause dependency conflicts for the main package
|
||||||
|
rm_rf Dir[".cabal-sandbox/*packages.conf.d/"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_cabal_package(args = [])
|
def install_cabal_package(*args)
|
||||||
|
options = if args[-1].kind_of?(Hash) then args.pop else {} end
|
||||||
|
|
||||||
cabal_sandbox do
|
cabal_sandbox do
|
||||||
# the dependencies are built first and installed locally, and only the
|
cabal_install_tools *options[:using] if options[:using]
|
||||||
# current package is actually installed in the destination dir
|
|
||||||
|
# install dependencies in the sandbox
|
||||||
cabal_install "--only-dependencies", *args
|
cabal_install "--only-dependencies", *args
|
||||||
|
|
||||||
|
# install the main package in the destination dir
|
||||||
cabal_install "--prefix=#{prefix}", *args
|
cabal_install "--prefix=#{prefix}", *args
|
||||||
|
|
||||||
|
yield if block_given?
|
||||||
end
|
end
|
||||||
cabal_clean_lib
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user