1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE RankNTypes #-}
4 -----------------------------------------------------------------------------
7 -- Module : Distribution.Simple.Register
8 -- Copyright : Isaac Jones 2003-2004
11 -- Maintainer : cabal-devel@haskell.org
12 -- Portability : portable
14 -- This module deals with registering and unregistering packages. There are a
15 -- couple ways it can do this, one is to do it directly. Another is to generate
16 -- a script that can be run later to do it. The idea here being that the user
17 -- is shielded from the details of what command to use for package registration
18 -- for a particular compiler. In practice this aspect was not especially
19 -- popular so we also provide a way to simply generate the package registration
20 -- file which then must be manually passed to @ghc-pkg@. It is possible to
21 -- generate registration information for where the package is to be installed,
22 -- or alternatively to register the package in place in the build tree. The
23 -- latter is occasionally handy, and will become more important when we try to
24 -- build multi-package systems.
26 -- This module does not delegate anything to the per-compiler modules but just
27 -- mixes it all in this module, which is rather unsatisfactory. The script
28 -- generation and the unregister feature are not well used or tested.
29 module Distribution
.Simple
.Register
32 , internalPackageDBPath
40 , HcPkg
.RegisterOptions
(..)
41 , HcPkg
.defaultRegisterOptions
42 , generateRegistrationInfo
43 , inplaceInstalledPackageInfo
44 , absoluteInstalledPackageInfo
45 , generalInstalledPackageInfo
48 import Distribution
.Compat
.Prelude
51 import Distribution
.Types
.ComponentLocalBuildInfo
52 import Distribution
.Types
.LocalBuildInfo
53 import Distribution
.Types
.TargetInfo
55 import Distribution
.Simple
.BuildPaths
56 import Distribution
.Simple
.BuildTarget
57 import Distribution
.Simple
.LocalBuildInfo
59 import qualified Distribution
.Simple
.GHC
as GHC
60 import qualified Distribution
.Simple
.GHCJS
as GHCJS
61 import qualified Distribution
.Simple
.HaskellSuite
as HaskellSuite
62 import qualified Distribution
.Simple
.PackageIndex
as Index
63 import qualified Distribution
.Simple
.UHC
as UHC
65 import Distribution
.Backpack
.DescribeUnitId
66 import Distribution
.Compat
.Graph
(IsNode
(nodeKey
))
67 import Distribution
.InstalledPackageInfo
(InstalledPackageInfo
)
68 import qualified Distribution
.InstalledPackageInfo
as IPI
69 import Distribution
.License
(licenseFromSPDX
, licenseToSPDX
)
70 import Distribution
.Package
71 import Distribution
.PackageDescription
72 import Distribution
.Pretty
73 import Distribution
.Simple
.Compiler
74 import Distribution
.Simple
.Errors
75 import Distribution
.Simple
.Flag
76 import Distribution
.Simple
.Program
77 import qualified Distribution
.Simple
.Program
.HcPkg
as HcPkg
78 import Distribution
.Simple
.Program
.Script
79 import Distribution
.Simple
.Setup
.Register
80 import Distribution
.Simple
.Utils
81 import Distribution
.System
82 import Distribution
.Utils
.MapAccum
83 import Distribution
.Verbosity
as Verbosity
84 import Distribution
.Version
85 import System
.Directory
86 import System
.FilePath (isAbsolute
, (<.>), (</>))
88 import qualified Data
.ByteString
.Lazy
.Char8
as BS
.Char8
90 -- -----------------------------------------------------------------------------
97 -- ^ Install in the user's database?; verbose
99 register pkg_descr lbi0 flags
=
100 -- Duncan originally asked for us to not register/install files
101 -- when there was no public library. But with per-component
102 -- configure, we legitimately need to install internal libraries
103 -- so that we can get them. So just unconditionally install.
107 targets
<- readTargetInfos verbosity pkg_descr lbi0
(regArgs flags
)
109 -- It's important to register in build order, because ghc-pkg
110 -- will complain if a dependency is not registered.
111 let componentsToRegister
=
112 neededTargetsInBuildOrder
' pkg_descr lbi0
(map nodeKey targets
)
115 mapAccumM `
flip` installedPkgs lbi0 `
flip` componentsToRegister
$ \index tgt
->
116 case targetComponent tgt
of
118 let clbi
= targetCLBI tgt
119 lbi
= lbi0
{installedPkgs
= index}
120 ipi
<- generateOne pkg_descr lib lbi clbi flags
121 return (Index
.insert ipi
index, Just ipi
)
122 _
-> return (index, Nothing
)
124 registerAll pkg_descr lbi0 flags
(catMaybes ipi_mbs
)
126 verbosity
= fromFlag
(regVerbosity flags
)
129 :: PackageDescription
132 -> ComponentLocalBuildInfo
134 -> IO InstalledPackageInfo
135 generateOne pkg lib lbi clbi regFlags
=
137 absPackageDBs
<- absolutePackageDBPaths packageDbs
139 generateRegistrationInfo
148 (registrationPackageDB absPackageDBs
)
149 info verbosity
(IPI
.showInstalledPackageInfo installedPkgInfo
)
150 return installedPkgInfo
152 inplace
= fromFlag
(regInPlace regFlags
)
153 reloc
= relocatable lbi
154 -- FIXME: there's really no guarantee this will work.
155 -- registering into a totally different db stack can
156 -- fail if dependencies cannot be satisfied.
160 ++ maybeToList (flagToMaybe
(regPackageDB regFlags
))
161 distPref
= fromFlag
(regDistPref regFlags
)
162 verbosity
= fromFlag
(regVerbosity regFlags
)
165 :: PackageDescription
168 -> [InstalledPackageInfo
]
170 registerAll pkg lbi regFlags ipis
=
172 when (fromFlag
(regPrintId regFlags
)) $ do
173 for_ ipis
$ \installedPkgInfo
->
174 -- Only print the public library's IPI
176 ( packageId installedPkgInfo
== packageId pkg
177 && IPI
.sourceLibName installedPkgInfo
== LMainLibName
179 $ putStrLn (prettyShow
(IPI
.installedUnitId installedPkgInfo
))
181 -- Three different modes:
184 | modeGenerateRegFile
-> writeRegistrationFileOrDirectory
185 | modeGenerateRegScript
-> writeRegisterScript
187 for_ ipis
$ \ipi
-> do
192 (CLibName
(IPI
.sourceLibName ipi
))
193 (Just
(IPI
.instantiatedWith ipi
))
200 HcPkg
.defaultRegisterOptions
202 modeGenerateRegFile
= isJust (flagToMaybe
(regGenPkgConf regFlags
))
205 (prettyShow
(packageId pkg
) <.> "conf")
206 (fromFlag
(regGenPkgConf regFlags
))
208 modeGenerateRegScript
= fromFlag
(regGenScript regFlags
)
210 -- FIXME: there's really no guarantee this will work.
211 -- registering into a totally different db stack can
212 -- fail if dependencies cannot be satisfied.
216 ++ maybeToList (flagToMaybe
(regPackageDB regFlags
))
217 verbosity
= fromFlag
(regVerbosity regFlags
)
219 writeRegistrationFileOrDirectory
= do
220 -- Handles overwriting both directory and file
221 deletePackageDB regFile
223 [installedPkgInfo
] -> do
224 info verbosity
("Creating package registration file: " ++ regFile
)
225 writeUTF8File regFile
(IPI
.showInstalledPackageInfo installedPkgInfo
)
227 info verbosity
("Creating package registration directory: " ++ regFile
)
228 createDirectory regFile
229 let num_ipis
= length ipis
230 lpad m xs
= replicate (m
- length ys
) '0' ++ ys
233 number i
= lpad
(length (show num_ipis
)) (show i
)
234 for_
(zip ([1 ..] :: [Int]) ipis
) $ \(i
, installedPkgInfo
) ->
236 (regFile
</> (number i
++ "-" ++ prettyShow
(IPI
.installedUnitId installedPkgInfo
)))
237 (IPI
.showInstalledPackageInfo installedPkgInfo
)
239 writeRegisterScript
=
240 case compilerFlavor
(compiler lbi
) of
241 UHC
-> notice verbosity
"Registration scripts not needed for uhc"
245 "Registration scripts are not implemented for this compiler"
248 (writeHcPkgRegisterScript verbosity ipis packageDbs
)
250 generateRegistrationInfo
252 -> PackageDescription
255 -> ComponentLocalBuildInfo
260 -> IO InstalledPackageInfo
261 generateRegistrationInfo verbosity pkg lib lbi clbi inplace reloc distPref packageDb
= do
262 -- TODO: eliminate pwd!
263 pwd
<- getCurrentDirectory
267 then -- NB: With an inplace installation, the user may run './Setup
268 -- build' to update the library files, without reregistering.
269 -- In this case, it is critical that the ABI hash not flip.
272 ( inplaceInstalledPackageInfo
276 (mkAbiHash
"inplace")
282 abi_hash
<- abiHash verbosity pkg distPref lbi lib clbi
285 relocRegistrationInfo
295 ( absoluteInstalledPackageInfo
303 return installedPkgInfo
305 -- | Compute the 'AbiHash' of a library that we built inplace.
308 -> PackageDescription
312 -> ComponentLocalBuildInfo
314 abiHash verbosity pkg distPref lbi lib clbi
=
315 case compilerFlavor comp
of
317 fmap mkAbiHash
$ GHC
.libAbiHash verbosity pkg lbi
' lib clbi
319 fmap mkAbiHash
$ GHCJS
.libAbiHash verbosity pkg lbi
' lib clbi
320 _
-> return (mkAbiHash
"")
327 ++ [SpecificPackageDB
(internalPackageDBPath lbi distPref
)]
330 relocRegistrationInfo
332 -> PackageDescription
335 -> ComponentLocalBuildInfo
338 -> IO InstalledPackageInfo
339 relocRegistrationInfo verbosity pkg lib lbi clbi abi_hash packageDb
=
340 case (compilerFlavor
(compiler lbi
)) of
342 fs
<- GHC
.pkgRoot verbosity lbi packageDb
344 ( relocatableInstalledPackageInfo
352 _
-> dieWithException verbosity RelocRegistrationInfo
354 initPackageDB
:: Verbosity
-> Compiler
-> ProgramDb
-> FilePath -> IO ()
355 initPackageDB verbosity comp progdb dbPath
=
356 createPackageDB verbosity comp progdb
False dbPath
358 -- | Create an empty package DB at the specified location.
366 createPackageDB verbosity comp progdb preferCompat dbPath
=
367 case compilerFlavor comp
of
368 GHC
-> HcPkg
.init (GHC
.hcPkgInfo progdb
) verbosity preferCompat dbPath
369 GHCJS
-> HcPkg
.init (GHCJS
.hcPkgInfo progdb
) verbosity
False dbPath
371 HaskellSuite _
-> HaskellSuite
.initPackageDB verbosity progdb dbPath
372 _
-> dieWithException verbosity CreatePackageDB
374 doesPackageDBExist
:: FilePath -> IO Bool
375 doesPackageDBExist dbPath
= do
376 -- currently one impl for all compiler flavours, but could change if needed
377 dir_exists
<- doesDirectoryExist dbPath
380 else doesFileExist dbPath
382 deletePackageDB
:: FilePath -> IO ()
383 deletePackageDB dbPath
= do
384 -- currently one impl for all compiler flavours, but could change if needed
385 dir_exists
<- doesDirectoryExist dbPath
387 then removeDirectoryRecursive dbPath
389 file_exists
<- doesFileExist dbPath
390 when file_exists
$ removeFile dbPath
392 -- | Run @hc-pkg@ using a given package DB stack, directly forwarding the
393 -- provided command-line arguments to it.
401 invokeHcPkg verbosity comp progdb dbStack extraArgs
=
407 (\hpi
-> HcPkg
.invoke hpi verbosity dbStack extraArgs
)
414 -> (HcPkg
.HcPkgInfo
-> IO a
)
416 withHcPkg verbosity name comp progdb f
=
417 case compilerFlavor comp
of
418 GHC
-> f
(GHC
.hcPkgInfo progdb
)
419 GHCJS
-> f
(GHCJS
.hcPkgInfo progdb
)
420 _
-> dieWithException verbosity
$ WithHcPkg name
427 -> InstalledPackageInfo
428 -> HcPkg
.RegisterOptions
430 registerPackage verbosity comp progdb packageDbs installedPkgInfo registerOptions
=
431 case compilerFlavor comp
of
432 GHC
-> GHC
.registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions
433 GHCJS
-> GHCJS
.registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions
435 HaskellSuite
.registerPackage verbosity progdb packageDbs installedPkgInfo
437 | HcPkg
.registerMultiInstance registerOptions
->
438 dieWithException verbosity RegisMultiplePkgNotSupported
439 UHC
-> UHC
.registerPackage verbosity comp progdb packageDbs installedPkgInfo
440 _
-> dieWithException verbosity RegisteringNotImplemented
442 writeHcPkgRegisterScript
444 -> [InstalledPackageInfo
]
448 writeHcPkgRegisterScript verbosity ipis packageDbs hpi
= do
449 let genScript installedPkgInfo
=
451 HcPkg
.registerInvocation
456 HcPkg
.defaultRegisterOptions
457 in invocationAsSystemScript buildOS invocation
458 scripts
= map genScript ipis
459 -- TODO: Do something more robust here
460 regScript
= unlines scripts
462 info verbosity
("Creating package registration script: " ++ regScriptFileName
)
463 writeUTF8File regScriptFileName regScript
464 setFileExecutable regScriptFileName
466 regScriptFileName
:: FilePath
467 regScriptFileName
= case buildOS
of
468 Windows
-> "register.bat"
471 -- -----------------------------------------------------------------------------
472 -- Making the InstalledPackageInfo
474 -- | Construct 'InstalledPackageInfo' for a library in a package, given a set
475 -- of installation directories.
476 generalInstalledPackageInfo
477 :: ([FilePath] -> [FilePath])
478 -- ^ Translate relative include dir paths to
480 -> PackageDescription
484 -> ComponentLocalBuildInfo
485 -> InstallDirs
FilePath
486 -> InstalledPackageInfo
487 generalInstalledPackageInfo adjustRelIncDirs pkg abi_hash lib lbi clbi installDirs
=
488 IPI
.InstalledPackageInfo
489 { IPI
.sourcePackageId
= packageId pkg
490 , IPI
.installedUnitId
= componentUnitId clbi
491 , IPI
.installedComponentId_
= componentComponentId clbi
492 , IPI
.instantiatedWith
= componentInstantiatedWith clbi
493 , IPI
.sourceLibName
= libName lib
494 , IPI
.compatPackageKey
= componentCompatPackageKey clbi
495 , -- If GHC >= 8.4 we register with SDPX, otherwise with legacy license
498 then Left
$ either id licenseToSPDX
$ licenseRaw pkg
499 else Right
$ either licenseFromSPDX
id $ licenseRaw pkg
500 , IPI
.copyright
= copyright pkg
501 , IPI
.maintainer
= maintainer pkg
502 , IPI
.author
= author pkg
503 , IPI
.stability
= stability pkg
504 , IPI
.homepage
= homepage pkg
505 , IPI
.pkgUrl
= pkgUrl pkg
506 , IPI
.synopsis
= synopsis pkg
507 , IPI
.description
= description pkg
508 , IPI
.category
= category pkg
509 , IPI
.abiHash
= abi_hash
510 , IPI
.indefinite
= componentIsIndefinite clbi
511 , IPI
.exposed
= libExposed lib
512 , IPI
.exposedModules
=
513 componentExposedModules clbi
514 -- add virtual modules into the list of exposed modules for the
515 -- package database as well.
516 ++ map (\name
-> IPI
.ExposedModule name Nothing
) (virtualModules bi
)
517 , IPI
.hiddenModules
= otherModules bi
518 , IPI
.trusted
= IPI
.trusted IPI
.emptyInstalledPackageInfo
519 , IPI
.importDirs
= [libdir installDirs | hasModules
]
520 , IPI
.libraryDirs
= libdirs
521 , IPI
.libraryDirsStatic
= libdirsStatic
522 , IPI
.libraryDynDirs
= dynlibdirs
523 , IPI
.dataDir
= datadir installDirs
526 then [getHSLibraryName
(componentUnitId clbi
)]
529 ++ extraBundledLibs bi
530 , IPI
.extraLibraries
= extraLibs bi
531 , IPI
.extraLibrariesStatic
= extraLibsStatic bi
532 , IPI
.extraGHCiLibraries
= extraGHCiLibs bi
533 , IPI
.includeDirs
= absinc
++ adjustRelIncDirs relinc
534 , IPI
.includes
= includes bi
535 , IPI
.depends
= depends
536 , IPI
.abiDepends
= [] -- due to #5465
537 , IPI
.ccOptions
= [] -- Note. NOT ccOptions bi!
538 -- We don't want cc-options to be propagated
539 -- to C compilations in other packages.
540 , IPI
.cxxOptions
= [] -- Also. NOT cxxOptions bi!
541 , IPI
.ldOptions
= ldOptions bi
542 , IPI
.frameworks
= frameworks bi
543 , IPI
.frameworkDirs
= extraFrameworkDirs bi
544 , IPI
.haddockInterfaces
= [haddockdir installDirs
</> haddockName pkg
]
545 , IPI
.haddockHTMLs
= [htmldir installDirs
]
546 , IPI
.pkgRoot
= Nothing
547 , IPI
.libVisibility
= libVisibility lib
550 ghc84
= case compilerId
$ compiler lbi
of
551 CompilerId GHC v
-> v
>= mkVersion
[8, 4]
554 bi
= libBuildInfo lib
555 -- TODO: unclear what the root cause of the
556 -- duplication is, but we nub it here for now:
557 depends
= ordNub
$ map fst (componentPackageDeps clbi
)
558 (absinc
, relinc
) = partition isAbsolute
(includeDirs bi
)
559 hasModules
= not $ null (allLibModules lib clbi
)
563 ||
not (null (cSources bi
))
564 ||
not (null (asmSources bi
))
565 ||
not (null (cmmSources bi
))
566 ||
not (null (cxxSources bi
))
567 ||
(not (null (jsSources bi
)) && hasJsSupport
)
569 && not (componentIsIndefinite clbi
)
570 hasJsSupport
= case hostPlatform lbi
of
571 Platform JavaScript _
-> True
574 | hasLibrary
= libdir installDirs
: extraLibDirsStaticOrFallback
575 |
otherwise = extraLibDirsStaticOrFallback
577 -- If no static library dirs were given, the package likely makes no
578 -- distinction between fully static linking and otherwise.
579 -- Fall back to the normal library dirs in that case.
580 extraLibDirsStaticOrFallback
= case extraLibDirsStatic bi
of
581 [] -> extraLibDirs bi
583 (libdirs
, dynlibdirs
)
585 (extraLibDirs bi
, [])
586 -- the dynamic-library-dirs defaults to the library-dirs if not specified,
587 -- so this works whether the dynamic-library-dirs field is supported or not
589 | libraryDynDirSupported comp
=
590 ( libdir installDirs
: extraLibDirs bi
591 , dynlibdir installDirs
: extraLibDirs bi
594 (libdir installDirs
: dynlibdir installDirs
: extraLibDirs bi
, [])
596 -- the compiler doesn't understand the dynamic-library-dirs field so we
597 -- add the dyn directory to the "normal" list in the library-dirs field
599 -- | Construct 'InstalledPackageInfo' for a library that is in place in the
602 -- This function knows about the layout of in place packages.
603 inplaceInstalledPackageInfo
605 -- ^ top of the build tree
607 -- ^ location of the dist tree
608 -> PackageDescription
612 -> ComponentLocalBuildInfo
613 -> InstalledPackageInfo
614 inplaceInstalledPackageInfo inplaceDir distPref pkg abi_hash lib lbi clbi
=
615 generalInstalledPackageInfo
616 adjustRelativeIncludeDirs
624 adjustRelativeIncludeDirs
= concatMap $ \d
->
625 [ inplaceDir
</> d
-- local include-dir
626 , inplaceDir
</> libTargetDir
</> d
-- autogen include-dir
628 libTargetDir
= componentBuildDir lbi clbi
630 (absoluteComponentInstallDirs pkg lbi
(componentUnitId clbi
) NoCopyDest
)
631 { libdir
= inplaceDir
</> libTargetDir
632 , dynlibdir
= inplaceDir
</> libTargetDir
633 , datadir
= inplaceDir
</> dataDir pkg
634 , docdir
= inplaceDocdir
635 , htmldir
= inplaceHtmldir
636 , haddockdir
= inplaceHtmldir
638 inplaceDocdir
= inplaceDir
</> distPref
</> "doc"
639 inplaceHtmldir
= inplaceDocdir
</> "html" </> prettyShow
(packageName pkg
)
641 -- | Construct 'InstalledPackageInfo' for the final install location of a
644 -- This function knows about the layout of installed packages.
645 absoluteInstalledPackageInfo
646 :: PackageDescription
650 -> ComponentLocalBuildInfo
651 -> InstalledPackageInfo
652 absoluteInstalledPackageInfo pkg abi_hash lib lbi clbi
=
653 generalInstalledPackageInfo
654 adjustReativeIncludeDirs
662 -- For installed packages we install all include files into one dir,
663 -- whereas in the build tree they may live in multiple local dirs.
664 adjustReativeIncludeDirs _
665 |
null (installIncludes bi
) = []
666 |
otherwise = [includedir installDirs
]
667 bi
= libBuildInfo lib
668 installDirs
= absoluteComponentInstallDirs pkg lbi
(componentUnitId clbi
) NoCopyDest
670 relocatableInstalledPackageInfo
671 :: PackageDescription
675 -> ComponentLocalBuildInfo
677 -> InstalledPackageInfo
678 relocatableInstalledPackageInfo pkg abi_hash lib lbi clbi pkgroot
=
679 generalInstalledPackageInfo
680 adjustReativeIncludeDirs
688 -- For installed packages we install all include files into one dir,
689 -- whereas in the build tree they may live in multiple local dirs.
690 adjustReativeIncludeDirs _
691 |
null (installIncludes bi
) = []
692 |
otherwise = [includedir installDirs
]
693 bi
= libBuildInfo lib
696 fmap (("${pkgroot}" </>) . shortRelativePath pkgroot
) $
697 absoluteComponentInstallDirs pkg lbi
(componentUnitId clbi
) NoCopyDest
699 -- -----------------------------------------------------------------------------
702 unregister
:: PackageDescription
-> LocalBuildInfo
-> RegisterFlags
-> IO ()
703 unregister pkg lbi regFlags
= do
704 let pkgid
= packageId pkg
705 genScript
= fromFlag
(regGenScript regFlags
)
706 verbosity
= fromFlag
(regVerbosity regFlags
)
709 (registrationPackageDB
(withPackageDB lbi
))
710 (regPackageDB regFlags
)
713 HcPkg
.unregisterInvocation
722 (BS
.Char8
.pack
$ invocationAsSystemScript buildOS invocation
)
723 else runProgramInvocation verbosity invocation
724 setupMessage verbosity
"Unregistering" pkgid
727 "unregistering is only implemented for GHC and GHCJS"
732 unregScriptFileName
:: FilePath
733 unregScriptFileName
= case buildOS
of
734 Windows
-> "unregister.bat"
737 internalPackageDBPath
:: LocalBuildInfo
-> FilePath -> FilePath
738 internalPackageDBPath lbi distPref
=
739 case compilerFlavor
(compiler lbi
) of
740 UHC
-> UHC
.inplacePackageDbPath lbi
741 _
-> distPref
</> "package.conf.inplace"