@@ -35,11 +35,12 @@ import System.Environment
3535import System.Exit
3636import System.FilePath
3737import System.IO
38- import System.IO.Error (isDoesNotExistError )
38+ import System.IO.Error (isDoesNotExistError , catchIOError )
3939import System.Process
4040import Text.PrettyPrint.GenericPretty
4141
42- import Data.List (isInfixOf )
42+ import Data.List (isInfixOf , stripPrefix )
43+ import Data.Char (isDigit , isSpace )
4344import Gibbon.Common
4445import Gibbon.DynFlags
4546import Gibbon.Language
@@ -376,6 +377,21 @@ compileRTS Config{verbosity,optc,dynflags,cc=ccCmd} = do
376377 when (isClangCompiler ccCmd && not (" llvm-ar" `isInfixOf` takeFileName archiver)) $
377378 putStrLn $
378379 " [compiler] clang detected but llvm-ar not found; using '" ++ archiver ++ " ' instead."
380+ when (isClangCompiler ccCmd && " llvm-ar" `isInfixOf` takeFileName archiver) $ do
381+ clangVer <- toolVersionMajor ccCmd
382+ arVer <- toolVersionMajor archiver
383+ case (clangVer, arVer) of
384+ (Just clangMajor, Just arMajor)
385+ | clangMajor /= arMajor ->
386+ die $ unlines
387+ [ " [compiler] clang/llvm-ar version mismatch detected."
388+ , " requested compiler : " ++ ccCmd
389+ , " selected archiver : " ++ archiver
390+ , " clang major version: " ++ show clangMajor
391+ , " archiver major ver : " ++ show arMajor
392+ , " Please adjust PATH so clang and llvm-ar versions align."
393+ ]
394+ _ -> pure ()
379395 let rtsmk = gibbon_dir </> " gibbon-rts/Makefile"
380396 userCFlags = optc
381397 rtsmkcmd = " make -f " ++ rtsmk ++ " "
@@ -488,6 +504,36 @@ chooseArchiver ccCmd = pick candidates
488504isClangCompiler :: String -> Bool
489505isClangCompiler = (" clang" `isInfixOf` ) . takeFileName
490506
507+ toolVersionMajor :: String -> IO (Maybe Int )
508+ toolVersionMajor toolString = do
509+ let exe = takeWhile (not . isSpace) (dropWhile isSpace toolString)
510+ base = takeFileName exe
511+ marker
512+ | " llvm-ar" `isInfixOf` base = Just " LLVM version "
513+ | " clang" `isInfixOf` base = Just " clang version "
514+ | otherwise = Nothing
515+ case marker of
516+ Nothing -> pure Nothing
517+ Just mk -> do
518+ outcome <- catchIOError (Just <$> readProcessWithExitCode exe [" --version" ] " " ) (const (pure Nothing ))
519+ case outcome of
520+ Just (ExitSuccess , stdoutText, _) -> pure (parseMajorAfter mk stdoutText)
521+ _ -> pure Nothing
522+
523+ parseMajorAfter :: String -> String -> Maybe Int
524+ parseMajorAfter marker txt = do
525+ rest <- findMarker marker txt
526+ let digits = takeWhile isDigit rest
527+ if null digits
528+ then Nothing
529+ else Just (read digits)
530+
531+ findMarker :: String -> String -> Maybe String
532+ findMarker _ [] = Nothing
533+ findMarker marker str =
534+ case stripPrefix marker str of
535+ Just rest -> Just rest
536+ Nothing -> findMarker marker (tail str)
491537
492538execCmd :: Maybe FilePath -> String -> String -> String -> IO ()
493539execCmd dir cmd msg errmsg = do
0 commit comments