summaryrefslogtreecommitdiff
path: root/configure.hs
blob: 7aa296e51289b2dae601b73edf727aa978f43cef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#! /usr/bin/env runhaskell
{- configure.hs for hmatrix
   ------------------------

    GSL and LAPACK may require auxiliary libraries which depend on OS,
    distribution, and implementation. This script tries to to find out
    the correct link command for your system.
    Suggestions and contributions are welcome.

    By default we try to link -lgsl -llapack. This works in ubuntu/debian,
    both with and without ATLAS.
    If this fails we try different sets of additional libraries which are
    known to work in some systems.

    The desired libraries can also be explicitly given by the user using cabal
    flags (e.g., -fmkl, -faccelerate) or --configure-option=link:lib1,lib2,lib3,...

-}

import System
import Data.List(isPrefixOf)
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Configure
import Distribution.PackageDescription

-- possible additional dependencies for the desired libs (by default gsl lapack)

opts = [ ""                              -- Ubuntu/Debian
       , "blas"
       , "blas cblas"
       , "cblas"
       , "gslcblas"
       , "blas gslcblas"
       , "f77blas cblas atlas gcc_s"     -- Arch Linux (older version of atlas-lapack)
       , "blas gslcblas gfortran"        -- Arch Linux with normal blas and lapack
       ]

-- compile a simple program with symbols from GSL and LAPACK with the given libs
testprog libs fmks = "echo \"#include <gsl/gsl_sf_gamma.h>\nint main(){zgesvd_(); gsl_sf_gamma(5);}\""
                     ++" > /tmp/dummy.c; gcc /tmp/dummy.c -o /tmp/dummy "
                     ++ f1 libs ++ " " ++ f2 fmks ++ " > /dev/null 2> /dev/null"

f1 = unwords . map ("-l"++) . words
f2 = unwords . map ("-framework "++) . words

check libs fmks = (ExitSuccess ==) `fmap` system (testprog libs fmks)

-- simple test for GSL
testGSL = "echo \"#include <gsl/gsl_sf_gamma.h>\nint main(){gsl_sf_gamma(5);}\""
           ++" > /tmp/dummy.c; gcc /tmp/dummy.c -o /tmp/dummy -lgsl -lgslcblas"
           ++ " > /dev/null 2> /dev/null"

checkGSL = (ExitSuccess ==) `fmap` system (testGSL)

-- test different configurations until the first one works
try _ _ [] = return Nothing
try b f (opt:rest) = do
    ok <- check (b ++ " " ++ opt) f
    if ok then return (Just opt)
          else try b f rest

-- read --configure-option=link:lib1,lib2,lib3,etc
linkop = "link:"
getUserLink = concatMap (g . drop (length linkop)) . filter (isPrefixOf linkop)
    where g = map cs
          cs ',' = ' '
          cs x   = x

main = do
    putStr "Checking foreign libraries..."

    args <- getArgs
    Just bInfo <- maybeGetPersistBuildConfig "dist"

    let Just lib = library . localPkgDescr $ bInfo
        base = unwords . extraLibs . libBuildInfo $ lib
        fwks = unwords . frameworks . libBuildInfo $ lib
        auxpref = getUserLink args

    -- We extract the desired libs from hmatrix.cabal (using a cabal flags)
    -- and from a posible --configure-option=link:lib1,lib2,lib3
    -- by default the desired libs are gsl lapack.

    let pref = if null (words (base ++ " " ++ auxpref)) then "gsl lapack" else auxpref
        fullOpts = map ((pref++" ")++) opts

    r <- try base fwks fullOpts
    case r of
        Nothing -> do
            putStrLn " FAIL"
            g <- checkGSL
            if g
                then putStrLn " *** Sorry, I can't link LAPACK."
                else putStrLn " *** Sorry, I can't link GSL."
            putStrLn " *** Please make sure that the appropriate -dev packages are installed."
            putStrLn " *** You can also specify the required libraries using"
            putStrLn " *** cabal install hmatrix --configure-option=link:lib1,lib2,lib3,etc."
            writeFile "hmatrix.buildinfo" ("buildable: False\n")
        Just ops -> do
            putStrLn " OK"
            writeFile "hmatrix.buildinfo" ("extra-libraries: " ++ ops++"\n")