2013-12-06 16:27:21 +00:00
|
|
|
{- Allows linking haskell programs too big for all the files to fit in a
|
|
|
|
- command line.
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- Copyright 2013 Joey Hess <joey@kitenet.net>
|
|
|
|
-
|
|
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
|
|
-}
|
|
|
|
|
|
|
|
module Main where
|
|
|
|
|
|
|
|
import Data.Maybe
|
|
|
|
import Data.Either
|
|
|
|
import Data.List
|
|
|
|
import Text.Parsec
|
|
|
|
import Text.Parsec.String
|
|
|
|
import Control.Applicative ((<$>))
|
|
|
|
import Control.Monad
|
|
|
|
|
|
|
|
import Utility.Monad
|
|
|
|
import Utility.Process
|
2013-12-06 16:43:30 +00:00
|
|
|
import System.Directory
|
2013-12-06 16:27:21 +00:00
|
|
|
|
2013-12-06 16:43:30 +00:00
|
|
|
data CmdParams = CmdParams { cmd :: String, opts :: String }
|
2013-12-06 16:27:21 +00:00
|
|
|
deriving (Show)
|
|
|
|
|
2013-12-06 16:43:30 +00:00
|
|
|
{- Find where ghc calls gcc to link the executable. -}
|
2013-12-06 16:27:21 +00:00
|
|
|
parseGhcLink :: Parser CmdParams
|
|
|
|
parseGhcLink = do
|
|
|
|
many prelinklines
|
|
|
|
linkheaderline
|
|
|
|
char '"'
|
|
|
|
gcccmd <- many1 (noneOf "\"")
|
|
|
|
string "\" "
|
|
|
|
gccparams <- restOfLine
|
|
|
|
return $ CmdParams gcccmd gccparams
|
|
|
|
where
|
|
|
|
linkheaderline = do
|
|
|
|
string "*** Linker"
|
|
|
|
restOfLine
|
|
|
|
prelinklines = do
|
|
|
|
notFollowedBy linkheaderline
|
|
|
|
restOfLine
|
|
|
|
|
2013-12-06 16:43:30 +00:00
|
|
|
{- Find where gcc calls collect1. -}
|
2013-12-06 16:48:39 +00:00
|
|
|
parseGccLink :: Parser CmdParams
|
|
|
|
parseGccLink = error "TODO"
|
2013-12-06 16:43:30 +00:00
|
|
|
|
|
|
|
{- Find where collect1 calls ld. -}
|
2013-12-06 16:48:39 +00:00
|
|
|
parseCollect1 :: Parser CmdParams
|
|
|
|
parseCollect1 = error "TODO"
|
2013-12-06 16:43:30 +00:00
|
|
|
|
2013-12-06 16:27:21 +00:00
|
|
|
restOfLine :: Parser String
|
|
|
|
restOfLine = newline `after` many (noneOf "\n")
|
|
|
|
|
2013-12-06 16:48:39 +00:00
|
|
|
{- Intentionally ignores command failure; the whole point is to work around
|
|
|
|
- that. -}
|
2013-12-06 16:27:21 +00:00
|
|
|
getOutput :: String -> [String] -> IO String
|
|
|
|
getOutput cmd params = do
|
|
|
|
putStrLn $ unwords [cmd, show params]
|
2013-12-06 16:48:39 +00:00
|
|
|
(log, _ok) <- processTranscript cmd params Nothing
|
2013-12-06 16:27:21 +00:00
|
|
|
return log
|
|
|
|
|
|
|
|
runParser' :: Parser a -> String -> a
|
|
|
|
runParser' p s = either (error . show) id (parse p "" s)
|
|
|
|
|
2013-12-06 16:43:30 +00:00
|
|
|
atFile :: FilePath -> String
|
|
|
|
atFile f = '@':f
|
|
|
|
|
|
|
|
runAtFile :: Parser CmdParams -> String -> FilePath -> [String] -> IO String
|
|
|
|
runAtFile p s f extraparams = do
|
|
|
|
writeFile f (opts c)
|
|
|
|
out <- getOutput (cmd c) (atFile f:extraparams)
|
|
|
|
removeFile f
|
|
|
|
return out
|
|
|
|
where
|
|
|
|
c = runParser' p s
|
|
|
|
|
2013-12-06 16:27:21 +00:00
|
|
|
main = do
|
|
|
|
ghcout <- getOutput "cabal"
|
|
|
|
["build", "--ghc-options=-v -keep-tmp-files"]
|
2013-12-06 16:43:30 +00:00
|
|
|
gccout <- runAtFile parseGhcLink ghcout "gcc.opt" ["-v"]
|
2013-12-06 16:44:40 +00:00
|
|
|
writeFile "gcc.out" gccout
|
2013-12-06 16:48:39 +00:00
|
|
|
collect1out <- runAtFile parseGccLink gccout "collect1.opt" ["-v"]
|
2013-12-06 16:44:40 +00:00
|
|
|
writeFile "collect1.out" collect1out
|
2013-12-06 16:48:39 +00:00
|
|
|
void $ runAtFile parseCollect1 collect1out "ld.opt" []
|