From 39ce5294b14a6fc1ae889c427290fc932466d8a0 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Thu, 1 Aug 2013 13:15:33 +0000 Subject: Fixed CFLAGS=-Os ghci failure (bug #452442 by Jason Mours). Added weak symbol processing into ghci. Limit maximum parallel job count down to 4 workers (-j1 is too slow on mmodern boxes, but -j12 kills the build almost always). Does not eliminate failures completely, but reduces them significantly (bug #456386). (Portage version: 2.2.0_alpha186/cvs/Linux x86_64, signed Manifest commit with key 611FF3AA) --- dev-lang/ghc/ChangeLog | 12 +- .../ghc/files/ghc-7.6.3-trac-3333-weak-syms.patch | 387 ++++++++++ dev-lang/ghc/ghc-7.6.3-r1.ebuild | 813 +++++++++++++++++++++ 3 files changed, 1211 insertions(+), 1 deletion(-) create mode 100644 dev-lang/ghc/files/ghc-7.6.3-trac-3333-weak-syms.patch create mode 100644 dev-lang/ghc/ghc-7.6.3-r1.ebuild (limited to 'dev-lang') diff --git a/dev-lang/ghc/ChangeLog b/dev-lang/ghc/ChangeLog index 1885244b56c0..f4fac98b08c4 100644 --- a/dev-lang/ghc/ChangeLog +++ b/dev-lang/ghc/ChangeLog @@ -1,6 +1,16 @@ # ChangeLog for dev-lang/ghc # Copyright 1999-2013 Gentoo Foundation; Distributed under the GPL v2 -# $Header: /var/cvsroot/gentoo-x86/dev-lang/ghc/ChangeLog,v 1.244 2013/07/19 10:21:35 slyfox Exp $ +# $Header: /var/cvsroot/gentoo-x86/dev-lang/ghc/ChangeLog,v 1.245 2013/08/01 13:15:33 slyfox Exp $ + +*ghc-7.6.3-r1 (01 Aug 2013) + + 01 Aug 2013; Sergei Trofimovich + +files/ghc-7.6.3-trac-3333-weak-syms.patch, +ghc-7.6.3-r1.ebuild: + Fixed CFLAGS=-Os ghci failure (bug #452442 by Jason Mours). Added weak symbol + processing into ghci. Limit maximum parallel job count down to 4 workers (-j1 + is too slow on mmodern boxes, but -j12 kills the build almost always). Does + not eliminate failures completely, but reduces them significantly (bug + #456386). 19 Jul 2013; Sergei Trofimovich ghc-7.6.3.ebuild: Fix building on systems where libdir differs from the one we have built GHC diff --git a/dev-lang/ghc/files/ghc-7.6.3-trac-3333-weak-syms.patch b/dev-lang/ghc/files/ghc-7.6.3-trac-3333-weak-syms.patch new file mode 100644 index 000000000000..c3184a68c1e7 --- /dev/null +++ b/dev-lang/ghc/files/ghc-7.6.3-trac-3333-weak-syms.patch @@ -0,0 +1,387 @@ +The patch set adds support for weak symbols to ghci. + +For gentoo it fixes nonworking ghci / template haskell +for package base. + +Steps to reproduce: + 1. CFLAGS=-Os emerge ghc + 2. ghci -package base + Loading package base ... linking ... ghc: /usr/lib64/ghc-7.6.3/base-4.6.0.1/HSbase-4.6.0.1.o: unknown symbol `stat' + +When built with -O2 weak 'stat' resolved to '__xstat' and we don't see any errors. +But on olwer optimization levels 'stat' remains. + +Patches-by: akio +Gentoo-bug: http://bugs.gentoo.org/452442 +Upstream-bug: http://ghc.haskell.org/trac/ghc/ticket/3333 + +From 500d57d3a18412c78cab5abc4d91f1564edc964d Mon Sep 17 00:00:00 2001 +From: Takano Akio +Date: Sat, 29 Dec 2012 11:47:22 +0900 +Subject: [PATCH 1/3] Linker.c: remove stablehash, which is no longer used + +--- + includes/rts/Linker.h | 3 --- + rts/Linker.c | 31 ++----------------------------- + 2 files changed, 2 insertions(+), 32 deletions(-) + +diff --git a/includes/rts/Linker.h b/includes/rts/Linker.h +index e900e85..d20ebc2 100644 +--- a/includes/rts/Linker.h ++++ b/includes/rts/Linker.h +@@ -23,9 +23,6 @@ typedef char pathchar; + /* initialize the object linker */ + void initLinker( void ); + +-/* insert a stable symbol in the hash table */ +-void insertStableSymbol(pathchar* obj_name, char* key, StgPtr data); +- + /* insert a symbol in the hash table */ + void insertSymbol(pathchar* obj_name, char* key, void* data); + +diff --git a/rts/Linker.c b/rts/Linker.c +index fa1de89..513fe3f 100644 +--- a/rts/Linker.c ++++ b/rts/Linker.c +@@ -30,1 +30,0 @@ +-#include "Stable.h" +@@ -150,9 +149,6 @@ int dynamicByDefault = 0; + /* Hash table mapping symbol names to Symbol */ + static /*Str*/HashTable *symhash; + +-/* Hash table mapping symbol names to StgStablePtr */ +-static /*Str*/HashTable *stablehash; +- + /* List of currently loaded objects */ + ObjectCode *objects = NULL; /* initially empty */ + +@@ -1126,1 +1126,0 @@ typedef struct _RtsSymbolVal { +- SymI_HasProto(insertStableSymbol) \ +@@ -1488,7 +1483,6 @@ initLinker( void ) + #if defined(THREADED_RTS) && (defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)) + initMutex(&dl_mutex); + #endif +- stablehash = allocStrHashTable(); + symhash = allocStrHashTable(); + + /* populate the symbol table with stuff from the RTS */ +@@ -1817,17 +1811,6 @@ error: + } + + /* ----------------------------------------------------------------------------- +- * insert a stable symbol in the hash table +- */ +- +-void +-insertStableSymbol(pathchar* obj_name, char* key, StgPtr p) +-{ +- ghciInsertStrHashTable(obj_name, stablehash, key, getStablePtr(p)); +-} +- +- +-/* ----------------------------------------------------------------------------- + * insert a symbol in the hash table + */ + void +@@ -4749,8 +4732,6 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC, + #ifdef i386_HOST_ARCH + Elf_Addr value; + #endif +- StgStablePtr stablePtr; +- StgPtr stableVal; + #ifdef arm_HOST_ARCH + int is_target_thm=0, T=0; + #endif +@@ -4773,16 +4754,8 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC, + + } else { + symbol = strtab + sym.st_name; +- stablePtr = (StgStablePtr)lookupHashTable(stablehash, (StgWord)symbol); +- if (NULL == stablePtr) { +- /* No, so look up the name in our global table. */ +- S_tmp = lookupSymbol( symbol ); +- S = (Elf_Addr)S_tmp; +- } else { +- stableVal = deRefStablePtr( stablePtr ); +- S_tmp = stableVal; +- S = (Elf_Addr)S_tmp; +- } ++ S_tmp = lookupSymbol( symbol ); ++ S = (Elf_Addr)S_tmp; + } + if (!S) { + errorBelch("%s: unknown symbol `%s'", oc->fileName, symbol); +-- +1.7.9.5 + +From 2e5e0f7a90dd390adc5ae5fb2a3bc6e879aa42d6 Mon Sep 17 00:00:00 2001 +From: Takano Akio +Date: Sat, 29 Dec 2012 11:59:34 +0900 +Subject: [PATCH 2/3] ghci: add support for ELF weak symbols + +--- + rts/Linker.c | 102 ++++++++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 78 insertions(+), 24 deletions(-) + +diff --git a/rts/Linker.c b/rts/Linker.c +index 513fe3f..5105085 100644 +--- a/rts/Linker.c ++++ b/rts/Linker.c +@@ -146,7 +146,13 @@ int dynamicByDefault = 1; + int dynamicByDefault = 0; + #endif + +-/* Hash table mapping symbol names to Symbol */ ++typedef struct _RtsSymbolInfo { ++ void *value; ++ const ObjectCode *owner; ++ HsBool weak; ++} RtsSymbolInfo; ++ ++/* Hash table mapping symbol names to RtsSymbolInfo */ + static /*Str*/HashTable *symhash; + + /* List of currently loaded objects */ +@@ -1415,15 +1421,31 @@ static RtsSymbolVal rtsSyms[] = { + * Insert symbols into hash tables, checking for duplicates. + */ + +-static void ghciInsertStrHashTable ( pathchar* obj_name, +- HashTable *table, +- char* key, +- void *data +- ) ++static void ghciInsertSymbolTable( ++ pathchar* obj_name, ++ HashTable *table, ++ char* key, ++ void *data, ++ HsBool weak, ++ ObjectCode *owner) + { +- if (lookupHashTable(table, (StgWord)key) == NULL) ++ RtsSymbolInfo *pinfo = lookupStrHashTable(table, key); ++ if (!pinfo) /* new entry */ ++ { ++ pinfo = stgMallocBytes(sizeof (*pinfo), "ghciInsertToSymbolTable"); ++ pinfo->value = data; ++ pinfo->owner = owner; ++ pinfo->weak = weak; ++ insertStrHashTable(table, key, pinfo); ++ return; ++ } else if ((!pinfo->weak || pinfo->value) && weak) { ++ return; /* duplicate weak symbol, throw it away */ ++ } else if (pinfo->weak) /* weak symbol is in the table */ + { +- insertStrHashTable(table, (StgWord)key, data); ++ /* override the weak definition with the non-weak one */ ++ pinfo->value = data; ++ pinfo->owner = owner; ++ pinfo->weak = HS_BOOL_FALSE; + return; + } + debugBelch( +@@ -1444,6 +1466,32 @@ static void ghciInsertStrHashTable ( pathchar* obj_name, + ); + stg_exit(1); + } ++ ++static HsBool ghciLookupSymbolTable(HashTable *table, ++ const char *key, void **result) ++{ ++ RtsSymbolInfo *pinfo = lookupStrHashTable(table, key); ++ if (!pinfo) { ++ *result = NULL; ++ return HS_BOOL_FALSE; ++ } ++ if (pinfo->weak) ++ IF_DEBUG(linker, debugBelch("lookup: promoting %s\n", key)); ++ /* Once it's looked up, it can no longer be overridden */ ++ pinfo->weak = HS_BOOL_FALSE; ++ ++ *result = pinfo->value; ++ return HS_BOOL_TRUE; ++} ++ ++static void ghciRemoveSymbolTable(HashTable *table, const char *key, ++ ObjectCode *owner) ++{ ++ RtsSymbolInfo *pinfo = lookupStrHashTable(table, key); ++ if (!pinfo || owner != pinfo->owner) return; ++ removeStrHashTable(table, key, NULL); ++ stgFree(pinfo); ++} + /* ----------------------------------------------------------------------------- + * initialize the object linker + */ +@@ -1487,8 +1535,8 @@ initLinker( void ) + + /* populate the symbol table with stuff from the RTS */ + for (sym = rtsSyms; sym->lbl != NULL; sym++) { +- ghciInsertStrHashTable(WSTR("(GHCi built-in symbols)"), +- symhash, sym->lbl, sym->addr); ++ ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"), ++ symhash, sym->lbl, sym->addr, HS_BOOL_FALSE, NULL); + IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr)); + } + # if defined(OBJFORMAT_MACHO) && defined(powerpc_HOST_ARCH) +@@ -1816,7 +1864,7 @@ error: + void + insertSymbol(pathchar* obj_name, char* key, void* data) + { +- ghciInsertStrHashTable(obj_name, symhash, key, data); ++ ghciInsertSymbolTable(obj_name, symhash, key, data, HS_BOOL_FALSE, NULL); + } + + /* ----------------------------------------------------------------------------- +@@ -1829,9 +1877,8 @@ lookupSymbol( char *lbl ) + IF_DEBUG(linker, debugBelch("lookupSymbol: looking up %s\n", lbl)); + initLinker() ; + ASSERT(symhash != NULL); +- val = lookupStrHashTable(symhash, lbl); + +- if (val == NULL) { ++ if (!ghciLookupSymbolTable(symhash, lbl, &val)) { + IF_DEBUG(linker, debugBelch("lookupSymbol: symbol not found\n")); + # if defined(OBJFORMAT_ELF) + return internal_dlsym(dl_prog_handle, lbl); +@@ -1903,7 +1950,7 @@ void ghci_enquire ( char* addr ) + if (sym == NULL) continue; + a = NULL; + if (a == NULL) { +- a = lookupStrHashTable(symhash, sym); ++ ghciLookupSymbolTable(symhash, sym, (void **)&a); + } + if (a == NULL) { + // debugBelch("ghci_enquire: can't find %s\n", sym); +@@ -2715,7 +2762,7 @@ unloadObj( pathchar *path ) + int i; + for (i = 0; i < oc->n_symbols; i++) { + if (oc->symbols[i] != NULL) { +- removeStrHashTable(symhash, oc->symbols[i], NULL); ++ ghciRemoveSymbolTable(symhash, oc->symbols[i], oc); + } + } + } +@@ -3802,7 +3849,8 @@ ocGetNames_PEi386 ( ObjectCode* oc ) + ASSERT(i >= 0 && i < oc->n_symbols); + /* cstring_from_COFF_symbol_name always succeeds. */ + oc->symbols[i] = (char*)sname; +- ghciInsertStrHashTable(oc->fileName, symhash, (char*)sname, addr); ++ ghciInsertSymbolTable(oc->fileName, symhash, (char*)sname, addr, ++ HS_BOOL_FALSE, oc); + } else { + # if 0 + debugBelch( +@@ -4595,6 +4643,7 @@ ocGetNames_ELF ( ObjectCode* oc ) + for (j = 0; j < nent; j++) { + + char isLocal = FALSE; /* avoids uninit-var warning */ ++ HsBool isWeak = HS_BOOL_FALSE; + char* ad = NULL; + char* nm = strtab + stab[j].st_name; + int secno = stab[j].st_shndx; +@@ -4615,6 +4664,7 @@ ocGetNames_ELF ( ObjectCode* oc ) + else + if ( ( ELF_ST_BIND(stab[j].st_info)==STB_GLOBAL + || ELF_ST_BIND(stab[j].st_info)==STB_LOCAL ++ || ELF_ST_BIND(stab[j].st_info)==STB_WEAK + ) + /* and not an undefined symbol */ + && stab[j].st_shndx != SHN_UNDEF +@@ -4638,7 +4688,8 @@ ocGetNames_ELF ( ObjectCode* oc ) + ad = ehdrC + shdr[ secno ].sh_offset + stab[j].st_value; + if (ELF_ST_BIND(stab[j].st_info)==STB_LOCAL) { + isLocal = TRUE; +- } else { ++ isWeak = FALSE; ++ } else { /* STB_GLOBAL or STB_WEAK */ + #ifdef ELF_FUNCTION_DESC + /* dlsym() and the initialisation table both give us function + * descriptors, so to be consistent we store function descriptors +@@ -4649,6 +4700,7 @@ ocGetNames_ELF ( ObjectCode* oc ) + IF_DEBUG(linker,debugBelch( "addOTabName(GLOB): %10p %s %s\n", + ad, oc->fileName, nm )); + isLocal = FALSE; ++ isWeak = (ELF_ST_BIND(stab[j].st_info)==STB_WEAK); + } + } + +@@ -4661,7 +4713,7 @@ ocGetNames_ELF ( ObjectCode* oc ) + if (isLocal) { + /* Ignore entirely. */ + } else { +- ghciInsertStrHashTable(oc->fileName, symhash, nm, ad); ++ ghciInsertSymbolTable(oc->fileName, symhash, nm, ad, isWeak, oc); + } + } else { + /* Skip. */ +@@ -6306,11 +6358,13 @@ ocGetNames_MachO(ObjectCode* oc) + else + { + IF_DEBUG(linker, debugBelch("ocGetNames_MachO: inserting %s\n", nm)); +- ghciInsertStrHashTable(oc->fileName, symhash, nm, ++ ghciInsertSymbolTable(oc->fileName, symhash, nm, + image + + sections[nlist[i].n_sect-1].offset + - sections[nlist[i].n_sect-1].addr +- + nlist[i].n_value); ++ + nlist[i].n_value, ++ HS_BOOL_FALSE, ++ oc); + oc->symbols[curSymbol++] = nm; + } + } +@@ -6341,8 +6395,8 @@ ocGetNames_MachO(ObjectCode* oc) + nlist[i].n_value = commonCounter; + + IF_DEBUG(linker, debugBelch("ocGetNames_MachO: inserting common symbol: %s\n", nm)); +- ghciInsertStrHashTable(oc->fileName, symhash, nm, +- (void*)commonCounter); ++ ghciInsertSymbolTable(oc->fileName, symhash, nm, ++ (void*)commonCounter, HS_BOOL_FALSE, oc); + oc->symbols[curSymbol++] = nm; + + commonCounter += sz; +@@ -6466,7 +6520,7 @@ machoInitSymbolsWithoutUnderscore(void) + + #undef SymI_NeedsProto + #define SymI_NeedsProto(x) \ +- ghciInsertStrHashTable("(GHCi built-in symbols)", symhash, #x, *p++); ++ ghciInsertSymbolTable("(GHCi built-in symbols)", symhash, #x, *p++, HS_BOOL_FALSE, NULL); + + RTS_MACHO_NOUNDERLINE_SYMBOLS + +-- +1.7.9.5 + +From 916d7713b34b529ae7ec24eaa836a4eaca7724fc Mon Sep 17 00:00:00 2001 +From: Takano Akio +Date: Sun, 6 Jan 2013 17:51:19 +0900 +Subject: [PATCH 3/3] Linker.c: add dso_handle to the symbol table + +--- + rts/Linker.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/rts/Linker.c b/rts/Linker.c +index 5105085..0b2bf63 100644 +--- a/rts/Linker.c ++++ b/rts/Linker.c +@@ -1542,6 +1542,13 @@ initLinker( void ) + # if defined(OBJFORMAT_MACHO) && defined(powerpc_HOST_ARCH) + machoInitSymbolsWithoutUnderscore(); + # endif ++ /* GCC defines a special symbol __dso_handle which is resolved to NULL if ++ referenced from a statically linked module. We need to mimic this, but ++ we cannot use NULL because we use it to mean nonexistent symbols. So we ++ use an arbitrary (hopefully unique) address here. ++ */ ++ ghciInsertSymbolTable(WSTR("(GHCi special symbols)"), ++ symhash, "__dso_handle", (void *)0x12345687, HS_BOOL_FALSE, NULL); + + # if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO) + # if defined(RTLD_DEFAULT) +-- +1.7.9.5 + diff --git a/dev-lang/ghc/ghc-7.6.3-r1.ebuild b/dev-lang/ghc/ghc-7.6.3-r1.ebuild new file mode 100644 index 000000000000..b693c3524d36 --- /dev/null +++ b/dev-lang/ghc/ghc-7.6.3-r1.ebuild @@ -0,0 +1,813 @@ +# Copyright 1999-2013 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/dev-lang/ghc/ghc-7.6.3-r1.ebuild,v 1.1 2013/08/01 13:15:33 slyfox Exp $ + +# Brief explanation of the bootstrap logic: +# +# Previous ghc ebuilds have been split into two: ghc and ghc-bin, +# where ghc-bin was primarily used for bootstrapping purposes. +# From now on, these two ebuilds have been combined, with the +# binary USE flag used to determine whether or not the pre-built +# binary package should be emerged or whether ghc should be compiled +# from source. If the latter, then the relevant ghc-bin for the +# arch in question will be used in the working directory to compile +# ghc from source. +# +# This solution has the advantage of allowing us to retain the one +# ebuild for both packages, and thus phase out virtual/ghc. + +# Note to users of hardened gcc-3.x: +# +# If you emerge ghc with hardened gcc it should work fine (because we +# turn off the hardened features that would otherwise break ghc). +# However, emerging ghc while using a vanilla gcc and then switching to +# hardened gcc (using gcc-config) will leave you with a broken ghc. To +# fix it you would need to either switch back to vanilla gcc or re-emerge +# ghc (or ghc-bin). Note that also if you are using hardened gcc-3.x and +# you switch to gcc-4.x that this will also break ghc and you'll need to +# re-emerge ghc (or ghc-bin). People using vanilla gcc can switch between +# gcc-3.x and 4.x with no problems. + +EAPI="5" + +# to make make a crosscompiler use crossdev and symlink ghc tree into +# cross overlay. result would look like 'cross-sparc-unknown-linux-gnu/ghc' +# +# 'CTARGET' definition and 'is_crosscompile' are taken from 'toolchain.eclass' +export CTARGET=${CTARGET:-${CHOST}} +if [[ ${CTARGET} = ${CHOST} ]] ; then + if [[ ${CATEGORY/cross-} != ${CATEGORY} ]] ; then + export CTARGET=${CATEGORY/cross-} + fi +fi + +inherit autotools bash-completion-r1 eutils flag-o-matic ghc-package +inherit multilib multiprocessing pax-utils toolchain-funcs versionator + +DESCRIPTION="The Glasgow Haskell Compiler" +HOMEPAGE="http://www.haskell.org/ghc/" + +# we don't have any binaries yet +arch_binaries="" + +# sorted! +arch_binaries="$arch_binaries alpha? ( http://code.haskell.org/~slyfox/ghc-alpha/ghc-bin-${PV}-alpha.tbz2 )" +#arch_binaries="$arch_binaries arm? ( http://code.haskell.org/~slyfox/ghc-arm/ghc-bin-${PV}-arm.tbz2 )" +arch_binaries="$arch_binaries amd64? ( http://code.haskell.org/~slyfox/ghc-amd64/ghc-bin-${PV}-amd64.tbz2 )" +arch_binaries="$arch_binaries ia64? ( http://code.haskell.org/~slyfox/ghc-ia64/ghc-bin-${PV}-ia64.tbz2 )" +#arch_binaries="$arch_binaries ppc? ( http://code.haskell.org/~slyfox/ghc-ppc/ghc-bin-${PV}-ppc.tbz2 )" +#arch_binaries="$arch_binaries ppc64? ( http://code.haskell.org/~slyfox/ghc-ppc64/ghc-bin-${PV}-ppc64.tbz2 )" +#arch_binaries="$arch_binaries sparc? ( http://code.haskell.org/~slyfox/ghc-sparc/ghc-bin-${PV}-sparc.tbz2 )" +arch_binaries="$arch_binaries x86? ( http://code.haskell.org/~slyfox/ghc-x86/ghc-bin-${PV}-x86.tbz2 )" + +# various ports: +#arch_binaries="$arch_binaries x86-fbsd? ( http://code.haskell.org/~slyfox/ghc-x86-fbsd/ghc-bin-${PV}-x86-fbsd.tbz2 )" + +# 0 - yet +yet_binary() { + case "${ARCH}" in + alpha) return 0 ;; + #arm) + # ewarn "ARM binary is built on armv5tel-eabi toolchain. Use with caution." + # return 0 + #;; + amd64) return 0 ;; + ia64) return 0 ;; + #ppc) return 0 ;; + #ppc64) return 0 ;; + #sparc) return 0 ;; + x86) return 0 ;; + *) return 1 ;; + esac +} + +SRC_URI="!binary? ( http://www.haskell.org/ghc/dist/${PV}/${P}-src.tar.bz2 )" +[[ -n $arch_binaries ]] && SRC_URI+=" !ghcbootstrap? ( $arch_binaries )" +LICENSE="BSD" +SLOT="0/${PV}" +KEYWORDS="~amd64 ~x86 ~amd64-linux ~x86-linux ~ppc-macos ~x86-macos ~sparc-solaris ~x86-solaris" +IUSE="doc ghcbootstrap ghcmakebinary +gmp llvm" +IUSE+=" binary" # don't forget about me later! +IUSE+=" elibc_glibc" # system stuff + +RDEPEND=" + !kernel_Darwin? ( >=sys-devel/gcc-2.95.3 ) + kernel_linux? ( >=sys-devel/binutils-2.17 ) + kernel_SunOS? ( >=sys-devel/binutils-2.17 ) + >=dev-lang/perl-5.6.1 + >=dev-libs/gmp-5 + virtual/libffi + !=gmp-5, even if >=gmp-4.1 would be enough. this is due to +# that we want the binaries to use the latest versioun available, and not to be +# built against gmp-4 + +# similar for glibc. we have bootstrapped binaries against glibc-2.14 +DEPEND="${RDEPEND} + ghcbootstrap? ( >=dev-haskell/alex-2.3 + >=dev-haskell/happy-1.18 + doc? ( app-text/docbook-xml-dtd:4.2 + app-text/docbook-xml-dtd:4.5 + app-text/docbook-xsl-stylesheets + >=dev-libs/libxslt-1.1.2 ) ) + !ghcbootstrap? ( !prefix? ( elibc_glibc? ( >=sys-libs/glibc-2.15 ) ) )" + +PDEPEND="!ghcbootstrap? ( =app-admin/haskell-updater-1.2* )" +PDEPEND=" + ${PDEPEND} + llvm? ( sys-devel/llvm )" + +# ia64 fails to return from STG GMP primitives (stage2 always SIGSEGVs) +REQUIRED_USE="ia64? ( !gmp )" + +is_crosscompile() { + [[ ${CHOST} != ${CTARGET} ]] +} + +append-ghc-cflags() { + local flag compile assemble link + for flag in $*; do + case ${flag} in + compile) compile="yes";; + assemble) assemble="yes";; + link) link="yes";; + *) + [[ ${compile} ]] && GHC_FLAGS="${GHC_FLAGS} -optc${flag}" CFLAGS="${CFLAGS} ${flag}" + [[ ${assemble} ]] && GHC_FLAGS="${GHC_FLAGS} -opta${flag}" CFLAGS="${CFLAGS} ${flag}" + [[ ${link} ]] && GHC_FLAGS="${GHC_FLAGS} -optl${flag}" FILTERED_LDFLAGS="${FILTERED_LDFLAGS} ${flag}";; + esac + done +} + +ghc_setup_cflags() { + if is_crosscompile; then + export CFLAGS=${GHC_CFLAGS-"-O2 -pipe"} + export LDFLAGS=${GHC_LDFLAGS-"-Wl,-O1"} + einfo "Crosscompiling mode:" + einfo " CHOST: ${CHOST}" + einfo " CTARGET: ${CTARGET}" + einfo " CFLAGS: ${CFLAGS}" + einfo " LDFLAGS: ${LDFLAGS}" + return + fi + # We need to be very careful with the CFLAGS we ask ghc to pass through to + # gcc. There are plenty of flags which will make gcc produce output that + # breaks ghc in various ways. The main ones we want to pass through are + # -mcpu / -march flags. These are important for arches like alpha & sparc. + # We also use these CFLAGS for building the C parts of ghc, ie the rts. + strip-flags + strip-unsupported-flags + + GHC_FLAGS="" + for flag in ${CFLAGS}; do + case ${flag} in + + # Ignore extra optimisation (ghc passes -O to gcc anyway) + # -O2 and above break on too many systems + -O*) ;; + + # Arch and ABI flags are what we're really after + -m*) append-ghc-cflags compile assemble ${flag};; + + # Sometimes it's handy to see backtrace of RTS + # to get an idea what happens there + -g*) append-ghc-cflags compile ${flag};; + + # Ignore all other flags, including all -f* flags + esac + done + + FILTERED_LDFLAGS="" + for flag in ${LDFLAGS}; do + case ${flag} in + # Pass the canary. we don't quite respect LDFLAGS, but we have an excuse! + "-Wl,--hash-style="*) append-ghc-cflags link ${flag};; + + # Ignore all other flags + esac + done + + # hardened-gcc needs to be disabled, because the mangler doesn't accept + # its output. + gcc-specs-pie && append-ghc-cflags compile link -nopie + gcc-specs-ssp && append-ghc-cflags compile -fno-stack-protector + + # prevent from failind building unregisterised ghc: + # http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg171602.html + use ppc64 && append-ghc-cflags compile -mminimal-toc + # fix the similar issue as ppc64 TOC on ia64. ia64 has limited size of small data + # currently ghc fails to build haddock + # http://osdir.com/ml/gnu.binutils.bugs/2004-10/msg00050.html + use ia64 && append-ghc-cflags compile -G0 -Os + + # Unfortunately driver/split/ghc-split.lprl is dumb + # enough to preserve stack marking for each split object + # and it flags stack marking violation: + # * !WX --- --- usr/lib64/ghc-7.4.1/base-4.5.0.0/libHSbase-4.5.0.0.a:Fingerprint__1.o + # * !WX --- --- usr/lib64/ghc-7.4.1/base-4.5.0.0/libHSbase-4.5.0.0.a:Fingerprint__2.o + # * !WX --- --- usr/lib64/ghc-7.4.1/base-4.5.0.0/libHSbase-4.5.0.0.a:Fingerprint__3.o + case $($(tc-getAS) -v 2>&1 /dev/null || die + use sparc-solaris && unpack ghc-6.10.4-sparc-sun-solaris2.tar.bz2 + use x86-solaris && unpack ghc-7.0.3-i386-unknown-solaris2.tar.bz2 + use x86-macos && unpack ghc-7.4.1-i386-apple-darwin.tar.bz2 + use x64-macos && unpack ghc-7.4.1-x86_64-apple-darwin.tar.bz2 + popd > /dev/null + + pushd "${WORKDIR}"/ghc-bin-installer/ghc-[67].?*.? > /dev/null || die + # fix the binaries so they run, on Solaris we need an + # LD_LIBRARY_PATH which has our prefix libdirs, on + # Darwin we need to replace the frameworks with our libs + # from the prefix fix before installation, because some + # of the tools are actually used during configure/make + if [[ ${CHOST} == *-solaris* ]] ; then + export LD_LIBRARY_PATH="${EPREFIX}/$(get_libdir):${EPREFIX}/usr/$(get_libdir):${LD_LIBRARY_PATH}" + elif [[ ${CHOST} == *-darwin* ]] ; then + local readline_framework=GNUreadline.framework/GNUreadline + local gmp_framework=/opt/local/lib/libgmp.10.dylib + local ncurses_file=/opt/local/lib/libncurses.5.dylib + for binary in $(scanmacho -BRE MH_EXECUTE -F '%F' .) ; do + install_name_tool -change \ + ${readline_framework} \ + "${EPREFIX}"/lib/libreadline.dylib \ + ${binary} || die + install_name_tool -change \ + ${gmp_framework} \ + "${EPREFIX}"/usr/lib/libgmp.dylib \ + ${binary} || die + install_name_tool -change \ + ${ncurses_file} \ + "${EPREFIX}"/usr/lib/libncurses.dylib \ + ${binary} || die + done + # we don't do frameworks! + sed -i \ + -e 's/\(frameworks = \)\["GMP"\]/\1[]/g' \ + -e 's/\(extraLibraries = \)\["m"\]/\1["m","gmp"]/g' \ + rts/package.conf.in || die + fi + + # it is autoconf, but we really don't want to give it too + # much arguments, in fact we do the make in-place anyway + ./configure --prefix="${WORKDIR}"/usr || die + make install || die + popd > /dev/null + ;; + *) + relocate_ghc "${WORKDIR}" + ;; + esac + fi + + sed -i -e "s|\"\$topdir\"|\"\$topdir\" ${GHC_FLAGS}|" \ + "${S}/ghc/ghc.wrapper" + + cd "${S}" # otherwise epatch will break + + epatch "${FILESDIR}/ghc-7.0.4-CHOST-prefix.patch" + + # epatch "${FILESDIR}"/${PN}-7.0.4-darwin8.patch + # failed to apply. FIXME + #epatch "${FILESDIR}"/${PN}-6.12.3-mach-o-relocation-limit.patch + + # epatch "${FILESDIR}"/${PN}-7.4-rc2-macos-prefix-respect-gcc.patch + # epatch "${FILESDIR}"/${PN}-7.2.1-freebsd-CHOST.patch + + we_want_libffi_workaround() { + use ghcmakebinary && return 1 + + # pick only registerised arches + # http://bugs.gentoo.org/463814 + use amd64 && return 0 + use x86 && return 0 + return 1 + } + # one mode external depend with unstable ABI be careful to stash it + # avoid external libffi runtime when we build binaries + we_want_libffi_workaround && epatch "${FILESDIR}"/${PN}-7.5.20120505-system-libffi.patch + + epatch "${FILESDIR}"/${PN}-7.4.1-ticket-7339-fix-unaligned-unreg.patch + epatch "${FILESDIR}"/${PN}-7.6.2-integer-simple-div-mod.patch + # ghc-7.8 changed linker code and likely fixed it + epatch "${FILESDIR}"/${PN}-7.6.3-trac-3333-weak-syms.patch + + if use prefix; then + # Make configure find docbook-xsl-stylesheets from Prefix + sed -e '/^FP_DIR_DOCBOOK_XSL/s:\[.*\]:['"${EPREFIX}"'/usr/share/sgml/docbook/xsl-stylesheets/]:' \ + -i utils/haddock/doc/configure.ac || die + fi + + # as we have changed the build system + eautoreconf + fi +} + +src_configure() { + GHC_PV=${PV} # overrided in live ebuilds + + if ! use binary; then + # initialize build.mk + echo '# Gentoo changes' > mk/build.mk + + # Put docs into the right place, ie /usr/share/doc/ghc-${PV} + echo "docdir = ${EPREFIX}/usr/share/doc/${P}" >> mk/build.mk + echo "htmldir = ${EPREFIX}/usr/share/doc/${P}" >> mk/build.mk + + # We also need to use the GHC_FLAGS flags when building ghc itself + echo "SRC_HC_OPTS+=${GHC_FLAGS}" >> mk/build.mk + echo "SRC_CC_OPTS+=${CFLAGS}" >> mk/build.mk + echo "SRC_LD_OPTS+=${FILTERED_LDFLAGS}" >> mk/build.mk + + # We can't depend on haddock except when bootstrapping when we + # must build docs and include them into the binary .tbz2 package + # app-text/dblatex is not in portage, can not build PDF or PS + if use ghcbootstrap && use doc; then + echo "BUILD_DOCBOOK_PDF = NO" >> mk/build.mk + echo "BUILD_DOCBOOK_PS = NO" >> mk/build.mk + echo "BUILD_DOCBOOK_HTML = YES" >> mk/build.mk + if is_crosscompile; then + # TODO this is a workaround for this build error with the live ebuild with haddock: + # make[1]: *** No rule to make target `compiler/stage2/build/Module.hi', + # needed by `utils/haddock/dist/build/Main.o'. Stop. + echo "HADDOCK_DOCS = NO" >> mk/build.mk + else + echo "HADDOCK_DOCS = YES" >> mk/build.mk + fi + else + echo "BUILD_DOCBOOK_PDF = NO" >> mk/build.mk + echo "BUILD_DOCBOOK_PS = NO" >> mk/build.mk + echo "BUILD_DOCBOOK_HTML = NO" >> mk/build.mk + echo "HADDOCK_DOCS = NO" >> mk/build.mk + fi + + # circumvent a very strange bug that seems related with ghc producing + # too much output while being filtered through tee (e.g. due to + # portage logging) reported as bug #111183 + echo "SRC_HC_OPTS+=-w" >> mk/build.mk + + # some arches do not support ELF parsing for ghci module loading + # PPC64: never worked (should be easy to implement) + # alpha: never worked + # arm: http://hackage.haskell.org/trac/ghc/changeset/27302c9094909e04eb73f200d52d5e9370c34a8a + if use alpha || use ppc64; then + echo "GhcWithInterpreter=NO" >> mk/build.mk + fi + + # we have to tell it to build unregisterised on some arches + # ppc64: EvilMangler currently does not understand some TOCs + # ia64: EvilMangler bitrot + # set GHC_IS_UNREG if you like to build slow unregisterised + # host compiler. Handy if you plan to user resulting + # host compiler as a booting compiler for crosscompiler + # which can work only in unregisterised mode. + if use alpha || use ia64 || use ppc64 || [[ -n ${GHC_IS_UNREG} ]]; then + echo "GhcUnregisterised=YES" >> mk/build.mk + echo "GhcWithNativeCodeGen=NO" >> mk/build.mk + echo "SplitObjs=NO" >> mk/build.mk + echo "GhcRTSWays := debug" >> mk/build.mk + echo "GhcNotThreaded=YES" >> mk/build.mk + fi + + # arm: no EvilMangler support, no NCG support + if use arm; then + echo "GhcUnregisterised=YES" >> mk/build.mk + echo "GhcWithNativeCodeGen=NO" >> mk/build.mk + fi + + # Have "ld -r --relax" problem with split-objs on sparc: + if use sparc; then + echo "SplitObjs=NO" >> mk/build.mk + fi + + if ! use llvm; then + echo "GhcWithLlvmCodeGen=NO" >> mk/build.mk + fi + + # allows overriding build flavours for libraries: + # v - vanilla (static libs) + # p - profiled + # dyn - shared libraries + # example: GHC_LIBRARY_WAYS="v dyn" + if [[ -n ${GHC_LIBRARY_WAYS} ]]; then + echo "GhcLibWays=${GHC_LIBRARY_WAYS}" >> mk/build.mk + fi + + # Get ghc from the unpacked binary .tbz2 + # except when bootstrapping we just pick ghc up off the path + if ! use ghcbootstrap; then + export PATH="${WORKDIR}/usr/bin:${PATH}" + fi + + if use gmp; then + echo "INTEGER_LIBRARY=integer-gmp" >> mk/build.mk + else + echo "INTEGER_LIBRARY=integer-simple" >> mk/build.mk + fi + + # Since GHC 6.12.2 the GHC wrappers store which GCC version GHC was + # compiled with, by saving the path to it. The purpose is to make sure + # that GHC will use the very same gcc version when it compiles haskell + # sources, as the extra-gcc-opts files contains extra gcc options which + # match only this GCC version. + # However, this is not required in Gentoo, as only modern GCCs are used + # (>4). + # Instead, this causes trouble when for example ccache is used during + # compilation, but we don't want the wrappers to point to ccache. + # Due to the above, we simply set GCC to be "gcc". When compiling ghc it + # might point to ccache, once installed it will point to the users + # regular gcc. + + local econf_args=() + + is_crosscompile || econf_args+=--with-gcc=${CHOST}-gcc + + econf ${econf_args[@]} --enable-bootstrap-with-devel-snapshot \ + || die "econf failed" + + [[ ${PV} == *9999* ]] && GHC_PV="$(grep 'S\[\"PACKAGE_VERSION\"\]' config.status | sed -e 's@^.*=\"\(.*\)\"@\1@')" + GHC_TPF="$(grep 'S\[\"TargetPlatformFull\"\]' config.status | sed -e 's@^.*=\"\(.*\)\"@\1@')" + fi # ! use binary +} + +src_compile() { + if ! use binary; then + limit_jobs() { + local user_jobs=$(makeopts_jobs) + local max_nonbreaking_jobs=$1 + + [[ ${user_jobs} -le ${max_nonbreaking_jobs} ]] && return + + if [[ -n ${I_DEMAND_MY_CORES_LOADED} ]]; then + ewarn "You have requested parallel build which is known to break." + ewarn "Please report all breakages upstream." + return + else + ewarn "Limiting MAKEOPTS -j${user_jobs} -> -j${max_nonbreaking_jobs} (bug #456386)" + user_jobs=${max_nonbreaking_jobs} + fi + echo -j${user_jobs} + } + # ghc massively parallel make: #409631, #409873 + # but let users screw it by setting 'I_DEMAND_MY_CORES_LOADED' + # 4 parallel jobs usually does not break + emake $(limit_jobs 4) all + emake all V=1 + + if is_crosscompile; then + # runghc does not work for a stage1 compiler, we can build it anyway + # so it will print the error message: not built for interactive use + pushd "${S}/utils/runghc" || die "Could not cd to utils/runghc" + if [ ! -f Setup.hs ]; then + echo 'import Distribution.Simple; main = defaultMainWithHooks defaultUserHooks' \ + > Setup.hs || die "failed to create default Setup.hs" + fi + ghc -o setup --make Setup.hs || die "setup build failed" + ./setup configure || die "runghc configure failed" + sed -e "s@VERSION@\"${GHC_PV}\"@" -i runghc.hs + ./setup build || die "runghc build failed" + popd + fi + fi # ! use binary +} + +ghc-needs-c_nonshared-for-interpreter-libs() { + local sample_test=${T}/c_nonshared-test.c + echo "int main() {} " > "${sample_test}" || die + $(tc-getCC) -o "${sample_test}".result "${sample_test}" \ + -L"${ROOT}"/usr/$(get_libdir) -lc_nonshared +} + +add-c_nonshared-to-ghci-libs() { + local ghci_lib + local nonshared_dir=${T}/libc_nonshared_objects + + is_crosscompile && return + ghc-needs-c_nonshared-for-interpreter-libs || return + + get-nonshared-objects() { + # ns - 'nonshared' + local ns_objects=" " + local ns_sym + local ns_srco + local ns_dsto + + # extract + mkdir "${nonshared_dir}" || die + pushd "${nonshared_dir}" >/dev/null || die + $(tc-getAR) x "${ROOT}"/usr/$(get_libdir)/libc_nonshared.a + popd >/dev/null || die + + for ns_sym in \ + stat fstat lstat mknod \ + stat64 fstat64 lstat64 \ + fstatat fstatat64 mknodat + do + ns_srco=${nonshared_dir}/${ns_sym}.oS + ns_dsto=${nonshared_dir}/${ns_sym}_weakened.o + [[ -f ${ns_srco} ]] || continue + # here we do The Magic: + # 1. --keep-global-symbol= hides everything to adoid double definition + # of stuff like __stat, __fstat and + # 2. --weaken converts exported symbols to weak symbols to be available + # for redefinition + $(tc-getOBJCOPY) \ + --weaken --keep-global-symbol=${ns_sym} \ + "${ns_srco}" "${ns_dsto}" || die + + ns_objects+=" ${ns_dsto}" + done + + echo "${ns_objects}" + } + # bug #452442: when building libraries for ghci + # ghc basically glues them together: + # $ ld -r -o result foo.o bar.o ... + # that way some symbols defined in libc_nonshared.a + # do not get included into final HS*.o files + # We piggyback on one of early loaded wired-in library + # loaded before 'base'. + while read ghci_lib + do + einfo "relinking '${ghci_lib}' with c_includes" + mv "${ghci_lib}" "${ghci_lib}".unrelinked.o || die + $(tc-getLD) -r -o "${ghci_lib}" \ + "${ghci_lib}".unrelinked.o \ + $(get-nonshared-objects) || die + rm -r "${nonshared_dir}" || die + rm "${ghci_lib}".unrelinked.o || die + done < <(find "${ED}"/usr/$(get_libdir)/${P}/ -name 'HSghc-prim*.o') +} + +src_install() { + if use binary; then + use prefix && mkdir -p "${ED}" + mv "${S}/usr" "${ED}" + + # Remove the docs if not requested + if ! use doc; then + rm -rf "${ED}/usr/share/doc/${P}/*/" \ + "${ED}/usr/share/doc/${P}/*.html" \ + || die "could not remove docs (P vs PF revision mismatch?)" + fi + else + local insttarget="install" + + # We only built docs if we were bootstrapping, otherwise + # we copy them out of the unpacked binary .tbz2 + if use doc && ! use ghcbootstrap; then + mkdir -p "${ED}/usr/share/doc" + mv "${WORKDIR}/usr/share/doc/${P}" "${ED}/usr/share/doc" \ + || die "failed to copy docs" + else + dodoc "${S}/README" "${S}/ANNOUNCE" "${S}/LICENSE" "${S}/VERSION" + fi + + emake -j1 ${insttarget} \ + DESTDIR="${D}" \ + || die "make ${insttarget} failed" + + # remove wrapper and linker + rm -f "${ED}"/usr/bin/haddock* + + add-c_nonshared-to-ghci-libs + + # ghci uses mmap with rwx protection at it implements dynamic + # linking on it's own (bug #299709) + # so mark resulting binary + pax-mark -m "${ED}/usr/$(get_libdir)/${P}/ghc" + + if [[ ! -f "${S}/VERSION" ]]; then + echo "${GHC_PV}" > "${S}/VERSION" \ + || die "Could not create file ${S}/VERSION" + fi + dobashcomp "${FILESDIR}/ghc-bash-completion" + + fi + + # path to the package.cache + local package_confdir="${ED}/usr/$(get_libdir)/${PN}-${GHC_PV}/package.conf.d" + PKGCACHE="${package_confdir}"/package.cache + # copy the package.conf.d, including timestamp, save it so we can help + # users that have a broken package.conf.d + cp -pR "${package_confdir}"{,.initial} || die "failed to backup intial package.conf.d" + + # copy the package.conf, including timestamp, save it so we later can put it + # back before uninstalling, or when upgrading. + cp -p "${PKGCACHE}"{,.shipped} \ + || die "failed to copy package.conf.d/package.cache" +} + +pkg_preinst() { + # have we got an earlier version of ghc installed? + if has_version "<${CATEGORY}/${PF}"; then + haskell_updater_warn="1" + fi +} + +pkg_postinst() { + ghc-reregister + + # path to the package.cache + PKGCACHE="${EROOT}/usr/$(get_libdir)/${P}/package.conf.d/package.cache" + + # give the cache a new timestamp, it must be as recent as + # the package.conf.d directory. + touch "${PKGCACHE}" + + if [[ "${haskell_updater_warn}" == "1" ]]; then + ewarn + ewarn "\e[1;31m************************************************************************\e[0m" + ewarn + ewarn "You have just upgraded from an older version of GHC." + ewarn "You may have to run" + ewarn " 'haskell-updater --upgrade'" + ewarn "to rebuild all ghc-based Haskell libraries." + ewarn + ewarn "\e[1;31m************************************************************************\e[0m" + ewarn + fi + if is_crosscompile; then + ewarn + ewarn "\e[1;31m************************************************************************\e[0m" + ewarn + ewarn "GHC built as a cross compiler. The interpreter, ghci and runghc, do" + ewarn "not work for a cross compiler." + ewarn "For the ghci error: \": not built for interactive use\" see:" + ewarn "http://www.haskell.org/haskellwiki/GHC:FAQ#When_I_try_to_start_ghci_.28probably_one_I_compiled_myself.29_it_says_ghc-5.02:_not_built_for_interactive_use" + ewarn + ewarn "\e[1;31m************************************************************************\e[0m" + ewarn + fi +} + +pkg_prerm() { + # Be very careful here... Call order when upgrading is (according to PMS): + # * src_install for new package + # * pkg_preinst for new package + # * pkg_postinst for new package + # * pkg_prerm for the package being replaced + # * pkg_postrm for the package being replaced + # so you'll actually be touching the new packages files, not the one you + # uninstall, due to that or installation directory ${P} will be the same for + # both packages. + + # Call order for reinstalling is (according to PMS): + # * src_install + # * pkg_preinst + # * pkg_prerm for the package being replaced + # * pkg_postrm for the package being replaced + # * pkg_postinst + + # Overwrite the modified package.cache with a copy of the + # original one, so that it will be removed during uninstall. + + PKGCACHE="${EROOT}/usr/$(get_libdir)/${P}/package.conf.d/package.cache" + rm -rf "${PKGCACHE}" + + cp -p "${PKGCACHE}"{.shipped,} +} -- cgit v1.2.3-65-gdbad