/src/Mkrt.hs

http://github.com/Eelis/geordi · Haskell · 81 lines · 72 code · 8 blank · 1 comment · 8 complexity · da7285d8a8925bb73a4b56755e7cb3d0 MD5 · raw file

  1. {-# LANGUAGE UnicodeSyntax, ViewPatterns #-}
  2. import System.Posix (createFile, createDirectory, closeFd,
  3. FileMode, unionFileModes, accessModes, nullFileMode,
  4. ownerReadMode, ownerWriteMode, ownerExecuteMode,
  5. groupReadMode, groupWriteMode, groupExecuteMode,
  6. otherReadMode, otherWriteMode, otherExecuteMode,
  7. setFileCreationMask)
  8. import System.Process (readProcessWithExitCode)
  9. import System.Exit (ExitCode(..))
  10. import System.Directory (createDirectoryIfMissing, copyFile, doesFileExist)
  11. import System.FilePath (takeDirectory, (</>))
  12. import System.IO (hFlush, stdout)
  13. import System.IO.Unsafe (unsafePerformIO)
  14. import System.Environment (getEnv)
  15. import Control.Monad (when, forM)
  16. import Text.Regex (matchRegex, mkRegex)
  17. import Data.Maybe (mapMaybe)
  18. import Data.List (nub)
  19. import Util (findM, (.))
  20. import Prelude hiding ((.))
  21. import Prelude.Unicode
  22. import Paths_geordi (getDataFileName)
  23. import CompileConfig
  24. split_paths :: String ? [FilePath]
  25. split_paths [] = []
  26. split_paths (span (/= ':') ? (f, r)) = f : split_paths (drop 1 r)
  27. which :: String ? IO (Maybe FilePath)
  28. which s = getEnv "PATH" >>= findM doesFileExist . (s:) . map (</> s) . filter (not . null) . split_paths
  29. modes :: [FileMode] ? FileMode
  30. modes = foldl1 unionFileModes
  31. readModes, writeModes, executeModes :: FileMode
  32. readModes = modes [ownerReadMode, groupReadMode, otherReadMode]
  33. writeModes = modes [ownerWriteMode, groupWriteMode, otherWriteMode]
  34. executeModes = modes [ownerExecuteMode, groupExecuteMode, otherExecuteMode]
  35. ldd :: FilePath ? IO [FilePath]
  36. ldd f = do
  37. (status, out, err) ? readProcessWithExitCode "ldd" [f] ""
  38. if status ? ExitSuccess then error err else do
  39. return $ map head $ mapMaybe (matchRegex $ mkRegex "[[:blank:]](/[^[:blank:]]*)") $ lines out
  40. compiler_files :: IO [FilePath]
  41. compiler_files = (nub .) $ do
  42. gxx ? gxxPath . readCompileConfig
  43. let
  44. query_gxx q = do
  45. (status, out, err) ? readProcessWithExitCode gxx [q] ""
  46. if status /= ExitSuccess then error err else do
  47. return $ head $ lines out
  48. fs ? (concat .) $ forM l $ \f ? do
  49. out ? query_gxx $ "-print-file-name=" ++ f
  50. return [out | out ? f]
  51. fs' ? (concat .) $ forM ["cc1plus", "as", "ld"] $ \p ? do
  52. mf ? query_gxx ("-print-prog-name=" ++ p) >>= which
  53. case mf of
  54. Nothing ? error $ "could not find " ++ p
  55. Just f ? (f:) . ldd f
  56. gxxlibs ? ldd gxx
  57. return $ gxx : gxxlibs ++ fs ++ fs'
  58. where l = words "crt1.o crti.o crtn.o crtbegin.o crtend.o libgcc.a libgcc_s.so libstdc++.so libstdc++.so.6 libmcheck.a libc.so libc_nonshared.a libm.so libm.so.6 libc.so.6 libgcc_s.so.1"
  59. main :: IO ()
  60. main = do
  61. setFileCreationMask $ modes [groupWriteMode, otherWriteMode]
  62. rt ? getDataFileName "rt"
  63. putStr $ "Setting up " ++ rt ++ " ..."
  64. hFlush stdout
  65. (compiler_files >>=) $ mapM_ $ \f ? do
  66. let to = rt ++ "/" ++ f -- can't use </> here because f is absolute
  67. createDirectoryIfMissing True $ takeDirectory to
  68. copyFile f to
  69. setFileCreationMask nullFileMode
  70. createFile (rt </> "lock") readModes >>= closeFd
  71. createFile (rt </> "t") accessModes >>= closeFd
  72. forM ["t.cpp", "t.s", "t.o"] $ (>>= closeFd) . flip createFile (unionFileModes writeModes readModes) . (rt </>)
  73. putStrLn " done."