1+ {-# LANGUAGE CPP #-}
12{-# LANGUAGE NoImplicitPrelude #-}
23{-# LANGUAGE DeriveGeneric #-}
34{-# LANGUAGE MultiParamTypeClasses #-}
@@ -32,14 +33,16 @@ module Stack.Build.Cache
3233 , BuildCache (.. )
3334 ) where
3435
35- import Stack.Constants
3636import Stack.Prelude
3737import Crypto.Hash (hashWith , SHA256 (.. ))
3838import Control.Monad.Trans.Maybe
3939import qualified Data.ByteArray as Mem (convert )
4040import qualified Data.ByteString.Base64.URL as B64URL
4141import qualified Data.ByteString as B
4242import qualified Data.ByteString.Char8 as S8
43+ #ifdef mingw32_HOST_OS
44+ import Data.Char (ord )
45+ #endif
4346import qualified Data.Map as M
4447import qualified Data.Set as Set
4548import qualified Data.Store as Store
@@ -107,10 +110,24 @@ markExeNotInstalled loc ident = do
107110 ident' <- parseRelFile $ packageIdentifierString ident
108111 liftIO $ ignoringAbsence (removeFile $ dir </> ident')
109112
113+ buildCacheFile :: (HasEnvConfig env , MonadReader env m , MonadThrow m )
114+ => Path Abs Dir
115+ -> NamedComponent
116+ -> m (Path Abs File )
117+ buildCacheFile dir component = do
118+ cachesDir <- buildCachesDir dir
119+ let nonLibComponent prefix name = prefix <> " -" <> T. unpack name
120+ cacheFileName <- parseRelFile $ case component of
121+ CLib -> " lib"
122+ CExe name -> nonLibComponent " exe" name
123+ CTest name -> nonLibComponent " test" name
124+ CBench name -> nonLibComponent " bench" name
125+ return $ cachesDir </> cacheFileName
126+
110127-- | Try to read the dirtiness cache for the given package directory.
111128tryGetBuildCache :: (MonadUnliftIO m , MonadReader env m , MonadThrow m , MonadLogger m , HasEnvConfig env )
112- => Path Abs Dir -> m (Maybe (Map FilePath FileCacheInfo ))
113- tryGetBuildCache dir = liftM (fmap buildCacheTimes) . $ (versionedDecodeFile buildCacheVC) =<< buildCacheFile dir
129+ => Path Abs Dir -> NamedComponent -> m (Maybe (Map FilePath FileCacheInfo ))
130+ tryGetBuildCache dir component = liftM (fmap buildCacheTimes) . $ (versionedDecodeFile buildCacheVC) =<< buildCacheFile dir component
114131
115132-- | Try to read the dirtiness cache for the given package directory.
116133tryGetConfigCache :: (MonadUnliftIO m , MonadReader env m , MonadThrow m , HasEnvConfig env , MonadLogger m )
@@ -124,9 +141,9 @@ tryGetCabalMod dir = $(versionedDecodeFile modTimeVC) =<< configCabalMod dir
124141
125142-- | Write the dirtiness cache for this package's files.
126143writeBuildCache :: (MonadIO m , MonadReader env m , MonadThrow m , HasEnvConfig env , MonadLogger m )
127- => Path Abs Dir -> Map FilePath FileCacheInfo -> m ()
128- writeBuildCache dir times = do
129- fp <- buildCacheFile dir
144+ => Path Abs Dir -> NamedComponent -> Map FilePath FileCacheInfo -> m ()
145+ writeBuildCache dir component times = do
146+ fp <- buildCacheFile dir component
130147 $ (versionedEncodeFile buildCacheVC) fp BuildCache
131148 { buildCacheTimes = times
132149 }
@@ -287,14 +304,12 @@ precompiledCacheFile loc copts installedPackageIDs = do
287304 -- See #3649 - shorten the paths on windows if MAX_PATH will be
288305 -- violated. Doing this only when necessary allows use of existing
289306 -- precompiled packages.
290- case maxPathLength of
291- Nothing -> return longPath
292- Just maxPath
293- | length (toFilePath longPath) > maxPath -> do
294- shortPkg <- shaPath pkg
295- shortHash <- shaPath hashPath
296- return $ precompiledDir </> shortPkg </> shortHash
297- | otherwise -> return longPath
307+ if pathTooLong (toFilePath longPath) then do
308+ shortPkg <- shaPath pkg
309+ shortHash <- shaPath hashPath
310+ return $ precompiledDir </> shortPkg </> shortHash
311+ else
312+ return longPath
298313
299314-- | Write out information about a newly built package
300315writePrecompiledCache :: (MonadThrow m , MonadReader env m , HasEnvConfig env , MonadIO m , MonadLogger m )
@@ -353,3 +368,20 @@ readPrecompiledCache loc copts depIDs = runMaybeT $
353368 { pcLibrary = mkAbs' <$> pcLibrary pc0
354369 , pcExes = mkAbs' <$> pcExes pc0
355370 }
371+
372+ -- | Check if a filesystem path is too long.
373+ pathTooLong :: FilePath -> Bool
374+ #ifdef mingw32_HOST_OS
375+ pathTooLong path = utf16StringLength path >= win32MaxPath
376+ where
377+ win32MaxPath = 260
378+ -- Calculate the length of a string in 16-bit units
379+ -- if it were converted to utf-16.
380+ utf16StringLength :: String -> Integer
381+ utf16StringLength = sum . map utf16CharLength
382+ where
383+ utf16CharLength c | ord c < 0x10000 = 1
384+ | otherwise = 2
385+ #else
386+ pathTooLong _ = False
387+ #endif
0 commit comments