This patch is based on https://github.com/sternenseemann/cabal/tree/sterni-cabal-3.16-for-aarch64-darwin and has been created using git diff 77afa40961a686d36717604864b4c48ed5233bea eeed4f92625bbe2dbfb57f51d953e3b9a495d884 --patch --src-prefix=a/libraries/Cabal/ --dst-prefix=b/libraries/Cabal/ Reasoning and explanation of the patch can be found in the comment in the diff for PathsModule.hs below. diff --git a/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule.hs b/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule.hs index 9392acf3c..3417e613a 100644 --- a/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule.hs +++ b/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule.hs @@ -52,6 +52,7 @@ generatePathsModule pkg_descr lbi clbi = , Z.zIsI386 = buildArch == I386 , Z.zIsX8664 = buildArch == X86_64 , Z.zIsAArch64 = buildArch == AArch64 + , Z.zOr = (||) , Z.zNot = not , Z.zManglePkgName = showPkgName , Z.zPrefix = show flat_prefix @@ -61,8 +62,110 @@ generatePathsModule pkg_descr lbi clbi = , Z.zDatadir = zDatadir , Z.zLibexecdir = zLibexecdir , Z.zSysconfdir = zSysconfdir + , -- Sadly we can't be cleverer about this – we can't have literals in the template + Z.zShouldEmitDataDir = shouldEmit "DataDir" + , Z.zShouldEmitLibDir = shouldEmit "LibDir" + , Z.zShouldEmitDynLibDir = shouldEmit "DynLibDir" + , Z.zShouldEmitLibexecDir = shouldEmit "LibexecDir" + , Z.zShouldEmitSysconfDir = shouldEmit "SysconfDir" + , Z.zWarning = zWarning + , Z.zShouldEmitWarning = zShouldEmitWarning } where + -- GHC's NCG backend for aarch64-darwin does not support link-time dead code + -- elimination to the extent that NCG does for other targets. Consequently, + -- we struggle with unnecessarily retained store path references due to the + -- use of `Paths_*` modules – even if `getLibDir` is not used, it'll end up + -- in the final library or executables we build. + -- + -- When using a different output for the executables and library, this + -- becomes more sinister: The library will contain a reference to the bin + -- output and itself due to `getLibDir` and `getBinDir`, but the executables + -- will do so, too. Either due to linking dynamically or because the library + -- is linked statically into the executable and retains those references. + -- Since Nix disallows cyclical references between two outputs, it becomes + -- impossible to use the `Paths_*` module and a separate `bin` output for + -- aarch64-darwin. + -- + -- The solution we have resorted to for now, is to trim the `Paths_*` module + -- dynamically depending on what references *could* be used without causing + -- a cyclical reference. That has the effect that any code that would not + -- cause a cyclical reference with dead code elimination will compile and + -- work for aarch64-darwin. If the code would use a `get*Dir` function that + -- has been omitted, this would indicate that the code would have caused a + -- cyclical reference anyways. + -- + -- The logic for this makes some pretty big assumptions about installation + -- prefixes that probably only hold fully in nixpkgs with + -- `haskellPackages.mkDerivation`. Simple uses outside nixpkgs that have + -- everything below the same prefix should continue to work as expected, + -- though. + -- + -- We assume the following: + -- + -- - flat_prefix is `$out`. + -- - flat_libdir etc. are always below `$out`. + -- + -- Since in the normal case due to static linking `$bin` and `$out` will + -- have the same references in libraries/executables, we need to either + -- prevent usage of `getBinDir` or `getLibDir` to break the cycle in case + -- `flat_bindir` is not below `$out`. We have decided to always allow usage + -- of `getBinDir`, so `getLibDir` gets dropped if a separate `bin` output is + -- used. This has the simple reason that `$out` which contains `flat_libdir` + -- tends to be quite big – we would like to have a `bin` output that doesn't + -- require keeping that around. + pathEmittable :: FilePath -> Bool + pathEmittable p + -- If the executable installation target is below `$out` the reference + -- cycle is within a single output (since libs are installed to `$out`) + -- and thus unproblematic. We can use any and all `get*Dir` functions. + | flat_prefix `isPrefixOf` flat_bindir = True + -- Otherwise, we need to disallow all `get*Dir` functions that would cause + -- a reference to `$out` which contains the libraries that would in turn + -- reference `$bin`. This always include `flat_libdir` and friends, but + -- can also include `flat_datadir` if no separate output for data files is + -- used. + | otherwise = not (flat_prefix `isPrefixOf` p) + + -- This list maps the "name" of the directory to whether we want to include + -- it in the `Paths_*` module or not. `shouldEmit` performs a lookup in this. + dirs :: [(String, Bool)] + dirs = + map + (\(name, path) -> (name, pathEmittable path)) + [ ("LibDir", flat_libdir) + , ("DynLibDir", flat_dynlibdir) + , ("DataDir", flat_datadir) + , ("LibexecDir", flat_libexecdir) + , ("SysconfDir", flat_sysconfdir) + ] + + shouldEmit :: String -> Bool + shouldEmit name = + case lookup name dirs of + Just b -> b + Nothing -> error "panic! BUG in Cabal Paths_ patch for aarch64-darwin, report this at https://github.com/nixos/nixpkgs/issues" + + -- This is a comma separated list of all functions that have been omitted. + -- This is included in a GHC warning which will be attached to the `Paths_*` + -- module in case we are dropping any `get*Dir` functions that would + -- normally exist. + -- + -- TODO: getDataFileName is not accounted for at the moment. + omittedFunctions :: String + omittedFunctions = + intercalate ", " $ + map (("get" ++) . fst) $ + filter (not . snd) dirs + + zWarning :: String + zWarning = + show $ + "The following functions have been omitted by a nixpkgs-specific patch to Cabal: " + ++ omittedFunctions + zShouldEmitWarning :: Bool + zShouldEmitWarning = any (not . snd) dirs + supports_cpp = supports_language_pragma supports_rebindable_syntax = ghc_newer_than (mkVersion [7, 0, 1]) supports_language_pragma = ghc_newer_than (mkVersion [6, 6, 1]) diff --git a/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule/Z.hs b/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule/Z.hs index 8f33717bb..b89775893 100644 --- a/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule/Z.hs +++ b/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule/Z.hs @@ -20,6 +20,14 @@ data Z zDatadir :: FilePath, zLibexecdir :: FilePath, zSysconfdir :: FilePath, + zShouldEmitLibDir :: Bool, + zShouldEmitDynLibDir :: Bool, + zShouldEmitLibexecDir :: Bool, + zShouldEmitDataDir :: Bool, + zShouldEmitSysconfDir :: Bool, + zShouldEmitWarning :: Bool, + zWarning :: String, + zOr :: (Bool -> Bool -> Bool), zNot :: (Bool -> Bool), zManglePkgName :: (PackageName -> String)} deriving Generic @@ -74,10 +82,51 @@ render z_root = execWriter $ do tell "\n" tell "module Paths_" tell (zManglePkgName z_root (zPackageName z_root)) - tell " (\n" + tell "\n" + tell " " + if (zShouldEmitWarning z_root) + then do + tell "{-# WARNING " + tell (zWarning z_root) + tell " #-}" + return () + else do + return () + tell "\n" + tell " (\n" tell " version,\n" - tell " getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir,\n" - tell " getDataFileName, getSysconfDir\n" + tell " getBinDir,\n" + if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitLibDir z_root)) + then do + tell " getLibDir,\n" + return () + else do + return () + if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitDynLibDir z_root)) + then do + tell " getDynLibDir,\n" + return () + else do + return () + if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitLibexecDir z_root)) + then do + tell " getLibexecDir,\n" + return () + else do + return () + if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitDataDir z_root)) + then do + tell " getDataFileName,\n" + tell " getDataDir,\n" + return () + else do + return () + if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitSysconfDir z_root)) + then do + tell " getSysconfDir\n" + return () + else do + return () tell " ) where\n" tell "\n" if (zNot z_root (zAbsolute z_root)) @@ -126,57 +175,19 @@ render z_root = execWriter $ do tell (zVersionDigits z_root) tell " []\n" tell "\n" - tell "-- |If the argument is a filename, the result is the name of a corresponding\n" - tell "-- file on the system on which the program is running, if the file were listed\n" - tell "-- in the @data-files@ field of the package's Cabal package description file.\n" - tell "-- No check is performed that the given filename is listed in that field.\n" - tell "getDataFileName :: FilePath -> IO FilePath\n" - tell "getDataFileName name = do\n" - tell " dir <- getDataDir\n" - tell " return (dir `joinFileName` name)\n" - tell "\n" - tell "-- |The location of the directory specified by Cabal's @--bindir@ option (where\n" - tell "-- executables that the user might invoke are installed). This can be overridden\n" - tell "-- at runtime using the environment variable " - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_bindir.\n" - tell "getBinDir :: IO FilePath\n" - tell "\n" - tell "-- |The location of the directory specified by Cabal's @--libdir@ option (where\n" - tell "-- object libraries are installed). This can be overridden at runtime using the\n" - tell "-- environment variable " - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_libdir.\n" - tell "getLibDir :: IO FilePath\n" - tell "\n" - tell "-- |The location of the directory specified by Cabal's @--dynlibdir@ option\n" - tell "-- (where dynamic libraries are installed). This can be overridden at runtime\n" - tell "-- using the environment variable " - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_dynlibdir.\n" - tell "getDynLibDir :: IO FilePath\n" - tell "\n" - tell "-- |The location of the directory specified by Cabal's @--datadir@ option (where\n" - tell "-- architecture-independent data files are installed). This can be overridden at\n" - tell "-- runtime using the environment variable " - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_datadir.\n" - tell "getDataDir :: IO FilePath\n" - tell "\n" - tell "-- |The location of the directory specified by Cabal's @--libexedir@ option\n" - tell "-- (where executables that are not expected to be invoked directly by the user\n" - tell "-- are installed). This can be overridden at runtime using the environment\n" - tell "-- variable " - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_libexedir.\n" - tell "getLibexecDir :: IO FilePath\n" - tell "\n" - tell "-- |The location of the directory specified by Cabal's @--sysconfdir@ option\n" - tell "-- (where configuration files are installed). This can be overridden at runtime\n" - tell "-- using the environment variable " - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_sysconfdir.\n" - tell "getSysconfDir :: IO FilePath\n" + if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitDataDir z_root)) + then do + tell "-- |If the argument is a filename, the result is the name of a corresponding\n" + tell "-- file on the system on which the program is running, if the file were listed\n" + tell "-- in the @data-files@ field of the package's Cabal package description file.\n" + tell "-- No check is performed that the given filename is listed in that field.\n" + tell "getDataFileName :: FilePath -> IO FilePath\n" + tell "getDataFileName name = do\n" + tell " dir <- getDataDir\n" + tell " return (dir `joinFileName` name)\n" + return () + else do + return () tell "\n" let z_var0_function_defs = do @@ -204,6 +215,7 @@ render z_root = execWriter $ do tell "\n" if (zRelocatable z_root) then do + tell "\n" tell "\n" tell "getPrefixDirReloc :: FilePath -> IO FilePath\n" tell "getPrefixDirReloc dirRel = do\n" @@ -213,31 +225,68 @@ render z_root = execWriter $ do tell (zBindir z_root) tell ") `joinFileName` dirRel)\n" tell "\n" + tell "-- |The location of the directory specified by Cabal's @--bindir@ option (where\n" + tell "-- executables that the user might invoke are installed). This can be overridden\n" + tell "-- at runtime using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_bindir.\n" + tell "getBinDir :: IO FilePath\n" tell "getBinDir = catchIO (getEnv \"" tell (zManglePkgName z_root (zPackageName z_root)) tell "_bindir\") (\\_ -> getPrefixDirReloc $ " tell (zBindir z_root) tell ")\n" + tell "-- |The location of the directory specified by Cabal's @--libdir@ option (where\n" + tell "-- object libraries are installed). This can be overridden at runtime using the\n" + tell "-- environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_libdir.\n" + tell "getLibDir :: IO FilePath\n" tell "getLibDir = catchIO (getEnv \"" tell (zManglePkgName z_root (zPackageName z_root)) tell "_libdir\") (\\_ -> getPrefixDirReloc $ " tell (zLibdir z_root) tell ")\n" + tell "-- |The location of the directory specified by Cabal's @--dynlibdir@ option\n" + tell "-- (where dynamic libraries are installed). This can be overridden at runtime\n" + tell "-- using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_dynlibdir.\n" + tell "getDynLibDir :: IO FilePath\n" tell "getDynLibDir = catchIO (getEnv \"" tell (zManglePkgName z_root (zPackageName z_root)) tell "_dynlibdir\") (\\_ -> getPrefixDirReloc $ " tell (zDynlibdir z_root) tell ")\n" + tell "-- |The location of the directory specified by Cabal's @--datadir@ option (where\n" + tell "-- architecture-independent data files are installed). This can be overridden at\n" + tell "-- runtime using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_datadir.\n" + tell "getDataDir :: IO FilePath\n" tell "getDataDir = catchIO (getEnv \"" tell (zManglePkgName z_root (zPackageName z_root)) tell "_datadir\") (\\_ -> getPrefixDirReloc $ " tell (zDatadir z_root) tell ")\n" + tell "-- |The location of the directory specified by Cabal's @--libexedir@ option\n" + tell "-- (where executables that are not expected to be invoked directly by the user\n" + tell "-- are installed). This can be overridden at runtime using the environment\n" + tell "-- variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_libexedir.\n" + tell "getLibexecDir :: IO FilePath\n" tell "getLibexecDir = catchIO (getEnv \"" tell (zManglePkgName z_root (zPackageName z_root)) tell "_libexecdir\") (\\_ -> getPrefixDirReloc $ " tell (zLibexecdir z_root) tell ")\n" + tell "-- |The location of the directory specified by Cabal's @--sysconfdir@ option\n" + tell "-- (where configuration files are installed). This can be overridden at runtime\n" + tell "-- using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_sysconfdir.\n" + tell "getSysconfDir :: IO FilePath\n" tell "getSysconfDir = catchIO (getEnv \"" tell (zManglePkgName z_root (zPackageName z_root)) tell "_sysconfdir\") (\\_ -> getPrefixDirReloc $ " @@ -251,72 +300,186 @@ render z_root = execWriter $ do if (zAbsolute z_root) then do tell "\n" - tell "bindir, libdir, dynlibdir, datadir, libexecdir, sysconfdir :: FilePath\n" + tell "bindir :: FilePath\n" tell "bindir = " tell (zBindir z_root) tell "\n" - tell "libdir = " - tell (zLibdir z_root) tell "\n" - tell "dynlibdir = " - tell (zDynlibdir z_root) + tell "-- |The location of the directory specified by Cabal's @--bindir@ option (where\n" + tell "-- executables that the user might invoke are installed). This can be overridden\n" + tell "-- at runtime using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_bindir.\n" + tell "getBinDir :: IO FilePath\n" + tell "getBinDir = catchIO (getEnv \"" + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_bindir\") (\\_ -> return bindir)\n" tell "\n" - tell "datadir = " - tell (zDatadir z_root) + if (zShouldEmitLibDir z_root) + then do + tell "libdir :: FilePath\n" + tell "libdir = " + tell (zLibdir z_root) + tell "\n" + tell "\n" + tell "-- |The location of the directory specified by Cabal's @--libdir@ option (where\n" + tell "-- object libraries are installed). This can be overridden at runtime using the\n" + tell "-- environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_libdir.\n" + tell "getLibDir :: IO FilePath\n" + tell "getLibDir = catchIO (getEnv \"" + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_libdir\") (\\_ -> return libdir)\n" + return () + else do + return () tell "\n" - tell "libexecdir = " - tell (zLibexecdir z_root) + if (zShouldEmitDynLibDir z_root) + then do + tell "dynlibdir :: FilePath\n" + tell "dynlibdir = " + tell (zDynlibdir z_root) + tell "\n" + tell "-- |The location of the directory specified by Cabal's @--dynlibdir@ option\n" + tell "-- (where dynamic libraries are installed). This can be overridden at runtime\n" + tell "-- using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_dynlibdir.\n" + tell "getDynLibDir :: IO FilePath\n" + tell "getDynLibDir = catchIO (getEnv \"" + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_dynlibdir\") (\\_ -> return dynlibdir)\n" + return () + else do + return () tell "\n" - tell "sysconfdir = " - tell (zSysconfdir z_root) + if (zShouldEmitDataDir z_root) + then do + tell "datadir :: FilePath\n" + tell "datadir = " + tell (zDatadir z_root) + tell "\n" + tell "\n" + tell "-- |The location of the directory specified by Cabal's @--datadir@ option (where\n" + tell "-- architecture-independent data files are installed). This can be overridden at\n" + tell "-- runtime using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_datadir.\n" + tell "getDataDir :: IO FilePath\n" + tell "getDataDir = catchIO (getEnv \"" + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_datadir\") (\\_ -> return datadir)\n" + return () + else do + return () tell "\n" + if (zShouldEmitLibexecDir z_root) + then do + tell "libexecdir :: FilePath\n" + tell "libexecdir = " + tell (zLibexecdir z_root) + tell "\n" + tell "\n" + tell "-- |The location of the directory specified by Cabal's @--libexedir@ option\n" + tell "-- (where executables that are not expected to be invoked directly by the user\n" + tell "-- are installed). This can be overridden at runtime using the environment\n" + tell "-- variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_libexedir.\n" + tell "getLibexecDir :: IO FilePath\n" + tell "getLibexecDir = catchIO (getEnv \"" + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_libexecdir\") (\\_ -> return libexecdir)\n" + return () + else do + return () tell "\n" - tell "getBinDir = catchIO (getEnv \"" - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_bindir\") (\\_ -> return bindir)\n" - tell "getLibDir = catchIO (getEnv \"" - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_libdir\") (\\_ -> return libdir)\n" - tell "getDynLibDir = catchIO (getEnv \"" - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_dynlibdir\") (\\_ -> return dynlibdir)\n" - tell "getDataDir = catchIO (getEnv \"" - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_datadir\") (\\_ -> return datadir)\n" - tell "getLibexecDir = catchIO (getEnv \"" - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_libexecdir\") (\\_ -> return libexecdir)\n" - tell "getSysconfDir = catchIO (getEnv \"" - tell (zManglePkgName z_root (zPackageName z_root)) - tell "_sysconfdir\") (\\_ -> return sysconfdir)\n" + if (zShouldEmitSysconfDir z_root) + then do + tell "sysconfdir :: FilePath\n" + tell "sysconfdir = " + tell (zSysconfdir z_root) + tell "\n" + tell "\n" + tell "-- |The location of the directory specified by Cabal's @--sysconfdir@ option\n" + tell "-- (where configuration files are installed). This can be overridden at runtime\n" + tell "-- using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_sysconfdir.\n" + tell "getSysconfDir :: IO FilePath\n" + tell "getSysconfDir = catchIO (getEnv \"" + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_sysconfdir\") (\\_ -> return sysconfdir)\n" + return () + else do + return () tell "\n" return () else do if (zIsWindows z_root) then do + tell "\n" tell "\n" tell "prefix :: FilePath\n" tell "prefix = " tell (zPrefix z_root) tell "\n" tell "\n" + tell "-- |The location of the directory specified by Cabal's @--bindir@ option (where\n" + tell "-- executables that the user might invoke are installed). This can be overridden\n" + tell "-- at runtime using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_bindir.\n" + tell "getBinDir :: IO FilePath\n" tell "getBinDir = getPrefixDirRel $ " tell (zBindir z_root) tell "\n" + tell "-- |The location of the directory specified by Cabal's @--libdir@ option (where\n" + tell "-- object libraries are installed). This can be overridden at runtime using the\n" + tell "-- environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_libdir.\n" + tell "getLibDir :: IO FilePath\n" tell "getLibDir = " tell (zLibdir z_root) tell "\n" + tell "-- |The location of the directory specified by Cabal's @--dynlibdir@ option\n" + tell "-- (where dynamic libraries are installed). This can be overridden at runtime\n" + tell "-- using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_dynlibdir.\n" + tell "getDynLibDir :: IO FilePath\n" tell "getDynLibDir = " tell (zDynlibdir z_root) tell "\n" + tell "-- |The location of the directory specified by Cabal's @--datadir@ option (where\n" + tell "-- architecture-independent data files are installed). This can be overridden at\n" + tell "-- runtime using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_datadir.\n" + tell "getDataDir :: IO FilePath\n" tell "getDataDir = catchIO (getEnv \"" tell (zManglePkgName z_root (zPackageName z_root)) tell "_datadir\") (\\_ -> " tell (zDatadir z_root) tell ")\n" + tell "-- |The location of the directory specified by Cabal's @--libexedir@ option\n" + tell "-- (where executables that are not expected to be invoked directly by the user\n" + tell "-- are installed). This can be overridden at runtime using the environment\n" + tell "-- variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_libexedir.\n" + tell "getLibexecDir :: IO FilePath\n" tell "getLibexecDir = " tell (zLibexecdir z_root) tell "\n" + tell "-- |The location of the directory specified by Cabal's @--sysconfdir@ option\n" + tell "-- (where configuration files are installed). This can be overridden at runtime\n" + tell "-- using the environment variable " + tell (zManglePkgName z_root (zPackageName z_root)) + tell "_sysconfdir.\n" + tell "getSysconfDir :: IO FilePath\n" tell "getSysconfDir = " tell (zSysconfdir z_root) tell "\n" diff --git a/libraries/Cabal/cabal-dev-scripts/src/GenPathsModule.hs b/libraries/Cabal/cabal-dev-scripts/src/GenPathsModule.hs index 7c5c947a5..3b7a67498 100644 --- a/libraries/Cabal/cabal-dev-scripts/src/GenPathsModule.hs +++ b/libraries/Cabal/cabal-dev-scripts/src/GenPathsModule.hs @@ -42,6 +42,16 @@ $(capture "decls" [d| , zLibexecdir :: FilePath , zSysconfdir :: FilePath + , zShouldEmitLibDir :: Bool + , zShouldEmitDynLibDir :: Bool + , zShouldEmitLibexecDir :: Bool + , zShouldEmitDataDir :: Bool + , zShouldEmitSysconfDir :: Bool + + , zShouldEmitWarning :: Bool + , zWarning :: String + + , zOr :: Bool -> Bool -> Bool , zNot :: Bool -> Bool , zManglePkgName :: PackageName -> String } diff --git a/libraries/Cabal/templates/Paths_pkg.template.hs b/libraries/Cabal/templates/Paths_pkg.template.hs index a9b02b0ef..d99252a29 100644 --- a/libraries/Cabal/templates/Paths_pkg.template.hs +++ b/libraries/Cabal/templates/Paths_pkg.template.hs @@ -31,10 +31,31 @@ For further information about Cabal's options for its configuration step, and their default values, see the Cabal User Guide. -} -module Paths_{{ manglePkgName packageName }} ( +module Paths_{{ manglePkgName packageName }} + {% if shouldEmitWarning %}{-# WARNING {{ warning }} #-}{% endif %} + ( version, - getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir, - getDataFileName, getSysconfDir + getBinDir, +{# We only care about the absolute case for our emit logic, since only in this + case references are incurred. We are not going to hit isWindows and relocatable + has no absolute references to begin with. +#} +{% if or (not absolute) shouldEmitLibDir %} + getLibDir, +{% endif %} +{% if or (not absolute) shouldEmitDynLibDir %} + getDynLibDir, +{% endif %} +{% if or (not absolute) shouldEmitLibexecDir %} + getLibexecDir, +{% endif %} +{% if or (not absolute) shouldEmitDataDir %} + getDataFileName, + getDataDir, +{% endif %} +{% if or (not absolute) shouldEmitSysconfDir %} + getSysconfDir +{% endif %} ) where {% if not absolute %} @@ -73,6 +94,7 @@ catchIO = Exception.catch version :: Version version = Version {{ versionDigits }} [] +{% if or (not absolute) shouldEmitDataDir %} -- |If the argument is a filename, the result is the name of a corresponding -- file on the system on which the program is running, if the file were listed -- in the @data-files@ field of the package's Cabal package description file. @@ -81,37 +103,7 @@ getDataFileName :: FilePath -> IO FilePath getDataFileName name = do dir <- getDataDir return (dir `joinFileName` name) - --- |The location of the directory specified by Cabal's @--bindir@ option (where --- executables that the user might invoke are installed). This can be overridden --- at runtime using the environment variable {{ manglePkgName packageName }}_bindir. -getBinDir :: IO FilePath - --- |The location of the directory specified by Cabal's @--libdir@ option (where --- object libraries are installed). This can be overridden at runtime using the --- environment variable {{ manglePkgName packageName }}_libdir. -getLibDir :: IO FilePath - --- |The location of the directory specified by Cabal's @--dynlibdir@ option --- (where dynamic libraries are installed). This can be overridden at runtime --- using the environment variable {{ manglePkgName packageName }}_dynlibdir. -getDynLibDir :: IO FilePath - --- |The location of the directory specified by Cabal's @--datadir@ option (where --- architecture-independent data files are installed). This can be overridden at --- runtime using the environment variable {{ manglePkgName packageName }}_datadir. -getDataDir :: IO FilePath - --- |The location of the directory specified by Cabal's @--libexedir@ option --- (where executables that are not expected to be invoked directly by the user --- are installed). This can be overridden at runtime using the environment --- variable {{ manglePkgName packageName }}_libexedir. -getLibexecDir :: IO FilePath - --- |The location of the directory specified by Cabal's @--sysconfdir@ option --- (where configuration files are installed). This can be overridden at runtime --- using the environment variable {{ manglePkgName packageName }}_sysconfdir. -getSysconfDir :: IO FilePath +{% endif %} {% defblock function_defs %} minusFileName :: FilePath -> String -> FilePath @@ -140,48 +132,155 @@ splitFileName p = (reverse (path2++drive), reverse fname) {% if relocatable %} +{# Relocatable can not incur any absolute references, so we can ignore it. + Additionally, --enable-relocatable is virtually useless in Nix builds +#} + getPrefixDirReloc :: FilePath -> IO FilePath getPrefixDirReloc dirRel = do exePath <- getExecutablePath let (dir,_) = splitFileName exePath return ((dir `minusFileName` {{ bindir }}) `joinFileName` dirRel) +-- |The location of the directory specified by Cabal's @--bindir@ option (where +-- executables that the user might invoke are installed). This can be overridden +-- at runtime using the environment variable {{ manglePkgName packageName }}_bindir. +getBinDir :: IO FilePath getBinDir = catchIO (getEnv "{{ manglePkgName packageName }}_bindir") (\_ -> getPrefixDirReloc $ {{ bindir }}) +-- |The location of the directory specified by Cabal's @--libdir@ option (where +-- object libraries are installed). This can be overridden at runtime using the +-- environment variable {{ manglePkgName packageName }}_libdir. +getLibDir :: IO FilePath getLibDir = catchIO (getEnv "{{ manglePkgName packageName }}_libdir") (\_ -> getPrefixDirReloc $ {{ libdir }}) +-- |The location of the directory specified by Cabal's @--dynlibdir@ option +-- (where dynamic libraries are installed). This can be overridden at runtime +-- using the environment variable {{ manglePkgName packageName }}_dynlibdir. +getDynLibDir :: IO FilePath getDynLibDir = catchIO (getEnv "{{ manglePkgName packageName }}_dynlibdir") (\_ -> getPrefixDirReloc $ {{ dynlibdir }}) +-- |The location of the directory specified by Cabal's @--datadir@ option (where +-- architecture-independent data files are installed). This can be overridden at +-- runtime using the environment variable {{ manglePkgName packageName }}_datadir. +getDataDir :: IO FilePath getDataDir = catchIO (getEnv "{{ manglePkgName packageName }}_datadir") (\_ -> getPrefixDirReloc $ {{ datadir }}) +-- |The location of the directory specified by Cabal's @--libexedir@ option +-- (where executables that are not expected to be invoked directly by the user +-- are installed). This can be overridden at runtime using the environment +-- variable {{ manglePkgName packageName }}_libexedir. +getLibexecDir :: IO FilePath getLibexecDir = catchIO (getEnv "{{ manglePkgName packageName }}_libexecdir") (\_ -> getPrefixDirReloc $ {{ libexecdir }}) +-- |The location of the directory specified by Cabal's @--sysconfdir@ option +-- (where configuration files are installed). This can be overridden at runtime +-- using the environment variable {{ manglePkgName packageName }}_sysconfdir. +getSysconfDir :: IO FilePath getSysconfDir = catchIO (getEnv "{{ manglePkgName packageName }}_sysconfdir") (\_ -> getPrefixDirReloc $ {{ sysconfdir }}) {% useblock function_defs %} {% elif absolute %} -bindir, libdir, dynlibdir, datadir, libexecdir, sysconfdir :: FilePath +bindir :: FilePath bindir = {{ bindir }} -libdir = {{ libdir }} -dynlibdir = {{ dynlibdir }} -datadir = {{ datadir }} -libexecdir = {{ libexecdir }} -sysconfdir = {{ sysconfdir }} +-- |The location of the directory specified by Cabal's @--bindir@ option (where +-- executables that the user might invoke are installed). This can be overridden +-- at runtime using the environment variable {{ manglePkgName packageName }}_bindir. +getBinDir :: IO FilePath getBinDir = catchIO (getEnv "{{ manglePkgName packageName }}_bindir") (\_ -> return bindir) + +{% if shouldEmitLibDir %} +libdir :: FilePath +libdir = {{ libdir }} + +-- |The location of the directory specified by Cabal's @--libdir@ option (where +-- object libraries are installed). This can be overridden at runtime using the +-- environment variable {{ manglePkgName packageName }}_libdir. +getLibDir :: IO FilePath getLibDir = catchIO (getEnv "{{ manglePkgName packageName }}_libdir") (\_ -> return libdir) +{% endif %} + +{% if shouldEmitDynLibDir %} +dynlibdir :: FilePath +dynlibdir = {{ dynlibdir }} +-- |The location of the directory specified by Cabal's @--dynlibdir@ option +-- (where dynamic libraries are installed). This can be overridden at runtime +-- using the environment variable {{ manglePkgName packageName }}_dynlibdir. +getDynLibDir :: IO FilePath getDynLibDir = catchIO (getEnv "{{ manglePkgName packageName }}_dynlibdir") (\_ -> return dynlibdir) +{% endif %} + +{% if shouldEmitDataDir %} +datadir :: FilePath +datadir = {{ datadir }} + +-- |The location of the directory specified by Cabal's @--datadir@ option (where +-- architecture-independent data files are installed). This can be overridden at +-- runtime using the environment variable {{ manglePkgName packageName }}_datadir. +getDataDir :: IO FilePath getDataDir = catchIO (getEnv "{{ manglePkgName packageName }}_datadir") (\_ -> return datadir) +{% endif %} + +{% if shouldEmitLibexecDir %} +libexecdir :: FilePath +libexecdir = {{ libexecdir }} + +-- |The location of the directory specified by Cabal's @--libexedir@ option +-- (where executables that are not expected to be invoked directly by the user +-- are installed). This can be overridden at runtime using the environment +-- variable {{ manglePkgName packageName }}_libexedir. +getLibexecDir :: IO FilePath getLibexecDir = catchIO (getEnv "{{ manglePkgName packageName }}_libexecdir") (\_ -> return libexecdir) +{% endif %} + +{% if shouldEmitSysconfDir %} +sysconfdir :: FilePath +sysconfdir = {{ sysconfdir }} + +-- |The location of the directory specified by Cabal's @--sysconfdir@ option +-- (where configuration files are installed). This can be overridden at runtime +-- using the environment variable {{ manglePkgName packageName }}_sysconfdir. +getSysconfDir :: IO FilePath getSysconfDir = catchIO (getEnv "{{ manglePkgName packageName }}_sysconfdir") (\_ -> return sysconfdir) +{% endif %} {% elif isWindows %} +{# We are only trying to fix the problem for aarch64-darwin with this patch, + so let's ignore Windows which we can reach via pkgsCross, for example. +#} + prefix :: FilePath prefix = {{ prefix }} +-- |The location of the directory specified by Cabal's @--bindir@ option (where +-- executables that the user might invoke are installed). This can be overridden +-- at runtime using the environment variable {{ manglePkgName packageName }}_bindir. +getBinDir :: IO FilePath getBinDir = getPrefixDirRel $ {{ bindir }} +-- |The location of the directory specified by Cabal's @--libdir@ option (where +-- object libraries are installed). This can be overridden at runtime using the +-- environment variable {{ manglePkgName packageName }}_libdir. +getLibDir :: IO FilePath getLibDir = {{ libdir }} +-- |The location of the directory specified by Cabal's @--dynlibdir@ option +-- (where dynamic libraries are installed). This can be overridden at runtime +-- using the environment variable {{ manglePkgName packageName }}_dynlibdir. +getDynLibDir :: IO FilePath getDynLibDir = {{ dynlibdir }} +-- |The location of the directory specified by Cabal's @--datadir@ option (where +-- architecture-independent data files are installed). This can be overridden at +-- runtime using the environment variable {{ manglePkgName packageName }}_datadir. +getDataDir :: IO FilePath getDataDir = catchIO (getEnv "{{ manglePkgName packageName }}_datadir") (\_ -> {{ datadir }}) +-- |The location of the directory specified by Cabal's @--libexedir@ option +-- (where executables that are not expected to be invoked directly by the user +-- are installed). This can be overridden at runtime using the environment +-- variable {{ manglePkgName packageName }}_libexedir. +getLibexecDir :: IO FilePath getLibexecDir = {{ libexecdir }} +-- |The location of the directory specified by Cabal's @--sysconfdir@ option +-- (where configuration files are installed). This can be overridden at runtime +-- using the environment variable {{ manglePkgName packageName }}_sysconfdir. +getSysconfDir :: IO FilePath getSysconfDir = {{ sysconfdir }} getPrefixDirRel :: FilePath -> IO FilePath