2 {-# LANGUAGE DeriveDataTypeable #-}
3 {-# LANGUAGE DeriveFunctor #-}
4 {-# LANGUAGE DeriveGeneric #-}
5 {-# LANGUAGE FlexibleContexts #-}
6 {-# LANGUAGE RankNTypes #-}
8 -----------------------------------------------------------------------------
11 -- Module : Distribution.Simple.InstallDirs
12 -- Copyright : Isaac Jones 2003-2004
15 -- Maintainer : cabal-devel@haskell.org
16 -- Portability : portable
18 -- This manages everything to do with where files get installed (though does
19 -- not get involved with actually doing any installation). It provides an
20 -- 'InstallDirs' type which is a set of directories for where to install
21 -- things. It also handles the fact that we use templates in these install
22 -- dirs. For example most install dirs are relative to some @$prefix@ and by
23 -- changing the prefix all other dirs still end up changed appropriately. So it
24 -- provides a 'PathTemplate' type and functions for substituting for these
26 module Distribution
.Simple
.InstallDirs
34 , prefixRelativeInstallDirs
35 , substituteInstallDirTemplates
37 , PathTemplateVariable
(..)
43 , initialPathTemplateEnv
48 , installDirsTemplateEnv
51 import Distribution
.Compat
.Prelude
54 import Distribution
.Compat
.Environment
(lookupEnv
)
55 import Distribution
.Compiler
56 import Distribution
.Package
57 import Distribution
.Pretty
58 import Distribution
.Simple
.InstallDirs
.Internal
59 import Distribution
.System
61 import System
.Directory
(getAppUserDataDirectory
)
62 import System
.FilePath
70 #ifdef mingw32_HOST_OS
71 import qualified Prelude
76 -- ---------------------------------------------------------------------------
77 -- Installation directories
79 -- | The directories where we will install files for packages.
81 -- We have several different directories for different types of files since
82 -- many systems have conventions whereby different types of files in a package
83 -- are installed in different directories. This is particularly the case on
84 -- Unix style systems.
85 data InstallDirs dir
= InstallDirs
92 -- ^ foreign libraries
94 , libexecsubdir
:: dir
104 deriving (Eq
, Read, Show, Functor
, Generic
, Typeable
)
106 instance Binary dir
=> Binary
(InstallDirs dir
)
107 instance Structured dir
=> Structured
(InstallDirs dir
)
109 instance (Semigroup dir
, Monoid dir
) => Monoid
(InstallDirs dir
) where
113 instance Semigroup dir
=> Semigroup
(InstallDirs dir
) where
121 combineInstallDirs combine a b
=
123 { prefix
= prefix a `combine` prefix b
124 , bindir
= bindir a `combine` bindir b
125 , libdir
= libdir a `combine` libdir b
126 , libsubdir
= libsubdir a `combine` libsubdir b
127 , dynlibdir
= dynlibdir a `combine` dynlibdir b
128 , flibdir
= flibdir a `combine` flibdir b
129 , libexecdir
= libexecdir a `combine` libexecdir b
130 , libexecsubdir
= libexecsubdir a `combine` libexecsubdir b
131 , includedir
= includedir a `combine` includedir b
132 , datadir
= datadir a `combine` datadir b
133 , datasubdir
= datasubdir a `combine` datasubdir b
134 , docdir
= docdir a `combine` docdir b
135 , mandir
= mandir a `combine` mandir b
136 , htmldir
= htmldir a `combine` htmldir b
137 , haddockdir
= haddockdir a `combine` haddockdir b
138 , sysconfdir
= sysconfdir a `combine` sysconfdir b
141 appendSubdirs
:: (a
-> a
-> a
) -> InstallDirs a
-> InstallDirs a
142 appendSubdirs append dirs
=
144 { libdir
= libdir dirs `append` libsubdir dirs
145 , libexecdir
= libexecdir dirs `append` libexecsubdir dirs
146 , datadir
= datadir dirs `append` datasubdir dirs
147 , libsubdir
= error "internal error InstallDirs.libsubdir"
148 , libexecsubdir
= error "internal error InstallDirs.libexecsubdir"
149 , datasubdir
= error "internal error InstallDirs.datasubdir"
152 -- | The installation directories in terms of 'PathTemplate's that contain
155 -- The defaults for most of the directories are relative to each other, in
156 -- particular they are all relative to a single prefix. This makes it
157 -- convenient for the user to override the default installation directory
158 -- by only having to specify --prefix=... rather than overriding each
159 -- individually. This is done by allowing $-style variables in the dirs.
160 -- These are expanded by textual substitution (see 'substPathTemplate').
162 -- A few of these installation directories are split into two components, the
163 -- dir and subdir. The full installation path is formed by combining the two
164 -- together with @\/@. The reason for this is compatibility with other Unix
165 -- build systems which also support @--libdir@ and @--datadir@. We would like
166 -- users to be able to configure @--libdir=\/usr\/lib64@ for example but
167 -- because by default we want to support installing multiple versions of
168 -- packages and building the same package for multiple compilers we append the
169 -- libsubdir to get: @\/usr\/lib64\/$libname\/$compiler@.
171 -- An additional complication is the need to support relocatable packages on
172 -- systems which support such things, like Windows.
173 type InstallDirTemplates
= InstallDirs PathTemplate
175 -- ---------------------------------------------------------------------------
176 -- Default installation directories
178 defaultInstallDirs
:: CompilerFlavor
-> Bool -> Bool -> IO InstallDirTemplates
179 defaultInstallDirs
= defaultInstallDirs
' False
182 :: Bool {- use external internal deps -}
186 -> IO InstallDirTemplates
187 defaultInstallDirs
' True comp userInstall hasLibs
= do
188 dflt
<- defaultInstallDirs
' False comp userInstall hasLibs
189 -- Be a bit more hermetic about per-component installs
192 { datasubdir
= toPathTemplate
$ "$abi" </> "$libname"
193 , docdir
= toPathTemplate
$ "$datadir" </> "doc" </> "$abi" </> "$libname"
195 defaultInstallDirs
' False comp userInstall _hasLibs
= do
199 mDir
<- lookupEnv
"CABAL_DIR"
201 Nothing
-> getAppUserDataDirectory
"cabal"
202 Just dir
-> return dir
205 windowsProgramFilesDir
<- getWindowsProgramFilesDir
206 return (windowsProgramFilesDir
</> "Haskell")
207 Haiku
-> return "/boot/system/non-packaged"
208 _
-> return "/usr/local"
211 Windows
-> return "$prefix"
212 _
-> return ("$prefix" </> "lib")
214 fmap toPathTemplate
$
216 { prefix
= installPrefix
217 , bindir
= "$prefix" </> "bin"
218 , libdir
= installLibDir
219 , libsubdir
= case comp
of
221 _other
-> "$abi" </> "$libname"
223 "$libdir" </> case comp
of
226 , libexecsubdir
= "$abi" </> "$pkgid"
227 , flibdir
= "$libdir"
228 , libexecdir
= case buildOS
of
229 Windows
-> "$prefix" </> "$libname"
231 _other
-> "$prefix" </> "libexec"
232 , includedir
= case buildOS
of
233 Haiku
-> "$prefix" </> "develop" </> "headers"
234 _other
-> "$libdir" </> "$libsubdir" </> "include"
235 , datadir
= case buildOS
of
237 Haiku
-> "$prefix" </> "data"
238 _other
-> "$prefix" </> "share"
239 , datasubdir
= "$abi" </> "$pkgid"
240 , docdir
= case buildOS
of
241 Haiku
-> "$prefix" </> "documentation"
242 _other
-> "$datadir" </> "doc" </> "$abi" </> "$pkgid"
243 , mandir
= case buildOS
of
244 Haiku
-> "$docdir" </> "man"
245 _other
-> "$datadir" </> "man"
246 , htmldir
= "$docdir" </> "html"
247 , haddockdir
= "$htmldir"
248 , sysconfdir
= case buildOS
of
249 Haiku
-> "boot" </> "system" </> "settings"
250 _other
-> "$prefix" </> "etc"
253 -- ---------------------------------------------------------------------------
254 -- Converting directories, absolute or prefix-relative
256 -- | Substitute the install dir templates into each other.
258 -- To prevent cyclic substitutions, only some variables are allowed in
259 -- particular dir templates. If out of scope vars are present, they are not
260 -- substituted for. Checking for any remaining unsubstituted vars can be done
261 -- as a subsequent operation.
263 -- The reason it is done this way is so that in 'prefixRelativeInstallDirs' we
264 -- can replace 'prefix' with the 'PrefixVar' and get resulting
265 -- 'PathTemplate's that still have the 'PrefixVar' in them. Doing this makes it
266 -- each to check which paths are relative to the $prefix.
267 substituteInstallDirTemplates
269 -> InstallDirTemplates
270 -> InstallDirTemplates
271 substituteInstallDirTemplates env dirs
= dirs
'
275 { -- So this specifies exactly which vars are allowed in each template
276 prefix
= subst prefix
[]
277 , bindir
= subst bindir
[prefixVar
]
278 , libdir
= subst libdir
[prefixVar
, bindirVar
]
279 , libsubdir
= subst libsubdir
[]
280 , dynlibdir
= subst dynlibdir
[prefixVar
, bindirVar
, libdirVar
]
281 , flibdir
= subst flibdir
[prefixVar
, bindirVar
, libdirVar
]
282 , libexecdir
= subst libexecdir prefixBinLibVars
283 , libexecsubdir
= subst libexecsubdir
[]
284 , includedir
= subst includedir prefixBinLibVars
285 , datadir
= subst datadir prefixBinLibVars
286 , datasubdir
= subst datasubdir
[]
287 , docdir
= subst docdir prefixBinLibDataVars
288 , mandir
= subst mandir
(prefixBinLibDataVars
++ [docdirVar
])
289 , htmldir
= subst htmldir
(prefixBinLibDataVars
++ [docdirVar
])
293 ( prefixBinLibDataVars
294 ++ [docdirVar
, htmldirVar
]
296 , sysconfdir
= subst sysconfdir prefixBinLibVars
298 subst dir env
' = substPathTemplate
(env
' ++ env
) (dir dirs
)
300 prefixVar
= (PrefixVar
, prefix dirs
')
301 bindirVar
= (BindirVar
, bindir dirs
')
302 libdirVar
= (LibdirVar
, libdir dirs
')
303 libsubdirVar
= (LibsubdirVar
, libsubdir dirs
')
304 datadirVar
= (DatadirVar
, datadir dirs
')
305 datasubdirVar
= (DatasubdirVar
, datasubdir dirs
')
306 docdirVar
= (DocdirVar
, docdir dirs
')
307 htmldirVar
= (HtmldirVar
, htmldir dirs
')
308 prefixBinLibVars
= [prefixVar
, bindirVar
, libdirVar
, libsubdirVar
]
309 prefixBinLibDataVars
= prefixBinLibVars
++ [datadirVar
, datasubdirVar
]
311 -- | Convert from abstract install directories to actual absolute ones by
312 -- substituting for all the variables in the abstract paths, to get real
320 -> InstallDirs PathTemplate
321 -> InstallDirs
FilePath
322 absoluteInstallDirs pkgId libname compilerId copydest platform dirs
=
324 CopyTo destdir
-> fmap ((destdir
</>) . dropDrive
)
325 CopyToDb dbdir
-> fmap (substPrefix
"${pkgroot}" (takeDirectory dbdir
))
328 . appendSubdirs
(</>)
329 . fmap fromPathTemplate
330 $ substituteInstallDirTemplates env dirs
332 env
= initialPathTemplateEnv pkgId libname compilerId platform
333 substPrefix pre root path
334 | pre `
isPrefixOf` path
= root
++ drop (length pre
) path
337 -- | The location prefix for the /copy/ command.
341 |
-- | when using the ${pkgroot} as prefix. The CopyToDb will
342 -- adjust the paths to be relative to the provided package
343 -- database when copying / installing.
345 deriving (Eq
, Show, Generic
)
347 instance Binary CopyDest
349 -- | Check which of the paths are relative to the installation $prefix.
351 -- If any of the paths are not relative, ie they are absolute paths, then it
352 -- prevents us from making a relocatable package (also known as a \"prefix
353 -- independent\" package).
354 prefixRelativeInstallDirs
359 -> InstallDirTemplates
360 -> InstallDirs
(Maybe FilePath)
361 prefixRelativeInstallDirs pkgId libname compilerId platform dirs
=
363 . appendSubdirs combinePathTemplate
364 $ substituteInstallDirTemplates
-- substitute the path template into each other, except that we map
365 -- \$prefix back to $prefix. We're trying to end up with templates that
366 -- mention no vars except $prefix.
369 { prefix
= PathTemplate
[Variable PrefixVar
]
372 env
= initialPathTemplateEnv pkgId libname compilerId platform
374 -- If it starts with $prefix then it's relative and produce the relative
375 -- path by stripping off $prefix/ or $prefix
376 relative dir
= case dir
of
377 PathTemplate cs
-> fmap (fromPathTemplate
. PathTemplate
) (relative
' cs
)
378 relative
' (Variable PrefixVar
: Ordinary
(s
: rest
) : rest
')
379 | isPathSeparator s
= Just
(Ordinary rest
: rest
')
380 relative
' (Variable PrefixVar
: rest
) = Just rest
381 relative
' _
= Nothing
383 -- ---------------------------------------------------------------------------
386 -- | An abstract path, possibly containing variables that need to be
387 -- substituted for to get a real 'FilePath'.
388 newtype PathTemplate
= PathTemplate
[PathComponent
]
389 deriving (Eq
, Ord
, Generic
, Typeable
)
391 instance Binary PathTemplate
392 instance Structured PathTemplate
394 type PathTemplateEnv
= [(PathTemplateVariable
, PathTemplate
)]
396 -- | Convert a 'FilePath' to a 'PathTemplate' including any template vars.
397 toPathTemplate
:: FilePath -> PathTemplate
400 . fromMaybe (error $ "panic! toPathTemplate " ++ show fp
)
401 . readMaybe
-- TODO: eradicateNoParse
404 -- | Convert back to a path, any remaining vars are included
405 fromPathTemplate
:: PathTemplate
-> FilePath
406 fromPathTemplate
(PathTemplate template
) = show template
408 combinePathTemplate
:: PathTemplate
-> PathTemplate
-> PathTemplate
409 combinePathTemplate
(PathTemplate t1
) (PathTemplate t2
) =
410 PathTemplate
(t1
++ [Ordinary
[pathSeparator
]] ++ t2
)
412 substPathTemplate
:: PathTemplateEnv
-> PathTemplate
-> PathTemplate
413 substPathTemplate environment
(PathTemplate template
) =
414 PathTemplate
(concatMap subst template
)
416 subst component
@(Ordinary _
) = [component
]
417 subst component
@(Variable variable
) =
418 case lookup variable environment
of
419 Just
(PathTemplate components
) -> components
420 Nothing
-> [component
]
422 -- | The initial environment has all the static stuff but no paths
423 initialPathTemplateEnv
429 initialPathTemplateEnv pkgId libname compiler platform
=
430 packageTemplateEnv pkgId libname
431 ++ compilerTemplateEnv compiler
432 ++ platformTemplateEnv platform
433 ++ abiTemplateEnv compiler platform
435 packageTemplateEnv
:: PackageIdentifier
-> UnitId
-> PathTemplateEnv
436 packageTemplateEnv pkgId uid
=
437 [ (PkgNameVar
, PathTemplate
[Ordinary
$ prettyShow
(packageName pkgId
)])
438 , (PkgVerVar
, PathTemplate
[Ordinary
$ prettyShow
(packageVersion pkgId
)])
439 , -- Invariant: uid is actually a HashedUnitId. Hard to enforce because
440 -- it's an API change.
441 (LibNameVar
, PathTemplate
[Ordinary
$ prettyShow uid
])
442 , (PkgIdVar
, PathTemplate
[Ordinary
$ prettyShow pkgId
])
445 compilerTemplateEnv
:: CompilerInfo
-> PathTemplateEnv
446 compilerTemplateEnv compiler
=
447 [ (CompilerVar
, PathTemplate
[Ordinary
$ prettyShow
(compilerInfoId compiler
)])
450 platformTemplateEnv
:: Platform
-> PathTemplateEnv
451 platformTemplateEnv
(Platform arch os
) =
452 [ (OSVar
, PathTemplate
[Ordinary
$ prettyShow os
])
453 , (ArchVar
, PathTemplate
[Ordinary
$ prettyShow arch
])
456 abiTemplateEnv
:: CompilerInfo
-> Platform
-> PathTemplateEnv
457 abiTemplateEnv compiler
(Platform arch os
) =
466 : prettyShow
(compilerInfoId compiler
)
467 ++ case compilerInfoAbiTag compiler
of
469 AbiTag tag
-> '-' : tag
472 , (AbiTagVar
, PathTemplate
[Ordinary
$ abiTagString
(compilerInfoAbiTag compiler
)])
475 installDirsTemplateEnv
:: InstallDirs PathTemplate
-> PathTemplateEnv
476 installDirsTemplateEnv dirs
=
477 [ (PrefixVar
, prefix dirs
)
478 , (BindirVar
, bindir dirs
)
479 , (LibdirVar
, libdir dirs
)
480 , (LibsubdirVar
, libsubdir dirs
)
481 , (DynlibdirVar
, dynlibdir dirs
)
482 , (DatadirVar
, datadir dirs
)
483 , (DatasubdirVar
, datasubdir dirs
)
484 , (DocdirVar
, docdir dirs
)
485 , (HtmldirVar
, htmldir dirs
)
488 -- ---------------------------------------------------------------------------
489 -- Parsing and showing path templates:
491 -- The textual format is that of an ordinary Haskell String, eg
493 -- and this gets parsed to the internal representation as a sequence of path
494 -- spans which are either strings or variables, eg:
495 -- PathTemplate [Variable PrefixVar, Ordinary "/bin" ]
497 instance Show PathTemplate
where
498 show (PathTemplate template
) = show (show template
)
500 instance Read PathTemplate
where
502 [ (PathTemplate template
, s
')
503 |
(path
, s
') <- readsPrec p s
504 , (template
, "") <- reads path
507 -- ---------------------------------------------------------------------------
508 -- Internal utilities
510 {- FOURMOLU_DISABLE -}
511 getWindowsProgramFilesDir
:: IO FilePath
512 getWindowsProgramFilesDir
= do
513 #ifdef mingw32_HOST_OS
514 m
<- shGetFolderPath csidl_PROGRAM_FILES
518 return (fromMaybe "C:\\Program Files" m
)
519 {- FOURMOLU_ENABLE -}
521 #ifdef mingw32_HOST_OS
522 shGetFolderPath
:: CInt
-> IO (Maybe FilePath)
524 allocaArray long_path_size
$ \pPath
-> do
525 r
<- c_SHGetFolderPath nullPtr n nullPtr
0 pPath
528 else do s
<- peekCWString pPath
; return (Just s
)
530 long_path_size
= 1024 -- MAX_PATH is 260, this should be plenty
532 csidl_PROGRAM_FILES
:: CInt
533 csidl_PROGRAM_FILES
= 0x0026
534 -- csidl_PROGRAM_FILES_COMMON :: CInt
535 -- csidl_PROGRAM_FILES_COMMON = 0x002b
537 {- FOURMOLU_DISABLE -}
538 #ifdef x86_64_HOST_ARCH
539 #define CALLCONV ccall
541 #define CALLCONV stdcall
544 foreign import CALLCONV unsafe
"shlobj.h SHGetFolderPathW"
545 c_SHGetFolderPath
:: Ptr
()
552 {- FOURMOLU_ENABLE -}