Commit c774b28f authored by Herbert Valerio Riedel's avatar Herbert Valerio Riedel 🕺

Implement new integer-gmp2 from scratch (re #9281)

This is done as a separate `integer-gmp2` backend library because it
turned out to become a complete rewrite from scratch.

Due to the different (over)allocation scheme and potentially different
accounting (via the new `{shrink,resize}MutableByteArray#` primitives),
some of the nofib benchmarks actually results in increased allocation
numbers (but not necessarily an increase in runtime!).  I believe the
allocation numbers could improve if `{resize,shrink}MutableByteArray#`
could be optimised to reallocate in-place more efficiently.

Here are the more apparent changes in the latest nofib comparision
between `integer-gmp` and `integer-gmp2`:

  ------------------------------------------------------------------
          Program     Size    Allocs   Runtime   Elapsed  TotalMem
  ------------------------------------------------------------------
              ...
       bernouilli    +1.6%    +15.3%     0.132     0.132      0.0%
              ...
     cryptarithm1    -2.2%      0.0%     -9.7%     -9.7%      0.0%
              ...
            fasta    -0.7%     -0.0%    +10.9%    +10.9%      0.0%
              ...
            kahan    +0.6%    +38.9%     0.169     0.169      0.0%
              ...
             lcss    -0.7%     -0.0%     -6.4%     -6.4%      0.0%
              ...
           mandel    +1.6%    +33.6%     0.049     0.049      0.0%
              ...
         pidigits    +0.8%     +8.5%     +3.9%     +3.9%      0.0%
            power    +1.4%    -23.8%    -18.6%    -18.6%    -16.7%
              ...
        primetest    +1.3%    +50.1%     0.085     0.085      0.0%
              ...
              rsa    +1.6%    +53.4%     0.026     0.026      0.0%
              ...
              scs    +1.2%     +6.6%     +6.5%     +6.6%    +14.3%
              ...
           symalg    +1.0%     +9.5%     0.010     0.010      0.0%
              ...
        transform    -0.6%     -0.0%     -5.9%     -5.9%      0.0%
              ...
  ------------------------------------------------------------------
              Min    -2.3%    -23.8%    -18.6%    -18.6%    -16.7%
              Max    +1.6%    +53.4%    +10.9%    +10.9%    +14.3%
   Geometric Mean    -0.3%     +1.9%     -0.8%     -0.8%     +0.0%

(see P35 / https://phabricator.haskell.org/P35 for full report)

By default, `INTEGER_LIBRARY=integer-gmp2` is active now, which results
in the package `integer-gmp-1.0.0.0` being registered in the package db.
The previous `integer-gmp-0.5.1.0` can be restored by setting
`INTEGER_LIBRARY=integer-gmp` (but will probably be removed altogether
for GHC 7.12). In-tree GMP support has been stolen from the old
`integer-gmp` (while unpatching the custom memory-allocators, as well as
forcing `-fPIC`)

A minor hack to `ghc-cabal` was necessary in order to support two different
`integer-gmp` packages (in different folders) with the same package key.

There will be a couple of follow-up commits re-implementing some features
that were dropped to keep D82 minimal, as well as further
clean-ups/improvements.

More information can be found via #9281 and
https://ghc.haskell.org/trac/ghc/wiki/Design/IntegerGmp2

Reviewed By: austin, rwbarton, simonmar

Differential Revision: https://phabricator.haskell.org/D82
parent fcfc87dc
......@@ -380,7 +380,12 @@ integerPackageKey, primPackageKey,
thPackageKey, dphSeqPackageKey, dphParPackageKey,
mainPackageKey, thisGhcPackageKey, interactivePackageKey :: PackageKey
primPackageKey = fsToPackageKey (fsLit "ghc-prim")
integerPackageKey = fsToPackageKey (fsLit cIntegerLibrary)
integerPackageKey = fsToPackageKey (fsLit n)
where
n = case cIntegerLibraryType of
IntegerGMP -> "integer-gmp"
IntegerGMP2 -> "integer-gmp"
IntegerSimple -> "integer-simple"
basePackageKey = fsToPackageKey (fsLit "base")
rtsPackageKey = fsToPackageKey (fsLit "rts")
thPackageKey = fsToPackageKey (fsLit "template-haskell")
......
......@@ -1123,7 +1123,8 @@ lookupIntegerSDataConName :: DynFlags -> HscEnv -> IO (Maybe DataCon)
lookupIntegerSDataConName dflags hsc_env = case cIntegerLibraryType of
IntegerGMP -> guardIntegerUse dflags $ liftM Just $
initTcForLookup hsc_env (tcLookupDataCon integerSDataConName)
IntegerGMP2-> guardIntegerUse dflags $ liftM Just $
initTcForLookup hsc_env (tcLookupDataCon integerSDataConName)
IntegerSimple -> return Nothing
-- | Helper for 'lookupMkIntegerName' and 'lookupIntegerSDataConName'
......
......@@ -53,8 +53,10 @@ compiler/stage%/build/Config.hs : mk/config.mk mk/project.mk | $$(dir $$@)/.
@echo >> $@
@echo '#include "ghc_boot_platform.h"' >> $@
@echo >> $@
@echo 'data IntegerLibrary = IntegerGMP | IntegerSimple' >> $@
@echo ' deriving Eq' >> $@
@echo 'data IntegerLibrary = IntegerGMP' >> $@
@echo ' | IntegerGMP2' >> $@
@echo ' | IntegerSimple' >> $@
@echo ' deriving Eq' >> $@
@echo >> $@
@echo 'cBuildPlatformString :: String' >> $@
@echo 'cBuildPlatformString = BuildPlatform_NAME' >> $@
......@@ -84,6 +86,8 @@ compiler/stage%/build/Config.hs : mk/config.mk mk/project.mk | $$(dir $$@)/.
@echo 'cIntegerLibraryType :: IntegerLibrary' >> $@
ifeq "$(INTEGER_LIBRARY)" "integer-gmp"
@echo 'cIntegerLibraryType = IntegerGMP' >> $@
else ifeq "$(INTEGER_LIBRARY)" "integer-gmp2"
@echo 'cIntegerLibraryType = IntegerGMP2' >> $@
else ifeq "$(INTEGER_LIBRARY)" "integer-simple"
@echo 'cIntegerLibraryType = IntegerSimple' >> $@
else ifneq "$(CLEANING)" "YES"
......
......@@ -356,6 +356,7 @@ basicKnownKeyNames
, ghciIoClassName, ghciStepIoMName
] ++ case cIntegerLibraryType of
IntegerGMP -> [integerSDataConName]
IntegerGMP2 -> [integerSDataConName]
IntegerSimple -> []
genericTyConNames :: [Name]
......@@ -936,6 +937,7 @@ integerTyConName = tcQual gHC_INTEGER_TYPE (fsLit "Integer") int
integerSDataConName = conName gHC_INTEGER_TYPE (fsLit n) integerSDataConKey
where n = case cIntegerLibraryType of
IntegerGMP -> "S#"
IntegerGMP2 -> "S#"
IntegerSimple -> panic "integerSDataConName evaluated for integer-simple"
mkIntegerName = varQual gHC_INTEGER_TYPE (fsLit "mkInteger") mkIntegerIdKey
integerToWord64Name = varQual gHC_INTEGER_TYPE (fsLit "integerToWord64") integerToWord64IdKey
......
......@@ -590,7 +590,9 @@ libraries/ghc-prim_dist-install_EXTRA_HADDOCK_SRCS = libraries/ghc-prim/dist-ins
ifneq "$(CLEANING)" "YES"
ifeq "$(INTEGER_LIBRARY)" "integer-gmp"
libraries/base_dist-install_CONFIGURE_OPTS += --flags=-integer-simple
libraries/base_dist-install_CONFIGURE_OPTS += --flags=integer-gmp
else ifeq "$(INTEGER_LIBRARY)" "integer-gmp2"
libraries/base_dist-install_CONFIGURE_OPTS += --flags=integer-gmp2
else ifeq "$(INTEGER_LIBRARY)" "integer-simple"
libraries/base_dist-install_CONFIGURE_OPTS += --flags=integer-simple
else
......@@ -657,6 +659,12 @@ BUILD_DIRS += libraries/integer-gmp/gmp
BUILD_DIRS += libraries/integer-gmp/mkGmpDerivedConstants
endif
ifeq "$(INTEGER_LIBRARY)" "integer-gmp2"
BUILD_DIRS += libraries/integer-gmp2/gmp
else ifneq "$(findstring clean,$(MAKECMDGOALS))" ""
BUILD_DIRS += libraries/integer-gmp2/gmp
endif
BUILD_DIRS += utils/haddock
BUILD_DIRS += utils/haddock/doc
BUILD_DIRS += compiler
......@@ -1212,6 +1220,7 @@ sdist_%:
CLEAN_FILES += libraries/bootstrapping.conf
CLEAN_FILES += libraries/integer-gmp/cbits/GmpDerivedConstants.h
CLEAN_FILES += libraries/integer-gmp/include/HsIntegerGmp.h
CLEAN_FILES += libraries/integer-gmp2/include/HsIntegerGmp.h
CLEAN_FILES += libraries/base/include/EventConfig.h
CLEAN_FILES += mk/config.mk.old
CLEAN_FILES += mk/project.mk.old
......
......@@ -27,7 +27,11 @@ import GHC.Show
import {-# SOURCE #-} GHC.Exception( divZeroException, overflowException, ratioZeroDenomException )
#ifdef OPTIMISE_INTEGER_GCD_LCM
# if defined(MIN_VERSION_integer_gmp) || defined(MIN_VERSION_integer_gmp2)
import GHC.Integer.GMP.Internals
# else
# error unsupported OPTIMISE_INTEGER_GCD_LCM configuration
# endif
#endif
infixr 8 ^, ^^
......
......@@ -44,6 +44,18 @@ source-repository head
Flag integer-simple
Description: Use integer-simple
Manual: True
Default: False
Flag integer-gmp
Description: Use integer-gmp
Manual: True
Default: False
Flag integer-gmp2
Description: Use integer-gmp2
Manual: True
Default: False
Library
default-language: Haskell2010
......@@ -90,10 +102,15 @@ Library
build-depends: rts == 1.0.*, ghc-prim >= 0.3.1 && < 0.4
if flag(integer-simple)
build-depends: integer-simple >= 0.1.1 && < 0.2
else
if flag(integer-gmp)
build-depends: integer-gmp >= 0.5.1 && < 0.6
cpp-options: -DOPTIMISE_INTEGER_GCD_LCM
if flag(integer-gmp2)
build-depends: integer-gmp >= 1.0 && < 1.1
cpp-options: -DOPTIMISE_INTEGER_GCD_LCM
exposed-modules:
Control.Applicative
Control.Arrow
......
/GNUmakefile
/autom4te.cache/
/config.log
/config.status
/configure
/dist-install/
/ghc.mk
/gmp/config.mk
/include/HsIntegerGmp.h
/integer-gmp.buildinfo
/gmp/gmp.h
/gmp/gmpbuild
Copyright (c) 2014, Herbert Valerio Riedel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Herbert Valerio Riedel nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
module Main (main) where
import Distribution.Simple
main :: IO ()
main = defaultMainWithHooks autoconfUserHooks
dnl--------------------------------------------------------------------
dnl * Check whether this machine has gmp/gmp3 installed
dnl--------------------------------------------------------------------
AC_DEFUN([LOOK_FOR_GMP_LIB],[
if test "$HaveFrameworkGMP" = "NO"
then
AC_CHECK_LIB([gmp], [__gmpz_powm],
[HaveLibGmp=YES; GMP_LIBS=gmp])
if test "$HaveLibGmp" = "NO"
then
AC_CHECK_LIB([gmp3], [__gmpz_powm],
[HaveLibGmp=YES; GMP_LIBS=gmp3])
fi
if test "$HaveLibGmp" = "YES"
then
AC_CHECK_LIB([$GMP_LIBS], [__gmpz_powm_sec],
[HaveSecurePowm=1])
fi
fi
])
dnl--------------------------------------------------------------------
dnl * Mac OS X only: check for GMP.framework
dnl--------------------------------------------------------------------
AC_DEFUN([LOOK_FOR_GMP_FRAMEWORK],[
if test "$HaveLibGmp" = "NO"
then
case $target_os in
darwin*)
AC_MSG_CHECKING([for GMP.framework])
save_libs="$LIBS"
LIBS="-framework GMP"
AC_TRY_LINK_FUNC(__gmpz_powm_sec,
[HaveFrameworkGMP=YES; GMP_FRAMEWORK=GMP])
LIBS="$save_libs"
AC_MSG_RESULT([$HaveFrameworkGMP])
;;
esac
fi
])
#define _ISOC99_SOURCE
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <float.h>
#include <stdio.h>
#include <gmp.h>
#include "HsFFI.h"
#include "MachDeps.h"
#if (GMP_NUMB_BITS) != (GMP_LIMB_BITS)
# error GMP_NUMB_BITS != GMP_LIMB_BITS not supported
#endif
#if (WORD_SIZE_IN_BITS) != (GMP_LIMB_BITS)
# error WORD_SIZE_IN_BITS != GMP_LIMB_BITS not supported
#endif
// sanity check
#if (SIZEOF_HSWORD*8) != WORD_SIZE_IN_BITS
# error (SIZEOF_HSWORD*8) != WORD_SIZE_IN_BITS
#endif
/* Perform arithmetic right shift on MPNs (multi-precision naturals)
*
* pre-conditions:
* - 0 < count < sn*GMP_NUMB_BITS
* - rn = sn - floor(count / GMP_NUMB_BITS)
* - sn > 0
*
* write {sp,sn} right-shifted by count bits into {rp,rn}
*
* return value: most-significant limb stored in {rp,rn} result
*/
mp_limb_t
integer_gmp_mpn_rshift (mp_limb_t rp[], const mp_limb_t sp[], mp_size_t sn,
mp_bitcnt_t count)
{
const mp_size_t limb_shift = count / GMP_NUMB_BITS;
const unsigned int bit_shift = count % GMP_NUMB_BITS;
const mp_size_t rn = sn - limb_shift;
if (bit_shift)
mpn_rshift(rp, &sp[limb_shift], rn, bit_shift);
else
memcpy(rp, &sp[limb_shift], rn*sizeof(mp_limb_t));
return rp[rn-1];
}
/* Twos-complement version of 'integer_gmp_mpn_rshift' for performing
* arithmetic right shifts on "negative" MPNs.
*
* Same pre-conditions as 'integer_gmp_mpn_rshift'
*
* This variant is needed to operate on MPNs interpreted as negative
* numbers, which require "rounding" towards minus infinity iff a
* non-zero bit is shifted out.
*/
mp_limb_t
integer_gmp_mpn_rshift_2c (mp_limb_t rp[], const mp_limb_t sp[],
const mp_size_t sn, const mp_bitcnt_t count)
{
const mp_size_t limb_shift = count / GMP_NUMB_BITS;
const unsigned int bit_shift = count % GMP_NUMB_BITS;
const mp_size_t rn = sn - limb_shift;
// whether non-zero bits were shifted out
bool nz_shift_out = false;
if (bit_shift) {
if (mpn_rshift(rp, &sp[limb_shift], rn, bit_shift))
nz_shift_out = true;
} else
memcpy(rp, &sp[limb_shift], rn*sizeof(mp_limb_t));
if (!nz_shift_out)
for (unsigned i = 0; i < limb_shift; i++)
if (sp[i]) {
nz_shift_out = true;
break;
}
// round if non-zero bits were shifted out
if (nz_shift_out)
if (mpn_add_1(rp, rp, rn, 1))
abort(); /* should never happen */
return rp[rn-1];
}
/* Perform left-shift operation on MPN
*
* pre-conditions:
* - 0 < count
* - rn = sn + ceil(count / GMP_NUMB_BITS)
* - sn > 0
*
* return value: most-significant limb stored in {rp,rn} result
*/
mp_limb_t
integer_gmp_mpn_lshift (mp_limb_t rp[], const mp_limb_t sp[],
const mp_size_t sn, const mp_bitcnt_t count)
{
const mp_size_t limb_shift = count / GMP_NUMB_BITS;
const unsigned int bit_shift = count % GMP_NUMB_BITS;
const mp_size_t rn0 = sn + limb_shift;
memset(rp, 0, limb_shift*sizeof(mp_limb_t));
if (bit_shift) {
const mp_limb_t msl = mpn_lshift(&rp[limb_shift], sp, sn, bit_shift);
rp[rn0] = msl;
return msl;
} else {
memcpy(&rp[limb_shift], sp, sn*sizeof(mp_limb_t));
return rp[rn0-1];
}
}
/*
*
* sign of mp_size_t argument controls sign of converted double
*/
HsDouble
integer_gmp_mpn_get_d (const mp_limb_t sp[], const mp_size_t sn,
const HsInt exponent)
{
if (sn == 0)
return 0.0; // should not happen
if (sn == 1 && sp[0] == 0)
return 0.0;
__mpz_struct const mpz = {
._mp_alloc = abs(sn),
._mp_size = sn,
._mp_d = (mp_limb_t*)sp
};
if (!exponent)
return mpz_get_d(&mpz);
long e = 0;
double d = mpz_get_d_2exp (&e, &mpz);
// TODO: over/underflow handling?
return ldexp(d, e+exponent);
}
mp_limb_t
integer_gmp_gcd_word(const mp_limb_t x, const mp_limb_t y)
{
if (!x) return y;
if (!y) return x;
return mpn_gcd_1(&x, 1, y);
}
mp_limb_t
integer_gmp_mpn_gcd_1(const mp_limb_t x[], const mp_size_t xn,
const mp_limb_t y)
{
assert (xn > 0);
assert (xn == 1 || y != 0);
if (xn == 1)
return integer_gmp_gcd_word(x[0], y);
return mpn_gcd_1(x, xn, y);
}
mp_size_t
integer_gmp_mpn_gcd(mp_limb_t r[],
const mp_limb_t x0[], const mp_size_t xn,
const mp_limb_t y0[], const mp_size_t yn)
{
assert (xn >= yn);
assert (yn > 0);
assert (xn == yn || yn > 1 || y0[0] != 0);
/* post-condition: rn <= xn */
if (yn == 1) {
if (y0[0]) {
r[0] = integer_gmp_mpn_gcd_1(x0, xn, y0[0]);
return 1;
} else { /* {y0,yn} == 0 */
assert (xn==yn); /* NB: redundant assertion */
memcpy(r, x0, xn*sizeof(mp_limb_t));
return xn;
}
} else {
// mpn_gcd() seems to require non-trivial normalization of its
// input arguments (which does not seem to be documented anywhere,
// see source of mpz_gcd() for more details), so we resort to just
// use mpz_gcd() which does the tiresome normalization for us at
// the cost of a few additional temporary buffer allocations in
// C-land.
const mpz_t op1 = {{
._mp_alloc = xn,
._mp_size = xn,
._mp_d = (mp_limb_t*)x0
}};
const mpz_t op2 = {{
._mp_alloc = yn,
._mp_size = yn,
._mp_d = (mp_limb_t*)y0
}};
mpz_t rop;
mpz_init (rop);
mpz_gcd(rop, op1, op2);
const mp_size_t rn = rop[0]._mp_size;
assert(rn > 0);
assert(rn <= xn);
/* the allocation/memcpy of the result can be neglectable since
mpz_gcd() already has to allocate other temporary buffers
anyway */
memcpy(r, rop[0]._mp_d, rn*sizeof(mp_limb_t));
mpz_clear(rop);
return rn;
}
}
/* Truncating (i.e. rounded towards zero) integer division-quotient of MPN */
void
integer_gmp_mpn_tdiv_q (mp_limb_t q[],
const mp_limb_t n[], const mp_size_t nn,
const mp_limb_t d[], const mp_size_t dn)
{
/* qn = 1+nn-dn; rn = dn */
assert(nn>=dn);
if (dn > 128) {
// Use temporary heap allocated throw-away buffer for MPNs larger
// than 1KiB for 64bit-sized limbs (larger than 512bytes for
// 32bit-sized limbs)
mp_limb_t *const r = malloc(dn*sizeof(mp_limb_t));
mpn_tdiv_qr(q, r, 0, n, nn, d, dn);
free (r);
} else { // allocate smaller arrays on the stack
mp_limb_t r[dn];
mpn_tdiv_qr(q, r, 0, n, nn, d, dn);
}
}
/* Truncating (i.e. rounded towards zero) integer division-remainder of MPNs */
void
integer_gmp_mpn_tdiv_r (mp_limb_t r[],
const mp_limb_t n[], const mp_size_t nn,
const mp_limb_t d[], const mp_size_t dn)
{
/* qn = 1+nn-dn; rn = dn */
assert(nn>=dn);
const mp_size_t qn = 1+nn-dn;
if (qn > 128) {
// Use temporary heap allocated throw-away buffer for MPNs larger
// than 1KiB for 64bit-sized limbs (larger than 512bytes for
// 32bit-sized limbs)
mp_limb_t *const q = malloc(qn*sizeof(mp_limb_t));
mpn_tdiv_qr(q, r, 0, n, nn, d, dn);
free (q);
} else { // allocate smaller arrays on the stack
mp_limb_t q[qn];
mpn_tdiv_qr(q, r, 0, n, nn, d, dn);
}
}
# Changelog for [`integer-gmp` package](http://hackage.haskell.org/package/integer-gmp)
## 1.0.0.0 **TBA**
* Bundled with GHC 7.10.1
* Complete rewrite of `integer-gmp`. For more details, see
https://ghc.haskell.org/trac/ghc/wiki/Design/IntegerGmp2
## 0.5.1.0 *Feb 2014*
* Bundled with GHC 7.8.1
* Improved Haddock documentation
* New [PrimBool](https://ghc.haskell.org/trac/ghc/wiki/PrimBool)
versions of comparison predicates in `GHC.Integer`:
eqInteger# :: Integer -> Integer -> Int#
geInteger# :: Integer -> Integer -> Int#
gtInteger# :: Integer -> Integer -> Int#
leInteger# :: Integer -> Integer -> Int#
ltInteger# :: Integer -> Integer -> Int#
neqInteger# :: Integer -> Integer -> Int#
* New `GHC.Integer.testBitInteger` primitive for use with `Data.Bits`
* Reduce short-lived heap allocation and try to demote `J#` back
to `S#` more aggressively. See also
[#8647](https://ghc.haskell.org/trac/ghc/ticket/8647)
for more details.
* New GMP-specific binary (de)serialization primitives added to
`GHC.Integer.GMP.Internals`:
importIntegerFromByteArray
importIntegerFromAddr
exportIntegerToAddr
exportIntegerToMutableByteArray
sizeInBaseInteger
* New GMP-implemented number-theoretic operations added to
`GHC.Integer.GMP.Internals`:
gcdExtInteger
nextPrimeInteger
testPrimeInteger
powInteger
powModInteger
powModSecInteger
recipModInteger
This diff is collapsed.
This diff is collapsed.
AC_INIT([Haskell integer (GMP)], [0.1], [libraries@haskell.org], [integer])
# Safety check: Ensure that we are in the correct source directory.
AC_CONFIG_SRCDIR([cbits/wrappers.c])
AC_CANONICAL_TARGET
AC_ARG_WITH([cc],
[C compiler],
[CC=$withval])
AC_PROG_CC()
dnl--------------------------------------------------------------------
dnl * Deal with arguments telling us gmp is somewhere odd
dnl--------------------------------------------------------------------
AC_ARG_WITH([gmp-includes],
[AC_HELP_STRING([--with-gmp-includes],
[directory containing gmp.h])],
[GMP_INCLUDE_DIRS=$withval; CPPFLAGS="-I$withval"],
[GMP_INCLUDE_DIRS=])
AC_ARG_WITH([gmp-libraries],
[AC_HELP_STRING([--with-gmp-libraries],
[directory containing gmp library])],
[GMP_LIB_DIRS=$withval; LDFLAGS="-L$withval"],
[GMP_LIB_DIRS=])
AC_ARG_WITH([gmp-framework-preferred],
[AC_HELP_STRING([--with-gmp-framework-preferred],
[on OSX, prefer the GMP framework to the gmp lib])],
[GMP_PREFER_FRAMEWORK=YES],
[GMP_PREFER_FRAMEWORK=NO])
AC_ARG_WITH([intree-gmp],
[AC_HELP_STRING([--with-intree-gmp],
[force using the in-tree GMP])],
[GMP_FORCE_INTREE=YES],
[GMP_FORCE_INTREE=NO])
dnl--------------------------------------------------------------------
dnl * Detect gmp
dnl--------------------------------------------------------------------
HaveLibGmp=NO
GMP_LIBS=
HaveFrameworkGMP=NO
GMP_FRAMEWORK=
HaveSecurePowm=0
if test "$GMP_FORCE_INTREE" != "YES"
then
if test "$GMP_PREFER_FRAMEWORK" = "YES"
then
LOOK_FOR_GMP_FRAMEWORK
LOOK_FOR_GMP_LIB
else
LOOK_FOR_GMP_LIB
LOOK_FOR_GMP_FRAMEWORK
fi
fi
if test "$HaveFrameworkGMP" = "YES" || test "$HaveLibGmp" = "YES"
then
AC_CHECK_HEADER([gmp.h], , [AC_MSG_ERROR([Cannot find gmp.h])])
fi
dnl--------------------------------------------------------------------
dnl * Make sure we got some form of gmp
dnl--------------------------------------------------------------------
AC_SUBST(GMP_INCLUDE_DIRS)
AC_SUBST(GMP_LIBS)
AC_SUBST(GMP_LIB_DIRS)
AC_SUBST(GMP_FRAMEWORK)
AC_SUBST(HaveLibGmp)
AC_SUBST(HaveFrameworkGMP)
AC_SUBST(HaveSecurePowm)
AC_CONFIG_FILES([integer-gmp.buildinfo gmp/config.mk include/HsIntegerGmp.h])
dnl--------------------------------------------------------------------
dnl * Generate the header cbits/GmpDerivedConstants.h
dnl--------------------------------------------------------------------
AC_OUTPUT
ifeq "$(HaveLibGmp)" ""
HaveLibGmp = @HaveLibGmp@
endif
ifeq "$(HaveFrameworkGMP)" ""
HaveFrameworkGMP = @HaveFrameworkGMP@
endif
GMP_INCLUDE_DIRS = @GMP_INCLUDE_DIRS@
GMP_LIB_DIRS = @GMP_LIB_DIRS@
# -----------------------------------------------------------------------------
#
# (c) 2009 The University of Glasgow
#
# This file is part of the GHC build system.
#
# To understand how the build system works and how to modify it, see
# http://ghc.haskell.org/trac/ghc/wiki/Building/Architecture
# http://ghc.haskell.org/trac/ghc/wiki/Building/Modifying
#
# -----------------------------------------------------------------------------
# We use a tarball like gmp-4.2.4-nodoc.tar.bz2, which is
# gmp-4.2.4.tar.bz2 repacked without the doc/ directory contents.
# That's because the doc/ directory contents are under the GFDL,
# which causes problems for Debian.
GMP_TARBALL := $(wildcard libraries/integer-gmp/gmp/tarball/gmp*.tar.bz2)
GMP_DIR := $(patsubst libraries/integer-gmp/gmp/tarball/%-nodoc-patched.tar.bz2,%,$(GMP_TARBALL))
ifneq "$(NO_CLEAN_GMP)" "YES"
$(eval $(call clean-target,gmp,,\
libraries/integer-gmp2/gmp/config.mk \
libraries/integer-gmp2/gmp/libgmp.a \
libraries/integer-gmp2/gmp/gmp.h \
libraries/integer-gmp2/gmp/gmpbuild \
libraries/integer-gmp2/gmp/$(GMP_DIR)))
clean : clean_gmp
.PHONY: clean_gmp
clean_gmp:
$(call removeTrees,libraries/integer-gmp2/gmp/objs)
$(call removeTrees,libraries/integer-gmp2/gmp/gmpbuild)
endif
ifeq "$(Windows_Host)" "YES"
# Apparently building on Windows fails when there is a system gmp
# available, so we never try to use the system gmp on Windows
libraries/integer-gmp2_CONFIGURE_OPTS += --configure-option=--with-intree-gmp
endif
ifeq "$(GMP_PREFER_FRAMEWORK)" "YES"
libraries/integer-gmp2_CONFIGURE_OPTS += --with-gmp-framework-preferred
endif
ifeq "$(phase)" "final"
ifeq "$(findstring clean,$(MAKECMDGOALS))" ""
include libraries/integer-gmp2/gmp/config.mk
endif