[nhc-users]
hmake: Getting compiler info at runtime and not relying on name for
compiler type
Ian Lynagh
igloo at earth.li
Fri Sep 26 02:03:45 EDT 2003
Hi,
Attached is a patch which does two things:
* Gets compiler type from the result of running a compiler if the first
3 letters aren't ghc|nhc|hbc|gcc. I wanted this for
/usr/bin/haskell-compiler.
* If "hmake-config add-dyn" is used instead of "hmake add" then the
compiler information is not stored, but worked out dynamically when
used. This means /usr/bin/haskell-compiler can be the default hmake
compiler on a Debian installation and it doesn't matter if it is
really nhc98, ghc6 or ghc5, and there is no need to require specific
versions of the compilers.
It could be a bit nicer, e.g. I didn't notice runAndReadStdout until I
was half way through, but it seems to work for me.
Thanks
Ian
-------------- next part --------------
--- hmake-3.08.orig/src/hmake/Makefile
+++ hmake-3.08/src/hmake/Makefile
@@ -9,9 +9,9 @@
SRCS = QSort.hs Unlit.hs Utils.hs Tsort.hs FileName.hs SymTab.hs \
Output.hs Order.hs ListUtil.hs Getmodtime.hs \
MkProg.hs IsPrefixOf.hs Compiler.hs PreProcessor.hs \
- PackageConfig.hs Config.hs RunAndReadStdout.hs
+ PackageConfig.hs RunAndReadStdout.hs
CPPSRCS = Argv.hs Graph.hs GetDep.hs ParseLib.hs Compat.hs Imports.hs \
- Platform.hs
+ Platform.hs Config.hs
CFGSRCS = RunAndReadStdout.hs Config.hs Compiler.hs Platform.hs
OBJS = $(patsubst %.hs, $(OBJDIR)/%.$O, $(SRCS))
@@ -25,12 +25,13 @@
hmake hmake.1
HC = $(LOCAL)nhc98 # can be overridden by caller HC=...
+BUILDCOMP = nhc # Override if you override the above. Should be ghc|nhc|hbc|gcc
HFLAGS = $(shell echo $(BUILDOPTS)) #-$(CFG)
-ifeq "nhc98" "$(findstring nhc98, ${HC})"
+ifeq "nhc" "${BUILDCOMP}"
HEAP = -H4M
endif
-ifeq "ghc" "$(findstring ghc, ${HC})"
+ifeq "ghc" "${BUILDCOMP}"
HFLAGS += $(shell ${LOCAL}fixghc ${GHCSYM} -package lang)
endif
@@ -102,7 +103,8 @@
${OBJDIR}/FileName.$O ${OBJDIR}/Unlit.$O \
${OBJDIR}/Argv.$O ${OBJDIR}/PreProcessor.$O \
${OBJDIR}/Config.$O
-${OBJDIR}/Config.$O: ${OBJDIR}/Compiler.$O ${OBJDIR}/Platform.$O
+${OBJDIR}/Config.$O: ${OBJDIR}/Compiler.$O ${OBJDIR}/Platform.$O \
+ ${OBJDIR}/RunAndReadStdout.$O
${OBJDIR}/Compiler.$O:
${OBJDIR}/ListUtil.$O:
${OBJDIR}/Argv.$O: ${OBJDIR}/ListUtil.$O ${OBJDIR}/Compiler.$O \
@@ -117,7 +119,7 @@
${OBJDIR}/Platform.$O
${OBJDIR}/Older.$O:
-ifeq "hbc" "$(HC)"
+ifeq "hbc" "${BUILDCOMP}"
${OBJDIR}/Argv.$O: ${OBJDIR}/IsPrefixOf.$O
endif
--- hmake-3.08.orig/src/hmake/Argv.hs
+++ hmake-3.08/src/hmake/Argv.hs
@@ -53,21 +53,10 @@
, compiler :: CompilerConfig -- chosen compiler
}
-decode :: [String] -> DecodedArgs
-decode progArgs =
+decode :: [String] -> IO DecodedArgs
+decode progArgs = do
let d = Decoded {
modules = (map wrapGoal . filter (not . isflag)) progArgs
- , pathSrc = (map tail . filter (\v -> head v == 'I')) flags ++
- (map tail . filter (\v -> head v == 'i')) flags ++
- if isopt "keepPrelude" then pathPrel d else []
- , pathPrel = (map tail . filter (\v -> head v == 'P')) flags ++
- includePaths (compiler d) ++
- packageDirs (compiler d)
- (map (drop 8) $
- filter ("package="`isPrefixOf`) flags)
- , zdefs = (map tail . filter (\v -> head v == 'Z')) flags ++
- cppSymbols (compiler d) ++
- (if isHaskell98 (compiler d) then haskell98SymsForCpp else [])
, defs = (map tail . filter (\v -> head v == 'D')) flags
, ignoreHi = (map tail . filter (\v -> head v == 'N')) flags
, dflag = False -- isopt "od"
@@ -94,12 +83,27 @@
{ globalConfig = readConfig (tail x)
, localConfig = Nothing }
_ -> error "hmake: only one -fconfigfile option allowed\n"
- , compiler = case filter (\v-> "hc=" `isPrefixOf` v) flags of
- [] -> usualCompiler (config d)
- [x] -> matchCompiler (drop 3 x) (config d)
- _ -> error "hmake: only one -hc=compiler option allowed\n"
+ , compiler = error "compiler not yet known"
+ }
+ cc <- unDyn $ case filter (\v-> "hc=" `isPrefixOf` v) flags of
+ [] -> usualCompiler (config d)
+ [x] -> matchCompiler (drop 3 x) (config d)
+ _ -> error "hmake: only one -hc=compiler option allowed\n"
+ let d' = d {
+ pathSrc = (map tail . filter (\v -> head v == 'I')) flags ++
+ (map tail . filter (\v -> head v == 'i')) flags ++
+ if isopt "keepPrelude" then pathPrel d' else []
+ , pathPrel = (map tail . filter (\v -> head v == 'P')) flags ++
+ includePaths (compiler d') ++
+ packageDirs (compiler d')
+ (map (drop 8) $
+ filter ("package="`isPrefixOf`) flags)
+ , zdefs = (map tail . filter (\v -> head v == 'Z')) flags ++
+ cppSymbols (compiler d') ++
+ (if isHaskell98 (compiler d') then haskell98SymsForCpp else [])
+ , compiler = cc
}
- in d
+ return d'
where
flags = (map tail . filter isflag) progArgs
--- hmake-3.08.orig/src/hmake/Config.hs
+++ hmake-3.08/src/hmake/Config.hs
@@ -1,11 +1,21 @@
module Config where
import Compiler
-import System (getEnv)
-import Directory (doesFileExist,doesDirectoryExist,createDirectory)
+import System (ExitCode(..),getEnv,system,exitWith)
+import Directory (doesFileExist,doesDirectoryExist,createDirectory
+ ,getPermissions,Permissions(..))
import Monad (when)
-import List (nub)
-import Platform (unsafePerformIO)
+import List (nub,isPrefixOf)
+import Platform (unsafePerformIO,exe,escape,windows)
+import RunAndReadStdout (runAndReadStdout, basename, dirname)
+import Char (isDigit)
+import Monad (foldM)
+import IO (stderr)
+#ifdef __HBC__
+import IOMisc (hPutStrLn)
+#else
+import IO (hPutStrLn)
+#endif
----
data PersonalConfig = PersonalConfig
@@ -43,12 +53,19 @@
, extraCompilerFlags :: [String]
, isHaskell98 :: Bool
}
+ | DynCompiler { compilerPath :: FilePath }
deriving (Read)
+unDyn :: CompilerConfig -> IO CompilerConfig
+unDyn (DynCompiler path) = configure path
+unDyn cc = return cc
+
instance Eq CompilerConfig where -- equality on filename only
cc1 == cc2 = compilerPath cc1 == compilerPath cc2
instance Show CompilerConfig where
+ showsPrec p (DynCompiler hc) =
+ showString "DynCompiler { compilerPath = " . shows hc . showString " }\n"
showsPrec p cc =
showString "CompilerConfig"
. showString "\n { compilerStyle = " . shows (compilerStyle cc)
@@ -176,3 +193,186 @@
usualCompiler :: HmakeConfig -> CompilerConfig
usualCompiler config = matchCompiler (defaultCompiler config) config
-}
+
+configure :: String -> IO CompilerConfig
+configure comp_path = do comp_type <- hcStyle comp_path
+ configure' comp_type comp_path
+
+-- configure for each style of compiler
+configure' :: HC -> String -> IO CompilerConfig
+configure' Ghc ghcpath = do
+ ghcversion <- runAndReadStdout (escape ghcpath ++ " --version 2>&1 | "
+ ++"sed 's/^.*version[ ]*\\([0-9.]*\\).*/\\1/'"
+ )
+ let ghcsym = (read (take 3 (filter isDigit ghcversion ++ "0"))) :: Int
+ config = CompilerConfig
+ { compilerStyle = Ghc
+ , compilerPath = ghcpath
+ , compilerVersion = ghcversion
+ , includePaths = undefined
+ , cppSymbols = ["__GLASGOW_HASKELL__="++show ghcsym]
+ , extraCompilerFlags = []
+ , isHaskell98 = ghcsym>=400 }
+ if windows && ghcsym<500
+ then do
+ fullpath <- which exe ghcpath
+ let incdir1 = dirname (dirname fullpath)++"/imports"
+ ok <- doesDirectoryExist incdir1
+ if ok
+ then return config{ includePaths = ghcDirs ghcsym incdir1 }
+ else do ioError (userError ("Can't find ghc includes at\n "++incdir1))
+ else if ghcsym<500
+ then do
+ fullpath <- which exe ghcpath
+ dir <- runAndReadStdout ("grep '^\\$libdir=' "++fullpath++" | head -1 | "
+ ++ "sed 's/^\\$libdir=[^/]*\\(.*\\).;/\\1/'")
+ let incdir1 = dir++"/imports"
+ ok <- doesDirectoryExist incdir1
+ if ok
+ then return config{ includePaths = ghcDirs ghcsym incdir1 }
+ else do
+ let incdir2 = dir++"/lib/imports"
+ ok <- doesDirectoryExist incdir2
+ if ok
+ then return config{ includePaths = ghcDirs ghcsym incdir2 }
+ else do ioError (userError ("Can't find ghc includes at\n "
+ ++incdir1++"\n "++incdir2))
+ else do -- 5.00 and above
+ pkgcfg <- runAndReadStdout (escape ghcpath++" -v 2>&1 | head -2 "
+ ++"| tail -1 | cut -c28- | head -1")
+ let libdir = dirname (escape pkgcfg)
+ incdir1 = libdir++"/imports"
+ ok <- doesDirectoryExist incdir1
+ if ok
+ then do
+ fullpath <- fmap escape (which exe ghcpath)
+ ghcpkg0 <- runAndReadStdout $ "echo `" ++ ghcpath ++ " --print-libdir`/bin/ghc-pkg"
+ let ghcpkg1 = dirname fullpath++"/ghc-pkg-"++ghcversion
+ ghcpkg2 = dirname fullpath++"/ghc-pkg"
+ ok0 <- doesFileExist ghcpkg0
+ ok1 <- doesFileExist ghcpkg1
+ ok2 <- doesFileExist ghcpkg2
+ let ghcpkg = if ok0 then ghcpkg0
+ else if ok1 then ghcpkg1
+ else if ok2 then ghcpkg2
+ else error $ "Can't find ghc-pkg for " ++ ghcpath
+ -- pkgs <- runAndReadStdout (ghcpkg++" --list-packages")
+ pkgs <- runAndReadStdout (ghcpkg++" -l")
+ let pkgsOK = filter (`elem`["std","base","haskell98"]) (deComma pkgs)
+ idirs <- mapM (\p-> runAndReadStdout
+ (ghcpkg++" --show-package="++p
+ ++" --field=import_dirs"))
+ pkgsOK
+ return config{ includePaths = pkgDirs libdir (nub idirs) }
+ else do ioError (userError ("Can't find ghc includes at "++incdir1))
+ where
+ ghcDirs n root | n < 400 = [root]
+ | n < 406 = map ((root++"/")++) ["std","exts","misc"
+ ,"posix"]
+ | otherwise = map ((root++"/")++) ["std","lang","data","net"
+ ,"posix","num","text"
+ ,"util","hssource"
+ ,"win32","concurrent"]
+ pkgDirs libdir dirs =
+ map (\dir-> if "$libdir" `isPrefixOf` dir
+ then libdir++drop 7 dir
+ else dir)
+ (concatMap words dirs)
+ deComma pkgs = map (\p-> if last p==',' then init p else p) (words pkgs)
+
+configure' Nhc98 nhcpath = do
+ fullpath <- which id nhcpath
+ nhcversion <- runAndReadStdout (escape nhcpath
+ ++" --version 2>&1 | cut -d' ' -f2 | head -1")
+ dir <- runAndReadStdout ("grep '^NHC98INCDIR' "++escape fullpath
+ ++ "| cut -c27- | cut -d'}' -f1 | head -1")
+ return CompilerConfig { compilerStyle = Nhc98
+ , compilerPath = nhcpath
+ , compilerVersion = nhcversion
+ , includePaths = [dir]
+ , cppSymbols = ["__NHC__="++
+ take 3 (filter isDigit nhcversion)]
+ , extraCompilerFlags = []
+ , isHaskell98 = True
+ }
+configure' Hbc hbcpath = do
+ let field n = "| cut -d' ' -f"++show n++" | head -1"
+ wibble <- runAndReadStdout (hbcpath ++ " -v 2>&1 " ++ field 2)
+ hbcversion <-
+ case wibble of
+ "version" -> runAndReadStdout (hbcpath ++ " -v 2>&1 " ++ field 3)
+ _ -> runAndReadStdout (hbcpath ++ " -v 2>&1 " ++ field 4)
+ dir <- catch (getEnv "HBCDIR")
+ (\e-> catch (getEnv "LMLDIR")
+ (\e-> return "/usr/local/lib/lmlc"))
+ return CompilerConfig { compilerStyle = Hbc
+ , compilerPath = hbcpath
+ , compilerVersion = hbcversion
+ , includePaths = map ((dir++"/")++)
+ ["hlib1.3","hbc_library1.3"]
+ , cppSymbols = ["__HBC__"]
+ , extraCompilerFlags = []
+ , isHaskell98 = ((hbcversion!!7) >= '5')
+ }
+configure' (Unknown hc) hcpath = do
+ hPutStrLn stderr ("hmake-config: the compiler\n '"++hcpath
+ ++"'\n does not look like a Haskell compiler.")
+ exitWith (ExitFailure 4)
+ return undefined -- never reached
+
+-- Work out which basic compiler.
+hcStyle :: String -> IO HC
+hcStyle path = do case toCompiler (basename path) of
+ -- Ugly hack as we can't read stdout
+ Unknown hc -> do rc <- system $ "case `" ++ path ++ " 2>&1 | head -1 | cut -c1-3` in ghc) exit 3;; nhc) exit 4;; hbc) exit 5;; gcc) exit 6;; *) exit 7;; esac"
+ return $ case rc of
+ ExitFailure 3 -> Ghc
+ ExitFailure 4 -> Nhc98
+ ExitFailure 5 -> Hbc
+ ExitFailure 6 -> Nhc98
+ _ -> Unknown hc
+ s -> return s
+ where
+ toCompiler :: String -> HC
+ toCompiler hc | "gcc" `isPrefixOf` hc = Nhc98
+ | "nhc" `isPrefixOf` hc = Nhc98
+ | "ghc" `isPrefixOf` hc = Ghc
+ | "hbc" `isPrefixOf` hc = Hbc
+ | otherwise = Unknown hc
+
+-- Emulate the shell `which` command.
+which :: (String->String) -> String -> IO String
+which exe cmd =
+ let dir = dirname cmd
+ in case dir of
+ "" -> do -- search the shell environment PATH variable for candidates
+ val <- getEnv "PATH"
+ let psep = pathSep val
+ dirs = splitPath psep "" val
+ search <- foldM (\a dir-> testFile a (dir++'/': exe cmd))
+ Nothing dirs
+ case search of
+ Just x -> return x
+ Nothing -> ioError (userError (cmd++" not found"))
+ _ -> do f <- perms (exe cmd)
+ case f of
+ Just x -> return x
+ Nothing -> ioError (userError (cmd++" is not executable"))
+ where
+ splitPath :: Char -> String -> String -> [String]
+ splitPath sep acc [] = [reverse acc]
+ splitPath sep acc (c:path) | c==sep = reverse acc : splitPath sep "" path
+ splitPath sep acc (c:path) = splitPath sep (c:acc) path
+
+ pathSep s = if length (filter (==';') s) >0 then ';' else ':'
+
+ testFile :: Maybe String -> String -> IO (Maybe String)
+ testFile gotit@(Just _) path = return gotit
+ testFile Nothing path = do
+ ok <- doesFileExist path
+ if ok then perms path else return Nothing
+
+ perms file = do
+ p <- getPermissions file
+ return (if executable p then Just file else Nothing)
+
--- hmake-3.08.orig/src/hmake/MkConfig.hs
+++ hmake-3.08/src/hmake/MkConfig.hs
@@ -3,13 +3,12 @@
import Compiler (HC(..))
import Config
-import Platform (unsafePerformIO,escape,windows,exe)
-import RunAndReadStdout (runAndReadStdout, basename, dirname)
+import Platform (unsafePerformIO)
+import RunAndReadStdout (dirname)
import Directory (doesDirectoryExist,doesFileExist,removeFile,getPermissions
,Permissions(..),renameFile,createDirectory)
import System (exitWith,ExitCode(..),getArgs,getEnv,getProgName)
-import List (intersperse,nub,isPrefixOf,sort)
-import Char (isDigit)
+import List (intersperse,nub,sort)
import Monad (foldM,when)
import Maybe (isJust,fromJust)
import IO (stderr,isDoesNotExistError)
@@ -34,20 +33,23 @@
Just f -> putStrLn ("Personal config file is:\n "++f)
Nothing -> return ())
putStrLn "Known compilers:"
+ known <- mapM unDyn $ knownComps config
mapM_ putStrLn
((reverse . sort
. map (\c-> " "++compilerPath c
++"\t("++compilerVersion c++")"))
- (knownComps config))
+ known)
putStrLn "Default compiler:"
putStrLn (" "++defaultComp config)
[hc] -> do -- no command, assume 'add'
- cc <- configure (hcStyle hc) hc
+ cc <- configure hc
config' <- add cc config
writeBack gfile lfile config'
- ["add",hc] -> do cc <- configure (hcStyle hc) hc
+ ["add",hc] -> do cc <- configure hc
config' <- add cc config
writeBack gfile lfile config'
+ ["add-dyn",hc] -> do config' <- add (DynCompiler hc) config
+ writeBack gfile lfile config'
["delete",hc] -> do config' <- delete config gfile hc
writeBack gfile lfile config'
["default",hc] -> do config' <- mkDefault config hc
@@ -55,7 +57,7 @@
["list",hc] -> do let cc = matchCompiler hc config
putStrLn (show cc)
_ -> do hPutStrLn stderr ("Usage: hmake-config [configfile] list\n"
- ++" hmake-config [configfile] [add|delete|default] hc\n"
+ ++" hmake-config [configfile] [add|add-dyn|delete|default] hc\n"
++" -- hc is name/path of a Haskell compiler")
exitWith (ExitFailure 1)
----
@@ -67,7 +69,7 @@
case args of
[] -> do let (g,_) = defaultConfigLocation False
hPutStrLn stderr ("Usage: hmake-config [configfile] list\n"
- ++" hmake-config [configfile] [add|delete|default] hc\n"
+ ++" hmake-config [configfile] [add-dyn|delete|default] hc\n"
++" -- hc is name/path of a Haskell compiler\n"
++" default configfile is:\n "++g)
exitWith (ExitFailure 1)
@@ -196,165 +198,3 @@
global { knownCompilers =
nub (hc: knownCompilers global)}}
--- configure for each style of compiler
-configure :: HC -> String -> IO CompilerConfig
-configure Ghc ghcpath = do
- ghcversion <- runAndReadStdout (escape ghcpath ++ " --version 2>&1 | "
- ++"sed 's/^.*version[ ]*\\([0-9.]*\\).*/\\1/'"
- )
- let ghcsym = (read (take 3 (filter isDigit ghcversion ++ "0"))) :: Int
- config = CompilerConfig
- { compilerStyle = Ghc
- , compilerPath = ghcpath
- , compilerVersion = ghcversion
- , includePaths = undefined
- , cppSymbols = ["__GLASGOW_HASKELL__="++show ghcsym]
- , extraCompilerFlags = []
- , isHaskell98 = ghcsym>=400 }
- if windows && ghcsym<500
- then do
- fullpath <- which exe ghcpath
- let incdir1 = dirname (dirname fullpath)++"/imports"
- ok <- doesDirectoryExist incdir1
- if ok
- then return config{ includePaths = ghcDirs ghcsym incdir1 }
- else do ioError (userError ("Can't find ghc includes at\n "++incdir1))
- else if ghcsym<500
- then do
- fullpath <- which exe ghcpath
- dir <- runAndReadStdout ("grep '^\\$libdir=' "++fullpath++" | head -1 | "
- ++ "sed 's/^\\$libdir=[^/]*\\(.*\\).;/\\1/'")
- let incdir1 = dir++"/imports"
- ok <- doesDirectoryExist incdir1
- if ok
- then return config{ includePaths = ghcDirs ghcsym incdir1 }
- else do
- let incdir2 = dir++"/lib/imports"
- ok <- doesDirectoryExist incdir2
- if ok
- then return config{ includePaths = ghcDirs ghcsym incdir2 }
- else do ioError (userError ("Can't find ghc includes at\n "
- ++incdir1++"\n "++incdir2))
- else do -- 5.00 and above
- pkgcfg <- runAndReadStdout (escape ghcpath++" -v 2>&1 | head -2 "
- ++"| tail -1 | cut -c28- | head -1")
- let libdir = dirname (escape pkgcfg)
- incdir1 = libdir++"/imports"
- ok <- doesDirectoryExist incdir1
- if ok
- then do
- fullpath <- fmap escape (which exe ghcpath)
- let ghcpkg0 = dirname fullpath++"/ghc-pkg-"++ghcversion
- ok <- doesFileExist ghcpkg0
- let ghcpkg = if ok then ghcpkg0 else dirname fullpath++"/ghc-pkg"
- -- pkgs <- runAndReadStdout (ghcpkg++" --list-packages")
- pkgs <- runAndReadStdout (ghcpkg++" -l")
- let pkgsOK = filter (`elem`["std","base","haskell98"]) (deComma pkgs)
- idirs <- mapM (\p-> runAndReadStdout
- (ghcpkg++" --show-package="++p
- ++" --field=import_dirs"))
- pkgsOK
- return config{ includePaths = pkgDirs libdir (nub idirs) }
- else do ioError (userError ("Can't find ghc includes at "++incdir1))
- where
- ghcDirs n root | n < 400 = [root]
- | n < 406 = map ((root++"/")++) ["std","exts","misc"
- ,"posix"]
- | otherwise = map ((root++"/")++) ["std","lang","data","net"
- ,"posix","num","text"
- ,"util","hssource"
- ,"win32","concurrent"]
- pkgDirs libdir dirs =
- map (\dir-> if "$libdir" `isPrefixOf` dir
- then libdir++drop 7 dir
- else dir)
- (concatMap words dirs)
- deComma pkgs = map (\p-> if last p==',' then init p else p) (words pkgs)
-
-configure Nhc98 nhcpath = do
- fullpath <- which id nhcpath
- nhcversion <- runAndReadStdout (escape nhcpath
- ++" --version 2>&1 | cut -d' ' -f2 | head -1")
- dir <- runAndReadStdout ("grep '^NHC98INCDIR' "++escape fullpath
- ++ "| cut -c27- | cut -d'}' -f1 | head -1")
- return CompilerConfig { compilerStyle = Nhc98
- , compilerPath = nhcpath
- , compilerVersion = nhcversion
- , includePaths = [dir]
- , cppSymbols = ["__NHC__="++
- take 3 (filter isDigit nhcversion)]
- , extraCompilerFlags = []
- , isHaskell98 = True
- }
-configure Hbc hbcpath = do
- let field n = "| cut -d' ' -f"++show n++" | head -1"
- wibble <- runAndReadStdout (hbcpath ++ " -v 2>&1 " ++ field 2)
- hbcversion <-
- case wibble of
- "version" -> runAndReadStdout (hbcpath ++ " -v 2>&1 " ++ field 3)
- _ -> runAndReadStdout (hbcpath ++ " -v 2>&1 " ++ field 4)
- dir <- catch (getEnv "HBCDIR")
- (\e-> catch (getEnv "LMLDIR")
- (\e-> return "/usr/local/lib/lmlc"))
- return CompilerConfig { compilerStyle = Hbc
- , compilerPath = hbcpath
- , compilerVersion = hbcversion
- , includePaths = map ((dir++"/")++)
- ["hlib1.3","hbc_library1.3"]
- , cppSymbols = ["__HBC__"]
- , extraCompilerFlags = []
- , isHaskell98 = ((hbcversion!!7) >= '5')
- }
-configure (Unknown hc) hcpath = do
- hPutStrLn stderr ("hmake-config: the compiler\n '"++hcpath
- ++"'\n does not look like a Haskell compiler.")
- exitWith (ExitFailure 4)
- return undefined -- never reached
-
--- Work out which basic compiler.
-hcStyle :: String -> HC
-hcStyle path = toCompiler (basename path)
- where
- toCompiler :: String -> HC
- toCompiler hc | "gcc" `isPrefixOf` hc = Nhc98
- | "nhc" `isPrefixOf` hc = Nhc98
- | "ghc" `isPrefixOf` hc = Ghc
- | "hbc" `isPrefixOf` hc = Hbc
- | otherwise = Unknown hc
-
--- Emulate the shell `which` command.
-which :: (String->String) -> String -> IO String
-which exe cmd =
- let dir = dirname cmd
- in case dir of
- "" -> do -- search the shell environment PATH variable for candidates
- val <- getEnv "PATH"
- let psep = pathSep val
- dirs = splitPath psep "" val
- search <- foldM (\a dir-> testFile a (dir++'/': exe cmd))
- Nothing dirs
- case search of
- Just x -> return x
- Nothing -> ioError (userError (cmd++" not found"))
- _ -> do f <- perms (exe cmd)
- case f of
- Just x -> return x
- Nothing -> ioError (userError (cmd++" is not executable"))
- where
- splitPath :: Char -> String -> String -> [String]
- splitPath sep acc [] = [reverse acc]
- splitPath sep acc (c:path) | c==sep = reverse acc : splitPath sep "" path
- splitPath sep acc (c:path) = splitPath sep (c:acc) path
-
- pathSep s = if length (filter (==';') s) >0 then ';' else ':'
-
- testFile :: Maybe String -> String -> IO (Maybe String)
- testFile gotit@(Just _) path = return gotit
- testFile Nothing path = do
- ok <- doesFileExist path
- if ok then perms path else return Nothing
-
- perms file = do
- p <- getPermissions file
- return (if executable p then Just file else Nothing)
-
--- hmake-3.08.orig/src/hmake/MkProg.hs
+++ hmake-3.08/src/hmake/MkProg.hs
@@ -10,9 +10,9 @@
main =
- getArgs >>= \ args ->
+ getArgs >>= \ args ->
+ decode args >>= \ d ->
let
- d = decode args
echo = not (quiet d)
order g = (scctsort . map (\(f,(tps,i)) -> (f,i))) g
--- hmake-3.08.orig/src/hmake/PackageConfig.hs
+++ hmake-3.08/src/hmake/PackageConfig.hs
@@ -11,6 +11,7 @@
import List (partition,intersperse,isPrefixOf)
import Char (isDigit)
import Monad (when,foldM)
+import System (system)
-- Work out the import directories for a bunch of packages.
packageDirs :: CompilerConfig -> [String] -> [FilePath]
@@ -31,7 +32,8 @@
ok <- doesDirectoryExist incdir1
if ok
then do
- let ghcpkg = matching ghc (ghcPkg ghc (compilerVersion config))
+ ghcpkg <- runAndReadStdout $ "echo `" ++ ghc ++ " --print-libdir`/bin/ghc-pkg"
+ -- let ghcpkg = matching ghc (ghcPkg ghc (compilerVersion config))
-- pkgs <- runAndReadStdout (ghcpkg++" --list-packages")
pkgs <- runAndReadStdout (ghcpkg++" -l")
let (ok,bad) = partition (`elem` deComma pkgs) packages
--- hmake-3.08.orig/src/interpreter/Makefile
+++ hmake-3.08/src/interpreter/Makefile
@@ -9,16 +9,16 @@
CHFILES = $(patsubst %.hs, ../hmake/%.$C, $(OTHERS))
-ifeq "$(findstring ghc, ${HC})" "ghc"
+ifeq "${BUILDCOMP}" "ghc"
HFLAGS = $(shell $(LOCAL)fixghc $(GHCSYM) \
-package lang -package util -package base $(READLINE) )
export HFLAGS
endif
-ifeq "$(findstring hbc, ${HC})" "hbc"
+ifeq "${BUILDCOMP}" "hbc"
HFLAGS =
export HFLAGS
endif
-ifeq "$(findstring nhc98, ${HC})" "nhc98"
+ifeq "${BUILDCOMP}" "nhc"
HFLAGS = -package base
export HFLAGS
endif
--- hmake-3.08.orig/script/hmake.inst
+++ hmake-3.08/script/hmake.inst
@@ -235,22 +235,32 @@
OD=
# Define the characteristics of each known compiler.
compilerstyle () {
- case `basename $1` in
+ COMPILERSTYLE=`basename $1 | cut -c1-3`
+ if [ $COMPILERSTYLE != hbc ] \
+ && [ $COMPILERSTYLE != ghc ] \
+ && [ $COMPILERSTYLE != nhc ]
+ then
+ COMPILERSTYLE=`$1 2>&1 | head -1 | cut -c1-3`
+ fi
+
+ case "$COMPILERSTYLE" in
hbc) RTSOPTIONSTYLE=minus
CTSOPTIONSTYLE=none
IMPORTOPTIONSTYLE=minusi
export LMLDIR HBCDIR
;;
- nhc98) RTSOPTIONSTYLE=rts
+ nhc) RTSOPTIONSTYLE=rts
CTSOPTIONSTYLE=cts
IMPORTOPTIONSTYLE=minusP
OD="-od"
;;
- ghc*) RTSOPTIONSTYLE=none
+ ghc) RTSOPTIONSTYLE=none
CTSOPTIONSTYLE=none
IMPORTOPTIONSTYLE=minusi
;;
- *) ;;
+ *) echo "No compiler style found" >&2
+ exit 1
+ ;;
esac
}
--- hmake-3.08.orig/Makefile
+++ hmake-3.08/Makefile
@@ -3,7 +3,10 @@
# This included config is only for the BUILDWITH variable.
include targets/$(MACHINE)/config.cache
-BUILDCOMP = $(shell echo ${BUILDWITH} | cut -c1-3)
+BUILDCOMPS := ghc nhc hbc gcc
+BUILDCOMP1 := $(shell echo $(notdir ${BUILDWITH}) | cut -c1-3)
+BUILDCOMP2 := $(if $(filter $(BUILDCOMP1), $(BUILDCOMPS)),$(BUILDCOMP1),$(shell ${BUILDWITH} 2>&1 | head -1 | cut -c1-3))
+BUILDCOMP := $(if $(filter $(BUILDCOMP2), $(BUILDCOMPS)),$(BUILDCOMP2),$(error Can't find compiler type))
HMAKE = src/hmake/Makefile* src/hmake/*.hs src/hmake/README* \
src/hmake/HISTORY src/hmake/Summary* \
@@ -39,31 +42,31 @@
$(TARGDIR)/$(MACHINE)/hmake-nhc: $(HMAKE)
- cd src/hmake; $(MAKE) HC=$(BUILDWITH) install config
+ cd src/hmake; $(MAKE) HC=$(BUILDWITH) BUILDCOMP=$(BUILDCOMP) install config
touch $(TARGDIR)/$(MACHINE)/hmake-nhc
$(TARGDIR)/$(MACHINE)/hmake-hbc: $(HMAKE)
- cd src/hmake; $(MAKE) HC=$(BUILDWITH) install config
+ cd src/hmake; $(MAKE) HC=$(BUILDWITH) BUILDCOMP=$(BUILDCOMP) install config
touch $(TARGDIR)/$(MACHINE)/hmake-hbc
$(TARGDIR)/$(MACHINE)/hmake-ghc: $(HMAKE)
- cd src/hmake; $(MAKE) HC=$(BUILDWITH) install config
+ cd src/hmake; $(MAKE) HC=$(BUILDWITH) BUILDCOMP=$(BUILDCOMP) install config
touch $(TARGDIR)/$(MACHINE)/hmake-ghc
$(TARGDIR)/$(MACHINE)/chmake: $(HMAKEC)
@echo "WARNING: hmake might not build correctly from C sources!"
- cd src/hmake; $(MAKE) HC=nhc98 fromC config
+ cd src/hmake; $(MAKE) HC=nhc98 BUILDCOMP=nhc fromC config
touch $(TARGDIR)/$(MACHINE)/chmake
$(TARGDIR)/$(MACHINE)/hi-nhc: $(HMAKE) hmake-nhc
- cd src/interpreter; $(MAKE) HC=$(BUILDWITH) install
+ cd src/interpreter; $(MAKE) HC=$(BUILDWITH) BUILDCOMP=$(BUILDCOMP) install
touch $(TARGDIR)/$(MACHINE)/hi-nhc98
$(TARGDIR)/$(MACHINE)/hi-hbc: $(HMAKE) hmake-hbc
- cd src/interpreter; $(MAKE) HC=$(BUILDWITH) install
+ cd src/interpreter; $(MAKE) HC=$(BUILDWITH) BUILDCOMP=$(BUILDCOMP) install
touch $(TARGDIR)/$(MACHINE)/hi-hbc
$(TARGDIR)/$(MACHINE)/hi-ghc: $(HMAKE) hmake-ghc
- cd src/interpreter; $(MAKE) HC=$(BUILDWITH) install
+ cd src/interpreter; $(MAKE) HC=$(BUILDWITH) BUILDCOMP=$(BUILDCOMP) install
touch $(TARGDIR)/$(MACHINE)/hi-ghc
$(TARGDIR)/$(MACHINE)/chi: $(HMAKEC) chmake
@echo "WARNING: hi might not build correctly from C sources!"
- cd src/interpreter; $(MAKE) HC=nhc98 fromC
+ cd src/interpreter; $(MAKE) HC=nhc98 BUILDCOMP=nhc fromC
touch $(TARGDIR)/$(MACHINE)/chi
@@ -72,6 +75,7 @@
clean:
cd src/hmake; $(MAKE) clean
cd src/interpreter; $(MAKE) clean
+ rm -f script/hmake script/hi script/hmake-config
realclean: clean
cd $(TARGDIR)/$(MACHINE); rm -f $(TARGETS)
@@ -79,4 +83,3 @@
rm -f $(LIBDIR)/$(MACHINE)/*
rm -f $(TARGDIR)/$(MACHINE)/config.cache
rm -f $(LIBDIR)/$(MACHINE)/hmakerc
- rm -f script/hmake script/hi script/hmake-config
More information about the Nhc-users
mailing list