Commit d2da6558 authored by Christiaan Baaij's avatar Christiaan Baaij

Add `--dynlibdir`

`--dynlibdir` indicates the directory in which dynamic libraries
are installed. By default this setting is equal to:

`$libdir/$abi`

The static libraries will still end up in:

`$libdir/$libsubdir`

With `$libsubdir/$abi` as the default directory for dynamic
libraries, dynamic libraries will by default end up in a
single shared directory (per package database). This has the
potential to reduce start-up times for dynamically linked
executable as only one RPATH per package database will be
needed.

This commit uses the functionality defined in

https://phabricator.haskell.org/D2611

to tell GHC's > 8.0.1 package database that dynamic libraries
are copied to the directories mentioned in the

`dynamic-library-dirs`

field.
parent ff4d4753
......@@ -100,6 +100,7 @@ data InstalledPackageInfo
trusted :: Bool,
importDirs :: [FilePath],
libraryDirs :: [FilePath],
libraryDynDirs :: [FilePath], -- ^ overrides 'libraryDirs'
dataDir :: FilePath,
hsLibraries :: [String],
extraLibraries :: [String],
......@@ -189,6 +190,7 @@ emptyInstalledPackageInfo
trusted = False,
importDirs = [],
libraryDirs = [],
libraryDynDirs = [],
dataDir = "",
hsLibraries = [],
extraLibraries = [],
......@@ -353,6 +355,9 @@ installedFieldDescrs = [
, listField "library-dirs"
showFilePath parseFilePathQ
libraryDirs (\xs pkg -> pkg{libraryDirs=xs})
, listField "dynamic-library-dirs"
showFilePath parseFilePathQ
libraryDynDirs (\xs pkg -> pkg{libraryDynDirs=xs})
, simpleField "data-dir"
showFilePath (parseFilePathQ Parse.<++ return "")
dataDir (\val pkg -> pkg{dataDir=val})
......
......@@ -71,7 +71,7 @@ generate pkg_descr lbi clbi =
pragmas++
"module " ++ display paths_modulename ++ " (\n"++
" version,\n"++
" getBinDir, getLibDir, getDataDir, getLibexecDir,\n"++
" getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir,\n"++
" getDataFileName, getSysconfDir\n"++
" ) where\n"++
"\n"++
......@@ -108,9 +108,10 @@ generate pkg_descr lbi clbi =
"\n\nbindirrel :: FilePath\n" ++
"bindirrel = " ++ show flat_bindirreloc ++
"\n"++
"\ngetBinDir, getLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"++
"\ngetBinDir, getLibDir, genDynLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"++
"getBinDir = "++mkGetEnvOrReloc "bindir" flat_bindirreloc++"\n"++
"getLibDir = "++mkGetEnvOrReloc "libdir" flat_libdirreloc++"\n"++
"getDynLibDir = "++mkGetEnvOrReloc "libdir" flat_dynlibdirreloc++"\n"++
"getDataDir = "++mkGetEnvOrReloc "datadir" flat_datadirreloc++"\n"++
"getLibexecDir = "++mkGetEnvOrReloc "libexecdir" flat_libexecdirreloc++"\n"++
"getSysconfDir = "++mkGetEnvOrReloc "sysconfdir" flat_sysconfdirreloc++"\n"++
......@@ -124,16 +125,18 @@ generate pkg_descr lbi clbi =
"\n"++
filename_stuff
| absolute =
"\nbindir, libdir, datadir, libexecdir, sysconfdir :: FilePath\n"++
"\nbindir, libdir, dynlibdir, datadir, libexecdir, sysconfdir :: FilePath\n"++
"\nbindir = " ++ show flat_bindir ++
"\nlibdir = " ++ show flat_libdir ++
"\ndynlibdir = " ++ show flat_dynlibdir ++
"\ndatadir = " ++ show flat_datadir ++
"\nlibexecdir = " ++ show flat_libexecdir ++
"\nsysconfdir = " ++ show flat_sysconfdir ++
"\n"++
"\ngetBinDir, getLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"++
"\ngetBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"++
"getBinDir = "++mkGetEnvOr "bindir" "return bindir"++"\n"++
"getLibDir = "++mkGetEnvOr "libdir" "return libdir"++"\n"++
"getDynLibDir = "++mkGetEnvOr "dynlibdir" "return dynlibdir"++"\n"++
"getDataDir = "++mkGetEnvOr "datadir" "return datadir"++"\n"++
"getLibexecDir = "++mkGetEnvOr "libexecdir" "return libexecdir"++"\n"++
"getSysconfDir = "++mkGetEnvOr "sysconfdir" "return sysconfdir"++"\n"++
......@@ -151,6 +154,8 @@ generate pkg_descr lbi clbi =
"getBinDir = getPrefixDirRel bindirrel\n\n"++
"getLibDir :: IO FilePath\n"++
"getLibDir = "++mkGetDir flat_libdir flat_libdirrel++"\n\n"++
"getDynLibDir :: IO FilePath\n"++
"getDynLibDir = "++mkGetDir flat_dynlibdir flat_dynlibdirrel++"\n\n"++
"getDataDir :: IO FilePath\n"++
"getDataDir = "++ mkGetEnvOr "datadir"
(mkGetDir flat_datadir flat_datadirrel)++"\n\n"++
......@@ -175,6 +180,7 @@ generate pkg_descr lbi clbi =
prefix = flat_prefix,
bindir = flat_bindir,
libdir = flat_libdir,
dynlibdir = flat_dynlibdir,
datadir = flat_datadir,
libexecdir = flat_libexecdir,
sysconfdir = flat_sysconfdir
......@@ -182,6 +188,7 @@ generate pkg_descr lbi clbi =
InstallDirs {
bindir = flat_bindirrel,
libdir = flat_libdirrel,
dynlibdir = flat_dynlibdirrel,
datadir = flat_datadirrel,
libexecdir = flat_libexecdirrel,
sysconfdir = flat_sysconfdirrel
......@@ -189,6 +196,7 @@ generate pkg_descr lbi clbi =
flat_bindirreloc = shortRelativePath flat_prefix flat_bindir
flat_libdirreloc = shortRelativePath flat_prefix flat_libdir
flat_dynlibdirreloc = shortRelativePath flat_prefix flat_dynlibdir
flat_datadirreloc = shortRelativePath flat_prefix flat_datadir
flat_libexecdirreloc = shortRelativePath flat_prefix flat_libexecdir
flat_sysconfdirreloc = shortRelativePath flat_prefix flat_sysconfdir
......
......@@ -60,6 +60,7 @@ module Distribution.Simple.Compiler (
coverageSupported,
profilingSupported,
backpackSupported,
libraryDynDirSupported,
-- * Support for profiling detail levels
ProfDetailLevel(..),
......@@ -324,6 +325,13 @@ unitIdSupported = ghcSupported "Uses unit IDs"
backpackSupported :: Compiler -> Bool
backpackSupported = ghcSupported "Support Backpack"
-- | Does this compiler support a package database entry with:
-- "dynamic-library-dirs"?
libraryDynDirSupported :: Compiler -> Bool
libraryDynDirSupported comp = case compilerFlavor comp of
GHC -> compilerVersion comp >= mkVersion [8,0,1,20161021]
_ -> False
-- | Does this compiler support Haskell program coverage?
coverageSupported :: Compiler -> Bool
coverageSupported comp =
......
......@@ -728,6 +728,7 @@ configure (pkg_descr0', pbi) cfg = do
dirinfo "Binaries" (bindir dirs) (bindir relative)
dirinfo "Libraries" (libdir dirs) (libdir relative)
dirinfo "Dynamic Libraries" (dynlibdir dirs) (dynlibdir relative)
dirinfo "Private binaries" (libexecdir dirs) (libexecdir relative)
dirinfo "Data files" (datadir dirs) (datadir relative)
dirinfo "Documentation" (docdir dirs) (docdir relative)
......
......@@ -91,6 +91,7 @@ toCurrent ipi@InstalledPackageInfo{} =
Current.trusted = Current.trusted Current.emptyInstalledPackageInfo,
Current.importDirs = importDirs ipi,
Current.libraryDirs = libraryDirs ipi,
Current.libraryDynDirs = [],
Current.dataDir = "",
Current.hsLibraries = hsLibraries ipi,
Current.extraLibraries = extraLibraries ipi,
......
......@@ -156,14 +156,10 @@ copyComponent :: Verbosity -> PackageDescription
copyComponent verbosity pkg_descr lbi (CLib lib) clbi copydest = do
let InstallDirs{
libdir = libPref,
dynlibdir = dynlibPref,
includedir = incPref
} = absoluteComponentInstallDirs pkg_descr lbi (componentUnitId clbi) copydest
buildPref = componentBuildDir lbi clbi
-- TODO: decide if we need the user to be able to control the libdir
-- for shared libs independently of the one for static libs. If so
-- it should also have a flag in the command line UI
-- For the moment use dynlibdir = libdir
dynlibPref = libPref
case libName lib of
Nothing -> notice verbosity ("Installing library in " ++ libPref)
......
......@@ -192,7 +192,11 @@ defaultInstallDirs' False comp userInstall _hasLibs = do
LHC -> "$compiler"
UHC -> "$pkgid"
_other -> "$abi" </> "$libname",
dynlibdir = "$libdir",
dynlibdir = "$libdir" </> case comp of
JHC -> "$compiler"
LHC -> "$compiler"
UHC -> "$pkgid"
_other -> "$abi",
libexecdir = case buildOS of
Windows -> "$prefix" </> "$libname"
_other -> "$prefix" </> "libexec",
......@@ -341,6 +345,7 @@ data PathTemplateVariable =
| BindirVar -- ^ The @$bindir@ path variable
| LibdirVar -- ^ The @$libdir@ path variable
| LibsubdirVar -- ^ The @$libsubdir@ path variable
| DynlibdirVar -- ^ The @$dynlibdir@ path variable
| DatadirVar -- ^ The @$datadir@ path variable
| DatasubdirVar -- ^ The @$datasubdir@ path variable
| DocdirVar -- ^ The @$docdir@ path variable
......@@ -438,6 +443,7 @@ installDirsTemplateEnv dirs =
,(BindirVar, bindir dirs)
,(LibdirVar, libdir dirs)
,(LibsubdirVar, libsubdir dirs)
,(DynlibdirVar, dynlibdir dirs)
,(DatadirVar, datadir dirs)
,(DatasubdirVar, datasubdir dirs)
,(DocdirVar, docdir dirs)
......@@ -460,6 +466,7 @@ instance Show PathTemplateVariable where
show BindirVar = "bindir"
show LibdirVar = "libdir"
show LibsubdirVar = "libsubdir"
show DynlibdirVar = "dynlibdir"
show DatadirVar = "datadir"
show DatasubdirVar = "datasubdir"
show DocdirVar = "docdir"
......@@ -488,6 +495,7 @@ instance Read PathTemplateVariable where
,("bindir", BindirVar)
,("libdir", LibdirVar)
,("libsubdir", LibsubdirVar)
,("dynlibdir", DynlibdirVar)
,("datadir", DatadirVar)
,("datasubdir", DatasubdirVar)
,("docdir", DocdirVar)
......
......@@ -266,10 +266,15 @@ depLibraryPaths inplace relative lbi clbi = do
-}
getLibDir sub_clbi
| inplace = componentBuildDir lbi sub_clbi
| otherwise = libdir (absoluteComponentInstallDirs pkgDescr lbi (componentUnitId sub_clbi) NoCopyDest)
| otherwise = dynlibdir (absoluteComponentInstallDirs pkgDescr lbi (componentUnitId sub_clbi) NoCopyDest)
let ipkgs = allPackages (installedPkgs lbi)
allDepLibDirs = concatMap Installed.libraryDirs ipkgs
-- First look for dynamic libraries in `dynamic-library-dirs`, and use
-- `library-dirs` as a fall back.
getDynDir pkg = case Installed.libraryDynDirs pkg of
[] -> Installed.libraryDirs pkg
d -> d
allDepLibDirs = concatMap getDynDir ipkgs
allDepLibDirs' = internalLibs ++ allDepLibDirs
allDepLibDirsC <- traverse canonicalizePathNoFail allDepLibDirs'
......
......@@ -397,11 +397,8 @@ generalInstalledPackageInfo adjustRelIncDirs pkg abi_hash lib lbi clbi installDi
IPI.hiddenModules = otherModules bi,
IPI.trusted = IPI.trusted IPI.emptyInstalledPackageInfo,
IPI.importDirs = [ libdir installDirs | hasModules ],
-- Note. the libsubdir and datasubdir templates have already been expanded
-- into libdir and datadir.
IPI.libraryDirs = if hasLibrary
then libdir installDirs : extraLibDirs bi
else extraLibDirs bi,
IPI.libraryDirs = libdirs,
IPI.libraryDynDirs = dynlibdirs,
IPI.dataDir = datadir installDirs,
IPI.hsLibraries = if hasLibrary
then [getHSLibraryName (componentUnitId clbi)]
......@@ -427,9 +424,24 @@ generalInstalledPackageInfo adjustRelIncDirs pkg abi_hash lib lbi clbi installDi
bi = libBuildInfo lib
(absinc, relinc) = partition isAbsolute (includeDirs bi)
hasModules = not $ null (allLibModules lib clbi)
comp = compiler lbi
hasLibrary = hasModules || not (null (cSources bi))
|| (not (null (jsSources bi)) &&
compilerFlavor (compiler lbi) == GHCJS)
compilerFlavor comp == GHCJS)
(libdirs, dynlibdirs)
| not hasLibrary
= (extraLibDirs bi, [])
-- the dynamic-library-dirs defaults to the library-dirs if not specified,
-- so this works whether the dynamic-library-dirs field is supported or not
| libraryDynDirSupported comp
= (libdir installDirs : extraLibDirs bi,
dynlibdir installDirs : extraLibDirs bi)
| otherwise
= (libdir installDirs : dynlibdir installDirs : extraLibDirs bi, [])
-- the compiler doesn't understand the dynamic-library-dirs field so we
-- add the dyn directory to the "normal" list in the library-dirs field
-- | Construct 'InstalledPackageInfo' for a library that is in place in the
-- build tree.
......@@ -453,6 +465,7 @@ inplaceInstalledPackageInfo inplaceDir distPref pkg abi_hash lib lbi clbi =
installDirs =
(absoluteComponentInstallDirs pkg lbi (componentUnitId clbi) NoCopyDest) {
libdir = inplaceDir </> libTargetDir,
dynlibdir = inplaceDir </> libTargetDir,
datadir = inplaceDir </> dataDir pkg,
docdir = inplaceDocdir,
htmldir = inplaceHtmldir,
......
......@@ -902,6 +902,11 @@ installDirsOptions =
libsubdir (\v flags -> flags { libsubdir = v })
installDirArg
, option "" ["dynlibdir"]
"installation directory for dynamic libraries"
dynlibdir (\v flags -> flags { dynlibdir = v })
installDirArg
, option "" ["libexecdir"]
"installation directory for program executables"
libexecdir (\v flags -> flags { libexecdir = v })
......
......@@ -2296,6 +2296,7 @@ into (e.g. data files live in ``getDataDir``):
getBinDir :: IO FilePath
getLibDir :: IO FilePath
getDynLibDir :: IO FilePath
getDataDir :: IO FilePath
getLibexecDir :: IO FilePath
getSysconfDir :: IO FilePath
......@@ -2304,7 +2305,7 @@ The actual location of all these directories can be individually
overridden at runtime using environment variables of the form
``pkg_name_var``, where ``pkg_name`` is the name of the package with all
hyphens converted into underscores, and ``var`` is either ``bindir``,
``libdir``, ``datadir``, ``libexedir`` or ``sysconfdir``. For example,
``libdir``, ``dynlibdir``, ``datadir``, ``libexedir`` or ``sysconfdir``. For example,
the configured data directory for ``pretty-show`` is controlled with the
``pretty_show_datadir`` environment variable.
......@@ -2551,7 +2552,7 @@ a few options:
commands are passed through as follows:
- The ``--with-hc-pkg``, ``--prefix``, ``--bindir``, ``--libdir``,
``--datadir``, ``--libexecdir`` and ``--sysconfdir`` options to
``--dynlibdir``, ``--datadir``, ``--libexecdir`` and ``--sysconfdir`` options to
the ``configure`` command are passed on to the ``configure``
script. In addition the value of the ``--with-compiler`` option is
passed in a ``--with-hc`` option and all options specified with
......@@ -2568,6 +2569,7 @@ a few options:
$(MAKE) install prefix=$(destdir)/$(prefix) \
bindir=$(destdir)/$(bindir) \
libdir=$(destdir)/$(libdir) \
dynlibdir=$(destdir)/$(dynlibdir) \
datadir=$(destdir)/$(datadir) \
libexecdir=$(destdir)/$(libexecdir) \
sysconfdir=$(destdir)/$(sysconfdir) \
......
......@@ -465,7 +465,7 @@ parameters <developing-packages.html#system-dependent-parameters>`__ or
on `complex
packages <developing-packages.html#more-complex-packages>`__), it is
passed the :option:`--with-hc-pkg`, :option:`--prefix`, :option:`--bindir`,
:option:`--libdir`, :option:`--datadir`, :option:`--libexecdir` and
:option:`--libdir`, :option:`--dynlibdir`, :option:`--datadir`, :option:`--libexecdir` and
:option:`--sysconfdir` options. In addition the value of the
:option:`--with-compiler` option is passed in a :option:`--with-hc-pkg` option
and all options specified with :option:`--configure-option` are passed on.
......@@ -600,6 +600,18 @@ package:
``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,
``$abitag``
.. option:: --dynlibdir=dir
Dynamic libraries are installed here.
By default, this is set to `$libdir/$abi`, which is usually not equal to
`$libdir/$libsubdir`.
In the simple build system, *dir* may contain the following path
variables: ``$prefix``, ``$bindir``, ``$libdir``, ``$pkgid``, ``$pkg``,
``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,
``$abitag``
.. option:: --libexecdir=dir
Executables that are not expected to be invoked directly by the user
......@@ -712,6 +724,8 @@ $libdir
As above but for :option:`--libdir`
$libsubdir
As above but for :option:`--libsubdir`
$dynlibdir
As above but for :option:`--dynlibdir`
$datadir
As above but for :option:`--datadir`
$datasubdir
......@@ -768,6 +782,9 @@ For the simple build system, the following defaults apply:
* - :option:`--libsubdir` (others)
- ``$pkgid/$compiler``
- ``$pkgid\$compiler``
* - :option:`--dynlibdir`
- ``$libdir/$abi``
- ``$libdir\$abi``
* - :option:`--libexecdir`
- ``$prefix/libexec``
- ``$prefix\$pkgid``
......@@ -809,7 +826,7 @@ particularly useful: it means the user can choose the install location
bake the path into the binary when it is built.
In order to achieve this, we require that for an executable on Windows,
all of ``$bindir``, ``$libdir``, ``$datadir`` and ``$libexecdir`` begin
all of ``$bindir``, ``$libdir``, ``$dynlibdir``, ``$datadir`` and ``$libexecdir`` begin
with ``$prefix``. If this is not the case then the compiled executable
will have baked-in all absolute paths.
......
......@@ -15,7 +15,7 @@ import Distribution.Types.LocalBuildInfo
import Distribution.Simple.LocalBuildInfo
( absoluteComponentInstallDirs
, InstallDirs(libdir)
, InstallDirs (..)
, ComponentLocalBuildInfo(componentUnitId), ComponentName(..) )
import Distribution.Simple.InstallDirs ( CopyDest(NoCopyDest) )
import Distribution.Simple.BuildPaths ( mkLibName, mkSharedLibName )
......@@ -683,8 +683,8 @@ tests config = do
cname = CSubLibName "foo-internal"
[target] = componentNameTargets' pkg_descr lbi cname
uid = componentUnitId (targetCLBI target)
dir = libdir (absoluteComponentInstallDirs pkg_descr lbi uid
NoCopyDest)
InstallDirs{libdir=dir,dynlibdir=dyndir} =
absoluteComponentInstallDirs pkg_descr lbi uid NoCopyDest
assertBool "interface files should be installed"
=<< liftIO (doesFileExist (dir </> "Foo.hi"))
assertBool "static library should be installed"
......@@ -692,11 +692,11 @@ tests config = do
if is_dynamic
then
assertBool "dynamic library MUST be installed"
=<< liftIO (doesFileExist (dir </> mkSharedLibName
=<< liftIO (doesFileExist (dyndir </> mkSharedLibName
compiler_id uid))
else
assertBool "dynamic library should be installed"
=<< liftIO (doesFileExist (dir </> mkSharedLibName
=<< liftIO (doesFileExist (dyndir </> mkSharedLibName
compiler_id uid))
shouldFail $ ghcPkg "describe" ["foo"]
-- clean away the dist directory so that we catch accidental
......
......@@ -95,7 +95,7 @@ import Distribution.Simple.Setup
, boolOpt, boolOpt', trueArg, falseArg
, readPToMaybe, optionNumJobs )
import Distribution.Simple.InstallDirs
( PathTemplate, InstallDirs(sysconfdir)
( PathTemplate, InstallDirs(dynlibdir, sysconfdir)
, toPathTemplate, fromPathTemplate )
import Distribution.Version
( Version, mkVersion, nullVersion, anyVersion, thisVersion )
......@@ -363,7 +363,7 @@ filterConfigureFlags :: ConfigFlags -> Version -> ConfigFlags
filterConfigureFlags flags cabalLibVersion
-- NB: we expect the latest version to be the most common case,
-- so test it first.
| cabalLibVersion >= mkVersion [1,23,0] = flags_latest
| cabalLibVersion >= mkVersion [1,25,0] = flags_latest
-- The naming convention is that flags_version gives flags with
-- all flags *introduced* in version eliminated.
-- It is NOT the latest version of Cabal library that
......@@ -379,6 +379,7 @@ filterConfigureFlags flags cabalLibVersion
| cabalLibVersion < mkVersion [1,21,1] = flags_1_21_1
| cabalLibVersion < mkVersion [1,22,0] = flags_1_22_0
| cabalLibVersion < mkVersion [1,23,0] = flags_1_23_0
| cabalLibVersion < mkVersion [1,25,0] = flags_1_25_0
| otherwise = flags_latest
where
flags_latest = flags {
......@@ -390,11 +391,15 @@ filterConfigureFlags flags cabalLibVersion
configAllowNewer = Just (Cabal.AllowNewer Cabal.RelaxDepsNone)
}
-- Cabal < 1.25.0 doesn't know about --dynlibdir.
flags_1_25_0 = flags_latest { configInstallDirs = configInstallDirs_1_25_0}
configInstallDirs_1_25_0 = (configInstallDirs flags) { dynlibdir = NoFlag }
-- Cabal < 1.23 doesn't know about '--profiling-detail'.
-- Cabal < 1.23 has a hacked up version of 'enable-profiling'
-- which we shouldn't use.
(tryLibProfiling, tryExeProfiling) = computeEffectiveProfiling flags
flags_1_23_0 = flags_latest { configProfDetail = NoFlag
flags_1_23_0 = flags_1_25_0 { configProfDetail = NoFlag
, configProfLibDetail = NoFlag
, configIPID = NoFlag
, configProf = NoFlag
......@@ -423,7 +428,7 @@ filterConfigureFlags flags cabalLibVersion
-- Cabal < 1.18.0 doesn't know about --extra-prog-path and --sysconfdir.
flags_1_18_0 = flags_1_19_1 { configProgramPathExtra = toNubList []
, configInstallDirs = configInstallDirs_1_18_0}
configInstallDirs_1_18_0 = (configInstallDirs flags) { sysconfdir = NoFlag }
configInstallDirs_1_18_0 = (configInstallDirs flags_1_19_1) { sysconfdir = NoFlag }
-- Cabal < 1.14.0 doesn't know about '--disable-benchmarks'.
flags_1_14_0 = flags_1_18_0 { configBenchmarks = NoFlag }
-- Cabal < 1.12.0 doesn't know about '--enable/disable-executable-dynamic'
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment