Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
-
72c55eee
by Cheng Shao at 2026-07-28T16:43:11-04:00
14 changed files:
- hadrian/src/Hadrian/Builder/Ar.hs
- hadrian/src/Hadrian/Utilities.hs
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Rules/CabalReinstall.hs
- hadrian/src/Rules/Documentation.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Library.hs
- hadrian/src/Rules/Nofib.hs
- hadrian/src/Rules/Program.hs
- hadrian/src/Rules/Register.hs
- hadrian/src/Rules/Rts.hs
- hadrian/src/Rules/SourceDist.hs
- hadrian/src/Rules/Test.hs
- hadrian/src/Rules/ToolArgs.hs
Changes:
| ... | ... | @@ -43,7 +43,7 @@ runAr :: FilePath -- ^ base name to use for response files |
| 43 | 43 | -> Action ()
|
| 44 | 44 | runAr outputFilePath arPath flagArgs fileArgs buildOptions = do
|
| 45 | 45 | rspFile <- responseFilePath outputFilePath
|
| 46 | - writeFile' rspFile $ unwords fileArgs
|
|
| 46 | + writeFileAtomic rspFile $ unwords fileArgs
|
|
| 47 | 47 | cmd [arPath] flagArgs ('@' : rspFile) buildOptions
|
| 48 | 48 | |
| 49 | 49 | -- | Invoke @ar@ given a path to it and a list of arguments. Note that @ar@
|
| ... | ... | @@ -21,7 +21,9 @@ module Hadrian.Utilities ( |
| 21 | 21 | -- * File system operations
|
| 22 | 22 | copyFile, copyFileUntracked, createFileLink, fixFile,
|
| 23 | 23 | makeExecutable, moveFile, removeFile, createDirectory, copyDirectory,
|
| 24 | - moveDirectory, removeDirectory, removeFile_, writeFileChangedBS,
|
|
| 24 | + moveDirectory, removeDirectory, removeFile_,
|
|
| 25 | + writeFileAtomic, writeFileLinesAtomic,
|
|
| 26 | + writeFileChangedBS,
|
|
| 25 | 27 | |
| 26 | 28 | -- * Diagnostic info
|
| 27 | 29 | Colour (..), ANSIColour (..), putColoured, shouldUseColor,
|
| ... | ... | @@ -48,6 +50,7 @@ import Data.List.Extra |
| 48 | 50 | import Data.Maybe
|
| 49 | 51 | import Data.Typeable (TypeRep, typeOf)
|
| 50 | 52 | import Development.Shake hiding (Normal)
|
| 53 | +import qualified Development.Shake as Shake
|
|
| 51 | 54 | import Development.Shake.Classes
|
| 52 | 55 | import Development.Shake.Command (CmdArgument (..), IsCmdArgument (toCmdArgument))
|
| 53 | 56 | import Development.Shake.FilePath
|
| ... | ... | @@ -341,7 +344,7 @@ withResponseFileIfLongCmd outputFilePath argsPre argsResp argsPost = do |
| 341 | 344 | then cmd argsPre argsResp argsPost
|
| 342 | 345 | else do
|
| 343 | 346 | rspFile <- responseFilePath outputFilePath
|
| 344 | - writeFile' rspFile (escapeArgs argsResp)
|
|
| 347 | + writeFileAtomic rspFile (escapeArgs argsResp)
|
|
| 345 | 348 | cmd argsPre ['@' : rspFile] argsPost
|
| 346 | 349 | |
| 347 | 350 | -- | Convert a command's output file path to a response file path to be used for that command.
|
| ... | ... | @@ -400,6 +403,19 @@ copyFileUntracked source target = do |
| 400 | 403 | putProgressInfo =<< renderAction "Copy file (untracked)" source target
|
| 401 | 404 | liftIO $ IO.copyFile source target
|
| 402 | 405 | |
| 406 | +-- | An atomic version of Shake's 'Shake.writeFile''.
|
|
| 407 | +writeFileAtomic :: FilePath -> String -> Action ()
|
|
| 408 | +writeFileAtomic file contents = do
|
|
| 409 | + let dir = takeDirectory file
|
|
| 410 | + liftIO $ IO.createDirectoryIfMissing True dir
|
|
| 411 | + withTempFileWithin dir $ \temp -> do
|
|
| 412 | + Shake.writeFile' temp contents
|
|
| 413 | + liftIO $ IO.renameFile temp file
|
|
| 414 | + |
|
| 415 | +-- | An atomic version of Shake's 'Shake.writeFileLines'.
|
|
| 416 | +writeFileLinesAtomic :: FilePath -> [String] -> Action ()
|
|
| 417 | +writeFileLinesAtomic file = writeFileAtomic file . unlines
|
|
| 418 | + |
|
| 403 | 419 | -- | Transform a given file by applying a function to its contents.
|
| 404 | 420 | fixFile :: FilePath -> (String -> String) -> Action ()
|
| 405 | 421 | fixFile file f = do
|
| ... | ... | @@ -409,7 +425,7 @@ fixFile file f = do |
| 409 | 425 | let new = f old
|
| 410 | 426 | IO.evaluate $ rnf new
|
| 411 | 427 | return new
|
| 412 | - liftIO $ writeFile file contents
|
|
| 428 | + writeFileAtomic file contents
|
|
| 413 | 429 | |
| 414 | 430 | -- | Make a given file executable by running the @chmod +x@ command.
|
| 415 | 431 | makeExecutable :: FilePath -> Action ()
|
| ... | ... | @@ -234,7 +234,7 @@ buildBinDistDir root conf@BindistConfig{..} = do |
| 234 | 234 | bindistContext = vanillaContext library_stage compiler
|
| 235 | 235 | bindistSettingsContent <- interpretInContext bindistContext $
|
| 236 | 236 | generateSettings bindistSettings False "package.conf.d"
|
| 237 | - writeFile' bindistSettings bindistSettingsContent
|
|
| 237 | + writeFileAtomic bindistSettings bindistSettingsContent
|
|
| 238 | 238 | |
| 239 | 239 | copyDirectory rtsIncludeDir bindistFilesDir
|
| 240 | 240 | when windowsHost $ createGhcii (bindistFilesDir -/- "bin")
|
| ... | ... | @@ -296,7 +296,7 @@ buildBinDistDir root conf@BindistConfig{..} = do |
| 296 | 296 | need $ map (bindistFilesDir -/-)
|
| 297 | 297 | (["configure", "Makefile"] ++ bindistInstallFiles)
|
| 298 | 298 | copyFile ("hadrian" -/- "bindist" -/- "config.mk.in") (bindistFilesDir -/- "config.mk.in")
|
| 299 | - generateBuildMk conf >>= writeFile' (bindistFilesDir -/- "build.mk")
|
|
| 299 | + generateBuildMk conf >>= writeFileAtomic (bindistFilesDir -/- "build.mk")
|
|
| 300 | 300 | copyFile ("hadrian" -/- "cfg" -/- "default.target.in") (bindistFilesDir -/- "default.target.in")
|
| 301 | 301 | copyFile ("hadrian" -/- "cfg" -/- "default.host.target.in") (bindistFilesDir -/- "default.host.target.in")
|
| 302 | 302 | |
| ... | ... | @@ -314,7 +314,7 @@ buildBinDistDir root conf@BindistConfig{..} = do |
| 314 | 314 | versioned_wrapper = wrapper_name ++ "-" ++ suffix
|
| 315 | 315 | versioned_wrapper_path = bindistFilesDir -/- "wrappers" -/- versioned_wrapper
|
| 316 | 316 | -- Write the wrapper to the versioned path
|
| 317 | - writeFile' versioned_wrapper_path wrapper_content
|
|
| 317 | + writeFileAtomic versioned_wrapper_path wrapper_content
|
|
| 318 | 318 | -- Create a symlink from the non-versioned to the versioned.
|
| 319 | 319 | liftIO $ do
|
| 320 | 320 | IO.removeFile unversioned_wrapper_path <|> return ()
|
| ... | ... | @@ -38,7 +38,7 @@ cabalBuildRules = do |
| 38 | 38 | withVerbosity Diagnostic $
|
| 39 | 39 | buildWithCmdOptions [] $
|
| 40 | 40 | target (vanillaContext Stage2 pkg) (Cabal Install Stage2) [] []
|
| 41 | - liftIO $ writeFile outpath "done"
|
|
| 41 | + writeFileAtomic outpath "done"
|
|
| 42 | 42 | |
| 43 | 43 | phony "build-cabal" $ need [root -/- "stage-cabal" -/- "bin" -/- ".stamp"]
|
| 44 | 44 | |
| ... | ... | @@ -86,8 +86,8 @@ cabalBuildRules = do |
| 86 | 86 | ]
|
| 87 | 87 | output_file = outputDir -/- wrapper_name
|
| 88 | 88 | wrapper_content <- wrapper Stage2 wrapper_name
|
| 89 | - writeFile' output_file (wrapper_prefix ++ wrapper_content)
|
|
| 89 | + writeFileAtomic output_file (wrapper_prefix ++ wrapper_content)
|
|
| 90 | 90 | makeExecutable output_file
|
| 91 | 91 | pure ()
|
| 92 | 92 | |
| 93 | - writeFile' stamp "OK" |
|
| 93 | + writeFileAtomic stamp "OK" |
| ... | ... | @@ -268,7 +268,7 @@ buildPackageDocumentation = do |
| 268 | 268 | syn <- pkgSynopsis (Context.package ctx)
|
| 269 | 269 | desc <- pkgDescription (Context.package ctx)
|
| 270 | 270 | let prologue = if null desc then syn else desc
|
| 271 | - liftIO $ writeFile file prologue
|
|
| 271 | + writeFileAtomic file prologue
|
|
| 272 | 272 | |
| 273 | 273 | root -/- htmlRoot -/- "libraries/*/*.haddock" %> \file -> do
|
| 274 | 274 | context <- pkgDocContext =<< getPkgDocTarget root file
|
| ... | ... | @@ -353,7 +353,7 @@ templateRuleFrom inPath outPath interps = do |
| 353 | 353 | outPath %> \_ -> do
|
| 354 | 354 | s <- readFile' inPath
|
| 355 | 355 | result <- runInterpolations interps s
|
| 356 | - writeFile' outPath result
|
|
| 356 | + writeFileAtomic outPath result
|
|
| 357 | 357 | putSuccess ("| Successfully generated " ++ outPath ++ " from its template")
|
| 358 | 358 | |
| 359 | 359 | templateRule :: FilePath -> Interpolations -> Rules ()
|
| ... | ... | @@ -140,7 +140,7 @@ buildPackage root fp = do |
| 140 | 140 | -- Write the current time into the file so the file always changes if
|
| 141 | 141 | -- we restamp it because a dependency changes.
|
| 142 | 142 | time <- liftIO $ getCurrentTime
|
| 143 | - liftIO $ writeFile fp (show time)
|
|
| 143 | + writeFileAtomic fp (show time)
|
|
| 144 | 144 | ways <- interpretInContext ctx getLibraryWays
|
| 145 | 145 | let hasVanilla = elem vanilla ways
|
| 146 | 146 | hasDynamic = elem dynamic ways
|
| ... | ... | @@ -148,7 +148,7 @@ buildPackage root fp = do |
| 148 | 148 | when ((hasVanilla && hasDynamic) &&
|
| 149 | 149 | support && way == vanilla) $ do
|
| 150 | 150 | stamp <- (pkgStampFile (ctx { way = dynamic }))
|
| 151 | - liftIO $ writeFile stamp (show time)
|
|
| 151 | + writeFileAtomic stamp (show time)
|
|
| 152 | 152 | |
| 153 | 153 | |
| 154 | 154 |
| ... | ... | @@ -42,7 +42,7 @@ nofibRules = do |
| 42 | 42 | unit $ cmd (Cwd "nofib") [makePath] ["clean"]
|
| 43 | 43 | unit $ cmd (Cwd "nofib") [makePath] (nofibArgs ++ ["boot"])
|
| 44 | 44 | (Exit e, Stdouterr log) <- cmd (Cwd "nofib") [makePath] nofibArgs
|
| 45 | - writeFile' fp log
|
|
| 45 | + writeFileAtomic fp log
|
|
| 46 | 46 | if e == ExitSuccess
|
| 47 | 47 | then putVerbose $ "nofib log available at " ++ fp
|
| 48 | 48 | else error $ "nofib failed, full log available at " ++ fp
|
| ... | ... | @@ -32,7 +32,7 @@ buildProgramRules rs = do |
| 32 | 32 | top <- topDirectory
|
| 33 | 33 | need [ top -/- "configure" ]
|
| 34 | 34 | copyDirectory (top -/- "inplace" -/- "mingw") root
|
| 35 | - writeFile' stampPath "OK"
|
|
| 35 | + writeFileAtomic stampPath "OK"
|
|
| 36 | 36 | |
| 37 | 37 | -- Rules for programs that are actually built by hadrian.
|
| 38 | 38 | forM_ allStages $ \stage ->
|
| ... | ... | @@ -94,7 +94,7 @@ registerPackageRules rs stage iplace = do |
| 94 | 94 | -- leads to errors in GHC).
|
| 95 | 95 | buildWithResources rs $
|
| 96 | 96 | target (Context stage compiler vanilla iplace) (GhcPkg Recache stage) [] []
|
| 97 | - writeFileLines stamp []
|
|
| 97 | + writeFileLinesAtomic stamp []
|
|
| 98 | 98 | |
| 99 | 99 | -- Special rule for registering system-cxx-std-lib
|
| 100 | 100 | root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- systemCxxStdLibConf %> \file -> do
|
| ... | ... | @@ -21,7 +21,7 @@ buildGhcInternalImportDef target = do |
| 21 | 21 | templateIn <- readFile' "rts/win32/libHSghc-internal.def.in"
|
| 22 | 22 | let dllName = takeFileName target -<.> "dll"
|
| 23 | 23 | templateOut = replace "@GhcInternalDll@" dllName templateIn
|
| 24 | - writeFile' target templateOut
|
|
| 24 | + writeFileAtomic target templateOut
|
|
| 25 | 25 | |
| 26 | 26 | buildGhcInternalImportLib :: Stage -> FilePath -> Action ()
|
| 27 | 27 | buildGhcInternalImportLib stg target = do
|
| ... | ... | @@ -36,7 +36,7 @@ sourceDistRules = alternatives $ do |
| 36 | 36 | need [mingw_tarballs_stamp]
|
| 37 | 37 | mingw_tarballs_stamp %> \stamp -> do
|
| 38 | 38 | build (target (vanillaContext Stage1 compiler) (Win32Tarballs DownloadTarballs) [] [])
|
| 39 | - writeFile' stamp "OK"
|
|
| 39 | + writeFileAtomic stamp "OK"
|
|
| 40 | 40 | |
| 41 | 41 | |
| 42 | 42 | archiveSourceTree :: (FilePath -> Action ()) -> FilePath -> Action ()
|
| ... | ... | @@ -328,7 +328,7 @@ timeoutProgBuilder = do |
| 328 | 328 | let script = unlines
|
| 329 | 329 | [ "#!/bin/sh"
|
| 330 | 330 | , "exec " ++ python ++ " $0.py \"$@\"" ]
|
| 331 | - writeFile' (root -/- timeoutPath) script
|
|
| 331 | + writeFileAtomic (root -/- timeoutPath) script
|
|
| 332 | 332 | makeExecutable (root -/- timeoutPath)
|
| 333 | 333 | |
| 334 | 334 | -- | Build extra programs and libraries required by testsuite
|
| ... | ... | @@ -63,7 +63,7 @@ multiSetup pkg_s = do |
| 63 | 63 | -- Get the arguments for all the targets
|
| 64 | 64 | pargs <- mapM one_args tool_targets
|
| 65 | 65 | -- Build any other dependencies (such as generated files)
|
| 66 | - liftIO $ writeOutput (concatMap (\x -> ["-unit", x]) (map ( "@" <>) pargs))
|
|
| 66 | + writeOutput (concatMap (\x -> ["-unit", x]) (map ( "@" <>) pargs))
|
|
| 67 | 67 | |
| 68 | 68 | where
|
| 69 | 69 | resp_file root p = root </> "multi" </> pkgName p
|
| ... | ... | @@ -96,7 +96,7 @@ multiSetup pkg_s = do |
| 96 | 96 | normalisePackageIds (x:xs) = x : normalisePackageIds xs
|
| 97 | 97 | normalisePackageIds [] = []
|
| 98 | 98 | |
| 99 | - writeFile' (resp_file root p) (intercalate "\n" (normalise_ghc arg_list
|
|
| 99 | + writeFileAtomic (resp_file root p) (intercalate "\n" (normalise_ghc arg_list
|
|
| 100 | 100 | ++ modules cd
|
| 101 | 101 | ++ concatMap rexp (reexportModules cd)
|
| 102 | 102 | ++ ["-outputdir", hidir,
|
| ... | ... | @@ -112,11 +112,12 @@ toolRuleBody fp = do |
| 112 | 112 | Just (_, (p, extra)) -> mkToolTarget extra p
|
| 113 | 113 | Nothing -> fail $ "No prefixes matched " ++ show fp ++ " IN\n " ++ show mm
|
| 114 | 114 | |
| 115 | -writeOutput :: [String] -> IO ()
|
|
| 115 | +writeOutput :: [String] -> Action ()
|
|
| 116 | 116 | writeOutput args = do
|
| 117 | - liftIO $ lookupEnv "TOOL_OUTPUT" >>= \case
|
|
| 118 | - Nothing -> putStrLn (intercalate "\n" args)
|
|
| 119 | - Just out -> writeFile out (intercalate "\n" args)
|
|
| 117 | + output <- liftIO $ lookupEnv "TOOL_OUTPUT"
|
|
| 118 | + case output of
|
|
| 119 | + Nothing -> liftIO $ putStrLn (intercalate "\n" args)
|
|
| 120 | + Just out -> writeFileAtomic out (intercalate "\n" args)
|
|
| 120 | 121 | |
| 121 | 122 | mkToolTarget :: [String] -> Package -> Action ()
|
| 122 | 123 | mkToolTarget es p = do
|
| ... | ... | @@ -138,7 +139,7 @@ mkToolTarget es p = do |
| 138 | 139 | need (gens ++ srcs ++ dep_confs)
|
| 139 | 140 | |
| 140 | 141 | arg_list <- interpret fake_target getArgs
|
| 141 | - liftIO $ writeOutput (arg_list ++ es)
|
|
| 142 | + writeOutput (arg_list ++ es)
|
|
| 142 | 143 | |
| 143 | 144 | -- This list is quite a lot like stage0packages but doesn't include
|
| 144 | 145 | -- critically the `exe:ghc` component as that depends on the GHC library
|
| ... | ... | @@ -200,4 +201,3 @@ dirMap = do |
| 200 | 201 | cd <- readContextData c
|
| 201 | 202 | ids <- liftIO $ mapM canonicalizePath [pkgPath p </> i | i <- srcDirs cd]
|
| 202 | 203 | return $ map (,(p, modules cd ++ otherModules cd)) ids |
| 203 | - |