Skip to content

Commit

Permalink
ghc: Update to 8.6.5 and major Portfile refactoring
Browse files Browse the repository at this point in the history
* Download x86_64-apple-darwin version from haskell.org
* Include gpg signature verification
* Bootstrap from source
* Eliminate old patch files, compiler incompatibilities
  • Loading branch information
essandess committed Jul 28, 2019
1 parent 67afb23 commit c862681
Show file tree
Hide file tree
Showing 7 changed files with 286 additions and 190 deletions.
342 changes: 216 additions & 126 deletions lang/ghc/Portfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4

PortSystem 1.0
PortGroup compiler_blacklist_versions 1.0

name ghc
# Do not update GHC separate from Haskell Platform.
# When updating GHC, make sure to revbump all Haskell ports.
# Also make sure to update the version in the Haskell PortGroup.
version 7.8.3
revision 6
version 8.6.5
categories lang haskell
maintainers {cal @neverpanic} openmaintainer
maintainers {cal @neverpanic} {ieee.org:s.t.smith @essandess} openmaintainer
license BSD
platforms darwin

Expand All @@ -29,144 +24,239 @@ long_description \
and a space and time profiler.

homepage http://haskell.org/${name}
master_sites ${homepage}/dist/${version}/
distname ${name}-${version}-src
worksrcdir ${name}-${version}

use_bzip2 yes
variant bootstrap \
description {Bootstrap a build of ghc.} {}

distfiles ${name}-${version}-src${extract.suffix} \
${name}-${version}-testsuite${extract.suffix}
# make bootstrapping the default when/if it works
default_variants +bootstrap

checksums ghc-7.8.3-src.tar.bz2 \
rmd160 464d31d924a8c1e23e94b3cae810c4e41dad4b75 \
sha256 2358826f8424bf571dcc313bd882422fe108a340d6e37db4339ff6d5d6ac3f37 \
ghc-7.8.3-testsuite.tar.bz2 \
rmd160 abc39b71e2f3926b80c681428c447f39599d7d83 \
sha256 9cfef874adf5b895701ae52e507f07049a64246af120ac15200e7bf612521122
# https://www.haskell.org/ghcup/
# https://gitlab.haskell.org/haskell/ghcup/blob/master/README.md#manual-install
use_xz yes
master_sites https://downloads.haskell.org/~${name}/${version}
distfiles ${distname}-x86_64-apple-darwin${extract.suffix} \
${distname}-testsuite${extract.suffix}
checksums ${distname}-x86_64-apple-darwin${extract.suffix} \
rmd160 618664b03640f58ebe28999c1c3bd3fc56c8ff7c \
sha256 dfc1bdb1d303a87a8552aa17f5b080e61351f2823c2b99071ec23d0837422169 \
size 159042284 \
${distname}-testsuite${extract.suffix} \
rmd160 9e4cb087bc8163feab7793f835916bdfd277868b \
sha256 21391cb63a8a6b327f6c9519217a3dad39493e72c48967008ae35af142ca895f \
size 1910060

depends_build port:ghc-bootstrap \
port:libxslt
if {[variant_isset "bootstrap"]} {
distfiles-append \
${distname}-src${extract.suffix}
checksums-append \
${distname}-src${extract.suffix} \
rmd160 2640736ab93348a6f9550d914d811c0e62b77e50 \
sha256 4d4aa1e96f4001b934ac6193ab09af5d6172f41f5a5d39d8e43393b9aafee361 \
size 19092168

depends_lib port:gmp \
port:ncurses \
port:libiconv \
port:llvm-3.5 \
port:libffi
# use these to specify python versions, python3 required
set python3_version 3.7
set python3_version_nickname \
[join [lrange [split ${python3_version} .] 0 1] {}]

patchfiles patch-configure-workaround-bsdsed-incompatibility.diff \
patch-configure-disable-docs.diff \
patch-unix_lib_osx_sandbox_compatibility.diff

if { ${os.platform} eq "darwin" && ${os.major} >= 16 } {
patchfiles-append patch-sierra-compatibility.diff
depends_build-append \
port:python${python3_version_nickname} \
port:texlive \
port:texlive-fonts-extra \
port:texlive-fonts-recommended
}

use_parallel_build \
no

livecheck.type none
test.run yes

# Compilation fails with older versions of clang. clang-4.1 from Xcode 4.5 is
# too old, clang-5.1 from from Xcode 5.1 works. I do not have any data points in
# between, so I'm blacklisting everything lower than 5.1. If you want to test
# the versions in between, be my guest.
# Also avoid LLVM GCC 4.2 and GCC 4.2, which are before MacPorts' clang 3.4 in
# the fallback list on some systems.
# NOTE that it is actually the C compiler used in ghc-bootstrap that is
# relevant here. This code block is duplicated in this port to avoid
# inconsistencies.
compiler.blacklist-append \
llvm-gcc-4.2 \
gcc-4.2 \
{clang < 503.0.38} \
macports-clang-3.3

# ghc needs a build and runtime dependency on the compiler used to build it
# same is also set in ghc-bootstrap. clang-4.0 works, is needed on older systems anyway
# also /usr/bin/clang does not work on 10.11, so override it there
if { ${os.platform} eq "darwin" && ( ${os.major} < 13 || ${os.major} == 15 ) } {
compiler.whitelist macports-clang-8.0
depends_run-append port:clang-8.0
supported_archs x86_64

set verify_gpg_signature_flag \
false

if {${verify_gpg_signature_flag} == "true"} {
distfiles-append \
${distname}-x86_64-apple-darwin${extract.suffix}.sig \
${distname}-testsuite${extract.suffix}.sig
checksums-append \
${distname}-x86_64-apple-darwin${extract.suffix}.sig \
rmd160 08ab969c5f1aeb45b925666933293c35afaa12fa \
sha256 19e5eb9fa7a39dcb3741fcf6f95d18fbb76ba5b4bbf3a891559b2a0bfb2716d5 \
size 586 \
${distname}-testsuite${extract.suffix}.sig \
rmd160 eb3614a266e8250e93564f87f46d83f6c462118b \
sha256 e1543cbe700f9cb0c3ec5495b930b32da9a2fedd65c77b8e38ba033ad7acbb90 \
size 586
}

set bootstraproot ${prefix}/share/ghc-bootstrap
set llvmPrefix ${prefix}/libexec/llvm-3.5
configure.args --with-ghc=${bootstraproot}/bin/ghc \
--with-iconv-includes=${prefix}/include \
--with-iconv-libraries=${prefix}/lib \
--with-gmp-includes=${prefix}/include \
--with-gmp-libraries=${prefix}/lib \
--with-ffi-includes=${prefix}/lib/libffi-3.2.1/include \
--with-ffi-libraries=${prefix}/lib \
--with-system-libffi \
--with-gcc="${configure.cc}" \
--with-llc=${llvmPrefix}/bin/llc \
--with-opt=${llvmPrefix}/bin/opt

# OK so because the bootstrap binary has been prebuilt for libraries in
# /usr/lib we search these in addition to MacPorts' paths to prevent link
# errors. GHC _should_ actually compile itself in stage2 using paths from the
# command line arguments
compiler.cpath /usr/include
compiler.library_path /usr/lib

build.args VERBOSE=1
destroot.args VERBOSE=1

pre-activate {
set obsoletes [list]

# Legacy port deactivation hack added 2012-12-08, hs-platform-ghc no longer exists
lappend obsoletes hs-platform-ghc
# Legacy port deactivation hack added 2013-08-11, hs-process is provided by base
lappend obsoletes hs-process
# Legacy port deactivation hack added 2013-08-14, hs-template-haskell is provided by base
lappend obsoletes hs-template-haskell
# Legacy port deactivation hack added 2015-01-05, hs-transformers, hs-xhtml
# and hs-binary are provided by base
lappend obsoletes hs-transformers
lappend obsoletes hs-xhtml
lappend obsoletes hs-binary

foreach obsolete $obsoletes {
if {![catch {set obsolete_installed [lindex [registry_active $obsolete] 0]}]} {
# $obsolete is installed and active
# force deactivation
registry_deactivate_composite $obsolete "" [list ports_nodepcheck 1]
if {${verify_gpg_signature_flag} == "true"} {
depends_fetch-append \
port:gnupg2

proc verify_gpg_signature {gpg_homedir keyid_file signature_file test_file} {
# pre-load public key to avoid keyserver downtime issues
# https://pgp.mit.edu/pks/lookup?op=get&search=0x${gpg_keyid}
# note: tcl exec will return error if error messages not directed to /dev/null
system "/bin/sh -c 'gpg --homedir ${gpg_homedir} --import ${keyid_file} 2>/dev/null || /usr/bin/true'"
set gpg_verification [exec /bin/sh -c "if gpg --homedir ${gpg_homedir} --verify ${signature_file} ${test_file} 2>/dev/null; then echo 'VERIFIED'; else echo 'UNVERIFIED'; fi"]
if {[string trim ${gpg_verification}] != "VERIFIED"} {
ui_error "GPG signature verification failed on ${test_file} with keyid file ${keyid_file}."
exit 1
}
}

pre-extract {
# check GPG signature: https://www.haskell.org/ghc/download_ghc_8_6_5.html
set gpg_keyid 97db64ad

verify_gpg_signature \
${workpath}/.gnupg \
${filespath}/keyid-${gpg_keyid}.txt \
${distpath}/${distname}-x86_64-apple-darwin${extract.suffix}.sig \
${distpath}/${distname}-x86_64-apple-darwin${extract.suffix}

verify_gpg_signature \
${workpath}/.gnupg \
${filespath}/keyid-${gpg_keyid}.txt \
${distpath}/${distname}-testsuite${extract.suffix}.sig \
${distpath}/${distname}-testsuite${extract.suffix}
}
}

post-activate {
set libprefix "${prefix}/lib/${name}-${version}"
extract.only ${distname}-x86_64-apple-darwin${extract.suffix} \
${distname}-testsuite${extract.suffix}

compiler.cpath /usr/bin/gcc
compiler.library_path \
/usr/lib:${prefix}/lib

# Note: ghc has DESTDIR; however, specifying --prefix=${prefix} installs
# binaries into ${prefix}, not DESTDIR. Work around this by setting
# --prefix=${destroot}${prefix} and not setting DESTDIR

if {![variant_isset "bootstrap"]} {
set bootstrap_dir ${destroot}${prefix}
} else {
set bootstrap_dir ${workpath}/bootstrap

pre-configure {
xinstall -m 0755 -d ${bootstrap_dir}
}
}

# install the initial bootstrap compiler to destroot
configure.pre_args --prefix=${bootstrap_dir}

build.target install

# Note: `make install` in bootstrap build cannot use a parallel build
use_parallel_build no

# the PATH environment must provide the bootstrap path
# note: this command does not change the destroot PATH environment, so export
# PATH explicitly in the necessary system command below
build.env \
PATH=$env(PATH):${bootstrap_dir}/bin

# delete old ${prefix}/lib/ghc-${version} directories
foreach fullpath [glob -nocomplain -directory ${prefix}/lib ghc-*] {
if {$fullpath ne $libprefix} {
ui_info "Cleaning up remnant GHC library directory ${fullpath}"
catch {delete $fullpath}
set srcpath ${workpath}/src

pre-build {
if {[variant_isset "bootstrap"]} {
# test: move extracted testsuite directory to src
xinstall -m 0755 -d ${srcpath}/${distname}
move ${test.dir} ${srcpath}/${distname}/testsuite
test.dir ${srcpath}/${distname}/testsuite
}
}

post-build {
if {[variant_isset "bootstrap"]} {
# bootstrap build/destroot from ${distname}-src${extract.suffix}

use_parallel_build yes

# extract
extract.dir ${srcpath}
extract.only ${distname}-src${extract.suffix}
portextract::extract_main

# fix DejaVu texlive fonts names, e.g. "\setmonofont{DejaVu Sans Mono}"
foreach f "\
${srcpath}/${distname}/libraries/Cabal/Cabal/doc/conf.py \
${srcpath}/${distname}/docs/users_guide/conf.py \
" {
reinplace -E "s|(\{DejaVu\[\[:alnum:\]_\]*)\[\[:space:\]\]+|\\1|g" \
${f}
reinplace -E "s|(\{DejaVu\[\[:alnum:\]_\]*)\[\[:space:\]\]+|\\1|g" \
${f}
reinplace -E "s|\{(DejaVu\[\[:alnum:\]_\]*)\}|\{\\1.ttf\}|g" \
${f}
}
# fix python3 executable name
foreach f "\
${srcpath}/${distname}/boot \
${srcpath}/${distname}/utils/checkUniques/check-uniques.py \
" {
reinplace -E "s|^(#!/usr/bin/env python)3|\\1${python3_version}|" \
${f}
}

system -W ${srcpath}/${distname} "\
export \
PATH=$env(PATH):${bootstrap_dir}/bin ; \
./boot \
"

# configure
# install the final compiler to destroot
configure.pre_args \
--prefix=${destroot}${prefix}
set configure_args \
--with-ghc=${bootstrap_dir}/bin/ghc
configure.dir ${srcpath}/${distname}
system -W ${srcpath}/${distname} "\
export \
PATH=/usr/bin:$env(PATH):${bootstrap_dir}/bin ; \
${configure.cmd} ${configure.pre_args} ${configure_args} \
"

# build and destroot the second stage: `make && make install`
system -W ${srcpath}/${distname} "\
export \
PATH=/usr/bin:$env(PATH):${bootstrap_dir}/bin ; \
${build.cmd} [portbuild::build_getjobsarg] \
"
system -W ${srcpath}/${distname} "\
export \
PATH=/usr/bin:$env(PATH):${bootstrap_dir}/bin ; \
${build.cmd} ${destroot.pre_args} \
"
}

# Walk the current package.conf.d and delete all files not belonging to any
# port, since haskell packages now directly drop it in packages.conf.d and
# register the file to themselves. The package cache is updated by the
# post-activate phase of the packages, which now runs ghc-pkg recache.
#
# This *will* cause pre-deactivation failures for all ports that still are
# correctly installed and would unregister themselves on uninstall.
# Unfortunately there is no good way around this now that the contents of
# PortGroups are stored together with Portfiles and used for deactivation
# (otherwise I could just edit the PortGroup and make unregistration
# failures non-fatal)
foreach configfile [glob -nocomplain -directory $libprefix/package.conf.d *] {
if {[registry_file_registered $configfile] == 0} {
# file is not registered to any port, remove it
catch {delete $configfile}
# delete any destroot path appearing in text files
fs-traverse f ${destroot}${prefix} {
if {[file isfile ${f}]} {
if {[string match "text/*" [lindex [exec /usr/bin/file --mime-type ${f}] end]]} {
reinplace -q "s|${destroot}||g" ${f}
}
}
}
}

catch {system [list ${prefix}/bin/ghc-pkg -v recache]}
destroot {
xinstall -W ${filespath} -m 0644 ./ghci.conf ${destroot}${prefix}/etc
}

post-activate {
system "${prefix}/bin/ghc-pkg recache"
}

test.dir ${worksrcpath}/testsuite
test.target test
test.run yes

notes "The GHC User Manual is available at:
file://${prefix}/share/doc/${distname}/html/index.html
${prefix}/share/doc/${distname}/users_guide.pdf
Copy/edit ${prefix}/etc/ghci.conf to your directory ~/.ghc
for a user-specific starup configuration."
7 changes: 7 additions & 0 deletions lang/ghc/files/ghci.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:def hoogle \x -> return $ ":!hoogle \"" ++ x ++ "\""
:def doc \x -> return $ ":!hoogle --info \"" ++ x ++ "\""
:def hg \x -> return $ ":!hoogle \"" ++ x ++ "\""
:set +t +s
-- :set prompt "ghci> "
-- :set prompt "\ESC[34mλ> \ESC[m"
:set prompt "\ESC[1;34m%s\n\ESC[0;34mλ> \ESC[m"
Loading

0 comments on commit c862681

Please sign in to comment.