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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
{-
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,...
-}
module Config(config) where
import System.Process
import System.Exit
import System.Environment
import System.Directory(createDirectoryIfMissing)
import Data.List(isPrefixOf, intercalate)
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"
, "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 bInfo buildInfo libs fmks =
"echo \"#include <gsl/gsl_sf_gamma.h>\nint main(){zgesvd_(); gsl_sf_gamma(5);}\""
++" > " ++ (buildDir bInfo) ++ "/dummy.c; gcc "
++ (join $ ccOptions buildInfo) ++ " "
++ (join $ cppOptions buildInfo) ++ " "
++ (join $ map ("-I"++) $ includeDirs buildInfo) ++ " "
++ (buildDir bInfo) ++ "/dummy.c -o "
++ (buildDir bInfo) ++ "/dummy "
++ (join $ map ("-L"++) $ extraLibDirs buildInfo) ++ " "
++ (prepend "-l" $ libs) ++ " "
++ (prepend "-framework " fmks) ++ " > /dev/null 2> /dev/null"
join = intercalate " "
prepend x = unwords . map (x++) . words
check bInfo buildInfo libs fmks = (ExitSuccess ==) `fmap` system (testprog bInfo buildInfo libs fmks)
-- simple test for GSL
gsl bInfo buildInfo = "echo \"#include <gsl/gsl_sf_gamma.h>\nint main(){gsl_sf_gamma(5);}\""
++" > " ++ (buildDir bInfo) ++ "/dummy.c; gcc "
++ (join $ ccOptions buildInfo) ++ " "
++ (join $ cppOptions buildInfo) ++ " "
++ (join $ map ("-I"++) $ includeDirs buildInfo) ++ " "
++ (buildDir bInfo) ++ "/dummy.c -o "
++ (buildDir bInfo) ++ "/dummy "
++ (join $ map ("-L"++) $ extraLibDirs buildInfo) ++ " -lgsl -lgslcblas"
++ " > /dev/null 2> /dev/null"
-- test for gsl >= 1.12
gsl112 bInfo buildInfo =
"echo \"#include <gsl/gsl_sf_exp.h>\nint main(){gsl_sf_exprel_n_CF_e(1,1,0);}\""
++" > " ++ (buildDir bInfo) ++ "/dummy.c; gcc "
++ (buildDir bInfo) ++ "/dummy.c "
++ (join $ ccOptions buildInfo) ++ " "
++ (join $ cppOptions buildInfo) ++ " "
++ (join $ map ("-I"++) $ includeDirs buildInfo)
++" -o " ++ (buildDir bInfo) ++ "/dummy "
++ (join $ map ("-L"++) $ extraLibDirs buildInfo) ++ " -lgsl -lgslcblas"
++ " > /dev/null 2> /dev/null"
checkCommand c = (ExitSuccess ==) `fmap` system c
-- test different configurations until the first one works
try _ _ _ _ [] = return Nothing
try l i b f (opt:rest) = do
ok <- check l i (b ++ " " ++ opt) f
if ok then return (Just opt)
else try l i 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
config = do
info <- maybeGetPersistBuildConfig "dist"
case info of
Nothing -> putStrLn "Please run \"cabal clean\" first." >> exitFailure
Just bInfo -> mainOk bInfo
mainOk bInfo = do
putStr "Checking foreign libraries..."
args <- getArgs
let Just lib = library . localPkgDescr $ bInfo
buildInfo = libBuildInfo lib
base = unwords . extraLibs $ buildInfo
fwks = unwords . frameworks $ buildInfo
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
-- create the build directory (used for tmp files) if necessary
createDirectoryIfMissing True $ buildDir bInfo
r <- try bInfo buildInfo base fwks fullOpts
case r of
Nothing -> do
putStrLn " FAIL"
g <- checkCommand $ gsl bInfo buildInfo
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"
g <- checkCommand $ gsl112 bInfo buildInfo
writeFile "hmatrix.buildinfo" $ "extra-libraries: " ++
ops ++ "\n" ++
if g
then ""
else "cc-options: -DGSL110\n"
|