11{-# LANGUAGE CPP #-}
2+ {-# LANGUAGE DataKinds #-}
23{-# LANGUAGE QuasiQuotes #-}
34{-# LANGUAGE TemplateHaskell #-}
45
@@ -33,13 +34,27 @@ import Distribution.PackageDescription.Parse
3334#if MIN_VERSION_Cabal(3,8,0)
3435import Distribution.Simple.PackageDescription
3536#endif
37+ #if MIN_VERSION_Cabal(3,14,0)
38+ -- Note [Cabal 3.14]
39+ --
40+ -- If you change any path stuff, either test that the package still works with
41+ -- Cabal 3.12 or stop declaring support for it in cuda.cabal. (If you do the
42+ -- latter, also remove all of the other conditionals in this file.)
43+ -- Note that supporting old versions of Cabal is useful for being able to run
44+ -- e.g. Accelerate on old GPU clusters, which is nice.
45+ import Distribution.Utils.Path (SymbolicPath , FileOrDir (File , Dir ), Lib , Include , Pkg , CWD , makeSymbolicPath , interpretSymbolicPath , makeRelativePathEx )
46+ import qualified Distribution.Types.LocalBuildConfig as LBC
47+ #else
48+ import Data.Kind (Constraint )
49+ #endif
3650
3751import Control.Exception
3852import Control.Monad
3953import Data.Char (isDigit )
4054import Data.Function
4155import Data.List
4256import Data.Maybe
57+ import Data.String (fromString )
4358import System.Directory
4459import System.Environment
4560import System.FilePath
@@ -67,8 +82,9 @@ defaultCUDAInstallPath _ = "/usr/local/cuda" -- windows?
6782main :: IO ()
6883main = defaultMainWithHooks customHooks
6984 where
85+ -- Be careful changing flags/paths stuff here; see Note [Cabal 3.14].
7086 readHook get_verbosity a flags = do
71- getHookedBuildInfo (fromFlag (get_verbosity flags))
87+ getHookedBuildInfo (flagToMaybe (workingDirFlag flags)) ( fromFlag (get_verbosity flags))
7288
7389 preprocessors = hookedPreProcessors simpleUserHooks
7490
@@ -87,14 +103,16 @@ main = defaultMainWithHooks customHooks
87103 , preReg = readHook regVerbosity
88104 , preUnreg = readHook regVerbosity
89105 , postConf = postConfHook
90- , hookedPreProcessors = (" chs" , ppC2hs) : filter (\ x -> fst x /= " chs" ) preprocessors
106+ , hookedPreProcessors = (fromString " chs" , ppC2hs) : filter (\ x -> fst x /= fromString " chs" ) preprocessors
91107 }
92108
93109 -- The hook just loads the HookedBuildInfo generated by postConfHook,
94110 -- unless there is user-provided info that overwrites it.
95111 --
96112 preBuildHook :: Args -> BuildFlags -> IO HookedBuildInfo
97- preBuildHook _ flags = getHookedBuildInfo $ fromFlag $ buildVerbosity flags
113+ preBuildHook _ flags = getHookedBuildInfo cwd verbosity
114+ where cwd = flagToMaybe (workingDirFlag flags)
115+ verbosity = fromFlag (buildVerbosity flags)
98116
99117 -- The hook scans system in search for CUDA Toolkit. If the toolkit is not
100118 -- found, an error is raised. Otherwise the toolkit location is used to
@@ -103,12 +121,14 @@ main = defaultMainWithHooks customHooks
103121 postConfHook :: Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()
104122 postConfHook args flags pkg_descr lbi = do
105123 let
124+ cwd = flagToMaybe (workingDirFlag flags)
106125 verbosity = fromFlagOrDefault normal (configVerbosity flags)
107126 profile = fromFlagOrDefault False (configProfLib flags)
108127 currentPlatform = hostPlatform lbi
109128 compilerId_ = compilerId (compiler lbi)
110129 --
111130 generateAndStoreBuildInfo
131+ cwd
112132 verbosity
113133 profile
114134 currentPlatform
@@ -118,7 +138,7 @@ main = defaultMainWithHooks customHooks
118138 generatedBuildInfoFilePath
119139 validateLinker verbosity currentPlatform $ withPrograms lbi
120140 --
121- actualBuildInfoToUse <- getHookedBuildInfo verbosity
141+ actualBuildInfoToUse <- getHookedBuildInfo cwd verbosity
122142 let pkg_descr' = updatePackageDescription actualBuildInfoToUse pkg_descr
123143 postConf simpleUserHooks args flags pkg_descr' lbi
124144
@@ -131,27 +151,29 @@ escBackslash (f:fs) = f : escBackslash fs
131151-- visible to underlying build tools.
132152--
133153libraryBuildInfo
134- :: Verbosity
154+ :: Maybe CWDPath
155+ -> Verbosity
135156 -> Bool
136157 -> FilePath
137158 -> Platform
138159 -> Version
139- -> [FilePath ]
140- -> [FilePath ]
160+ -> [ExtraLibsPath ]
161+ -> [ExtraIncludesPath ]
141162 -> IO HookedBuildInfo
142- libraryBuildInfo verbosity profile installPath platform@ (Platform arch os) ghcVersion extraLibs extraIncludes = do
163+ libraryBuildInfo cwd verbosity profile installPath platform@ (Platform arch os) ghcVersion extraLibs extraIncludes = do
143164 let
144- libraryPaths = cudaLibraryPaths platform installPath ++ extraLibs
145- includePaths = cudaIncludePath platform installPath : extraIncludes
165+ -- Be careful changing flags/paths stuff here; see Note [Cabal 3.14].
166+ libraryPaths = map makeSymbolicPath (cudaLibraryPaths platform installPath) ++ extraLibs
167+ includePaths = makeSymbolicPath (cudaIncludePath platform installPath) : extraIncludes
146168
147169 takeFirstExisting paths = do
148- existing <- filterM doesDirectoryExist libraryPaths
170+ existing <- filterM ( doesDirectoryExist . interpretSymbolicPath cwd) libraryPaths
149171 case existing of
150172 (p0: _) -> return p0
151173 _ -> die' verbosity $ " Could not find path: " ++ show paths
152174
153175 -- This can only be defined once, so take the first path which exists
154- canonicalLibraryPath <- takeFirstExisting libraryPaths
176+ canonicalLibraryPath <- interpretSymbolicPath cwd <$> takeFirstExisting libraryPaths
155177
156178 let
157179 -- OS-specific escaping for -D path defines
@@ -163,16 +185,16 @@ libraryBuildInfo verbosity profile installPath platform@(Platform arch os) ghcVe
163185 extraLibDirs' = libraryPaths
164186 ccOptions' = [ " -DCUDA_INSTALL_PATH=\" " ++ escDefPath installPath ++ " \" "
165187 , " -DCUDA_LIBRARY_PATH=\" " ++ escDefPath canonicalLibraryPath ++ " \" "
166- ] ++ map (" -I" ++ ) includePaths
167- ldOptions' = map (" -L" ++ ) libraryPaths
188+ ] ++ map (( " -I" ++ ) . interpretSymbolicPath cwd ) includePaths
189+ ldOptions' = map (( " -L" ++ ) . interpretSymbolicPath cwd ) libraryPaths
168190 ghcOptions = map (" -optc" ++ ) ccOptions'
169191 ++ map (" -optl" ++ ) ldOptions'
170192 ++ if os /= Windows && not profile
171- then map (" -optl-Wl,-rpath," ++ ) extraLibDirs'
193+ then map (( " -optl-Wl,-rpath," ++ ) . interpretSymbolicPath cwd ) extraLibDirs'
172194 else []
173195 extraLibs' = cudaLibraries platform
174- frameworks' = [ " CUDA" | os == OSX ]
175- frameworkDirs' = [ " /Library/Frameworks" | os == OSX ]
196+ frameworks' = [ makeRelativePathEx " CUDA" | os == OSX ]
197+ frameworkDirs' = [ makeSymbolicPath " /Library/Frameworks" | os == OSX ]
176198
177199 -- options or c2hs
178200 archFlag = case arch of
@@ -427,17 +449,18 @@ windowsLinkerBugMsg ldPath = printf (unlines msg) windowsHelpPage ldPath
427449-- Runs CUDA detection procedure and stores .buildinfo to a file.
428450--
429451generateAndStoreBuildInfo
430- :: Verbosity
452+ :: Maybe CWDPath
453+ -> Verbosity
431454 -> Bool
432455 -> Platform
433456 -> CompilerId
434- -> [FilePath ]
435- -> [FilePath ]
457+ -> [ExtraLibsPath ]
458+ -> [ExtraIncludesPath ]
436459 -> FilePath
437460 -> IO ()
438- generateAndStoreBuildInfo verbosity profile platform (CompilerId _ghcFlavor ghcVersion) extraLibs extraIncludes path = do
461+ generateAndStoreBuildInfo cwd verbosity profile platform (CompilerId _ghcFlavor ghcVersion) extraLibs extraIncludes path = do
439462 installPath <- findCUDAInstallPath verbosity platform
440- hbi <- libraryBuildInfo verbosity profile installPath platform ghcVersion extraLibs extraIncludes
463+ hbi <- libraryBuildInfo cwd verbosity profile installPath platform ghcVersion extraLibs extraIncludes
441464 storeHookedBuildInfo verbosity path hbi
442465
443466storeHookedBuildInfo
@@ -622,21 +645,22 @@ findProgram verbosity prog = do
622645-- (generated one should be always present, as it is created in the post-conf step)
623646--
624647getHookedBuildInfo
625- :: Verbosity
648+ :: Maybe CWDPath
649+ -> Verbosity
626650 -> IO HookedBuildInfo
627- getHookedBuildInfo verbosity = do
628- doesCustomBuildInfoExists <- doesFileExist customBuildInfoFilePath
651+ getHookedBuildInfo cwd verbosity = do
652+ doesCustomBuildInfoExists <- doesFileExist ( customBuildInfoFilePath)
629653 if doesCustomBuildInfoExists
630654 then do
631655 notice verbosity $ printf " The user-provided buildinfo from file %s will be used. To use default settings, delete this file.\n " customBuildInfoFilePath
632- readHookedBuildInfo verbosity customBuildInfoFilePath
656+ readHookedBuildInfoWithCWD verbosity cwd (makeSymbolicPath customBuildInfoFilePath)
633657 else do
634658 doesGeneratedBuildInfoExists <- doesFileExist generatedBuildInfoFilePath
635659 if doesGeneratedBuildInfoExists
636660 then do
637661 notice verbosity $ printf " Using build information from '%s'.\n " generatedBuildInfoFilePath
638662 notice verbosity $ printf " Provide a '%s' file to override this behaviour.\n " customBuildInfoFilePath
639- readHookedBuildInfo verbosity generatedBuildInfoFilePath
663+ readHookedBuildInfoWithCWD verbosity cwd (makeSymbolicPath generatedBuildInfoFilePath)
640664 else
641665 die' verbosity $ printf " Unexpected failure. Neither the default %s nor custom %s exist.\n " generatedBuildInfoFilePath customBuildInfoFilePath
642666
@@ -672,7 +696,7 @@ ppC2hs bi lbi
672696getCppOptions :: BuildInfo -> LocalBuildInfo -> [String ]
673697getCppOptions bi lbi
674698 = hcDefines (compiler lbi)
675- ++ [" -I" ++ dir | dir <- includeDirs bi]
699+ ++ [" -I" ++ interpretSymbolicPath (lbiCWD lbi) dir | dir <- includeDirs bi]
676700 ++ [opt | opt@ (' -' : c: _) <- ccOptions bi, c `elem` " DIU" ]
677701
678702hcDefines :: Compiler -> [String ]
@@ -706,3 +730,66 @@ die' :: Verbosity -> String -> IO a
706730die' _ = die
707731#endif
708732
733+
734+ -- Compatibility across Cabal 3.14 symbolic paths.
735+ -- If we want to drop pre-Cabal-3.14 compatibility at some point, this should all be merged in above.
736+
737+ workingDirFlag :: HasCommonFlags flags => flags -> Flag CWDPath
738+ lbiCWD :: LocalBuildInfo -> Maybe CWDPath
739+
740+ #if MIN_VERSION_Cabal(3,14,0)
741+ type ExtraLibsPath = SymbolicPath Pkg ('Dir Lib )
742+ type ExtraIncludesPath = SymbolicPath Pkg ('Dir Include )
743+ type CWDPath = SymbolicPath CWD ('Dir Pkg )
744+
745+ regVerbosity :: RegisterFlags -> Flag Verbosity
746+ regVerbosity = setupVerbosity . registerCommonFlags
747+
748+ workingDirFlag = setupWorkingDir . getCommonFlags
749+
750+ lbiCWD = flagToMaybe . setupWorkingDir . configCommonFlags . LBC. configFlags . LBC. packageBuildDescr . localBuildDescr
751+
752+ -- makeSymbolicPath is an actual useful function in Cabal 3.14
753+ -- makeRelativePathEx is an actual useful function in Cabal 3.14
754+ -- interpretSymbolicPath is an actual useful function in Cabal 3.14
755+
756+ class HasCommonFlags flags where getCommonFlags :: flags -> CommonSetupFlags
757+ instance HasCommonFlags BuildFlags where getCommonFlags = buildCommonFlags
758+ instance HasCommonFlags CleanFlags where getCommonFlags = cleanCommonFlags
759+ instance HasCommonFlags ConfigFlags where getCommonFlags = configCommonFlags
760+ instance HasCommonFlags CopyFlags where getCommonFlags = copyCommonFlags
761+ instance HasCommonFlags InstallFlags where getCommonFlags = installCommonFlags
762+ instance HasCommonFlags HscolourFlags where getCommonFlags = hscolourCommonFlags
763+ instance HasCommonFlags HaddockFlags where getCommonFlags = haddockCommonFlags
764+ instance HasCommonFlags RegisterFlags where getCommonFlags = registerCommonFlags
765+
766+ readHookedBuildInfoWithCWD :: Verbosity -> Maybe CWDPath -> SymbolicPath Pkg 'File -> IO HookedBuildInfo
767+ readHookedBuildInfoWithCWD = readHookedBuildInfo
768+ #else
769+ type ExtraLibsPath = FilePath
770+ type ExtraIncludesPath = FilePath
771+ type CWDPath = ()
772+
773+ -- regVerbosity is still present as an actual field in Cabal 3.12
774+
775+ workingDirFlag _ = NoFlag
776+
777+ lbiCWD _ = Nothing
778+
779+ makeSymbolicPath :: FilePath -> FilePath
780+ makeSymbolicPath = id
781+
782+ makeRelativePathEx :: FilePath -> FilePath
783+ makeRelativePathEx = id
784+
785+ interpretSymbolicPath :: Maybe CWDPath -> FilePath -> FilePath
786+ interpretSymbolicPath _ = id
787+
788+ type HasCommonFlags flags = () :: Constraint
789+ getCommonFlags :: flags -> ()
790+ getCommonFlags _ = ()
791+
792+ readHookedBuildInfoWithCWD :: Verbosity -> Maybe CWDPath -> FilePath -> IO HookedBuildInfo
793+ readHookedBuildInfoWithCWD verb _ path = readHookedBuildInfo verb path
794+ #endif
795+
0 commit comments