aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/src/Fpm.hs
diff options
context:
space:
mode:
Diffstat (limited to 'bootstrap/src/Fpm.hs')
-rw-r--r--bootstrap/src/Fpm.hs271
1 files changed, 264 insertions, 7 deletions
diff --git a/bootstrap/src/Fpm.hs b/bootstrap/src/Fpm.hs
index 9fc1c91..10e14fe 100644
--- a/bootstrap/src/Fpm.hs
+++ b/bootstrap/src/Fpm.hs
@@ -71,6 +71,7 @@ import System.Exit ( ExitCode(..)
, exitWith
)
import System.Process ( readProcess
+ , readProcessWithExitCode
, system
)
import Toml ( TomlCodec
@@ -92,6 +93,7 @@ data Arguments =
}
| Run
{ runRelease :: Bool
+ , runExample :: Bool
, runCompiler :: FilePath
, runFlags :: [String]
, runRunner :: Maybe String
@@ -111,6 +113,7 @@ data TomlSettings = TomlSettings {
tomlSettingsProjectName :: String
, tomlSettingsLibrary :: (Maybe Library)
, tomlSettingsExecutables :: [Executable]
+ , tomlSettingsExamples :: [Executable]
, tomlSettingsTests :: [Executable]
, tomlSettingsDependencies :: (Map.Map String Version)
, tomlSettingsDevDependencies :: (Map.Map String Version)
@@ -122,6 +125,7 @@ data AppSettings = AppSettings {
, appSettingsBuildPrefix :: String
, appSettingsLibrary :: (Maybe Library)
, appSettingsExecutables :: [Executable]
+ , appSettingsExamples :: [Executable]
, appSettingsTests :: [Executable]
, appSettingsDependencies :: (Map.Map String Version)
, appSettingsDevDependencies :: (Map.Map String Version)
@@ -168,15 +172,23 @@ start args = case args of
app :: Arguments -> AppSettings -> IO ()
app args settings = case args of
Build{} -> build settings
- Run { runTarget = whichOne, runArgs = runArgs, runRunner = runner } -> do
+ Run { runTarget = whichOne, runArgs = runArgs, runRunner = runner, runExample = runExample } -> do
build settings
let buildPrefix = appSettingsBuildPrefix settings
let
- executableNames = map
- (\Executable { executableSourceDir = sourceDir, executableMainFile = mainFile, executableName = name } ->
- sourceDir </> name
- )
- (appSettingsExecutables settings)
+ executableNames = if runExample
+ then
+ map
+ (\Executable { executableSourceDir = sourceDir, executableMainFile = mainFile, executableName = name } ->
+ sourceDir </> name
+ )
+ (appSettingsExamples settings)
+ else
+ map
+ (\Executable { executableSourceDir = sourceDir, executableMainFile = mainFile, executableName = name } ->
+ sourceDir </> name
+ )
+ (appSettingsExecutables settings)
let executables =
map (buildPrefix </>) $ map (flip (<.>) exe) executableNames
canonicalExecutables <- mapM makeAbsolute executables
@@ -265,6 +277,7 @@ build settings = do
let projectName = appSettingsProjectName settings
let buildPrefix = appSettingsBuildPrefix settings
let executables = appSettingsExecutables settings
+ let examples = appSettingsExamples settings
let tests = appSettingsTests settings
mainDependencyTrees <- fetchDependencies (appSettingsDependencies settings)
builtDependencies <- buildDependencies buildPrefix
@@ -341,6 +354,29 @@ build settings = do
++ (map snd localDependencies)
)
)
+ examples
+ mapM_
+ (\Executable { executableSourceDir = sourceDir, executableMainFile = mainFile, executableName = name, executableDependencies = dependencies } ->
+ do
+ localDependencies <-
+ fetchExecutableDependencies maybeTree dependencies
+ >>= buildDependencies buildPrefix compilerSettings
+ buildProgram
+ sourceDir
+ ( (map fst executableDepends)
+ ++ (map fst devDependencies)
+ ++ (map fst localDependencies)
+ )
+ [".f90", ".f", ".F", ".F90", ".f95", ".f03"]
+ (buildPrefix </> sourceDir)
+ compilerSettings
+ name
+ mainFile
+ ( (map snd executableDepends)
+ ++ (map snd devDependencies)
+ ++ (map snd localDependencies)
+ )
+ )
tests
getArguments :: IO Arguments
@@ -410,6 +446,10 @@ runArguments =
( long "release"
<> help "Build with optimizations instead of debugging"
)
+ <*> switch
+ ( long "example"
+ <> help "Run example programs instead of applications"
+ )
<*> strOption
( long "compiler"
<> metavar "COMPILER"
@@ -503,6 +543,8 @@ settingsCodec =
.= tomlSettingsLibrary
<*> Toml.list executableCodec "executable"
.= tomlSettingsExecutables
+ <*> Toml.list executableCodec "example"
+ .= tomlSettingsExamples
<*> Toml.list executableCodec "test"
.= tomlSettingsTests
<*> Toml.tableMap Toml._KeyString versionCodec "dependencies"
@@ -608,6 +650,7 @@ toml2AppSettings tomlSettings args = do
executableSettings <- getExecutableSettings
(tomlSettingsExecutables tomlSettings)
projectName
+ exampleSettings <- getExampleSettings $ tomlSettingsExamples tomlSettings
testSettings <- getTestSettings $ tomlSettingsTests tomlSettings
compilerSettings <- defineCompilerSettings specifiedFlags compiler release
buildPrefix <- makeBuildPrefix (compilerSettingsCompiler compilerSettings)
@@ -619,6 +662,7 @@ toml2AppSettings tomlSettings args = do
, appSettingsBuildPrefix = buildPrefix
, appSettingsLibrary = librarySettings
, appSettingsExecutables = executableSettings
+ , appSettingsExamples = exampleSettings
, appSettingsTests = testSettings
, appSettingsDependencies = dependencies
, appSettingsDevDependencies = devDependencies
@@ -690,6 +734,185 @@ defineCompilerSettings specifiedFlags compiler release
, compilerSettingsModuleFlag = "-J"
, compilerSettingsIncludeFlag = "-I"
}
+ | "f95" `isInfixOf` compiler
+ = let flags = case specifiedFlags of
+ [] -> if release
+ then
+ [ "-O3"
+ , "-Wimplicit-interface"
+ , "-fPIC"
+ , "-fmax-errors=1"
+ , "-ffast-math"
+ , "-funroll-loops"
+ ]
+ else
+ [ "-Wall"
+ , "-Wextra"
+ , "-Wimplicit-interface"
+ , "-fPIC"
+ , "-fmax-errors=1"
+ , "-g"
+ , "-fbounds-check"
+ , "-fcheck-array-temporaries"
+ , "-Wno-maybe-uninitialized"
+ , "-Wno-uninitialized"
+ , "-fbacktrace"
+ ]
+ fs -> fs
+ in return $ CompilerSettings { compilerSettingsCompiler = compiler
+ , compilerSettingsFlags = flags
+ , compilerSettingsModuleFlag = "-J"
+ , compilerSettingsIncludeFlag = "-I"
+ }
+ | "nvfortran" `isInfixOf` compiler
+ = let flags = case specifiedFlags of
+ [] -> if release
+ then
+ [ "-Mbackslash"
+ ]
+ else
+ [ "-Minform=inform"
+ , "-Mbackslash"
+ , "-g"
+ , "-Mbounds"
+ , "-Mchkptr"
+ , "-Mchkstk"
+ , "-traceback"
+ ]
+ fs -> fs
+ in return $ CompilerSettings { compilerSettingsCompiler = compiler
+ , compilerSettingsFlags = flags
+ , compilerSettingsModuleFlag = "-module"
+ , compilerSettingsIncludeFlag = "-I"
+ }
+ | "ifort" `isInfixOf` compiler
+ = let flags = case specifiedFlags of
+ [] -> if release
+ then
+ [ "-fp-model", "precise"
+ , "-pc", "64"
+ , "-align", "all"
+ , "-error-limit", "1"
+ , "-reentrancy", "threaded"
+ , "-nogen-interfaces"
+ , "-assume", "byterecl"
+ , "-assume", "nounderscore"
+ ]
+ else
+ [ "-warn", "all"
+ , "-check:all:noarg_temp_created"
+ , "-error-limit", "1"
+ , "-O0"
+ , "-g"
+ , "-assume", "byterecl"
+ , "-traceback"
+ ]
+ fs -> fs
+ in return $ CompilerSettings { compilerSettingsCompiler = compiler
+ , compilerSettingsFlags = flags
+ , compilerSettingsModuleFlag = "-module"
+ , compilerSettingsIncludeFlag = "-I"
+ }
+ | "ifx" `isInfixOf` compiler
+ = let flags = case specifiedFlags of
+ [] -> if release
+ then
+ []
+ else
+ []
+ fs -> fs
+ in return $ CompilerSettings { compilerSettingsCompiler = compiler
+ , compilerSettingsFlags = flags
+ , compilerSettingsModuleFlag = "-module"
+ , compilerSettingsIncludeFlag = "-I"
+ }
+ | "pgfortran" `isInfixOf` compiler || "pgf90" `isInfixOf` compiler || "pgf95" `isInfixOf` compiler
+ = let flags = case specifiedFlags of
+ [] -> if release
+ then
+ []
+ else
+ []
+ fs -> fs
+ in return $ CompilerSettings { compilerSettingsCompiler = compiler
+ , compilerSettingsFlags = flags
+ , compilerSettingsModuleFlag = "-module"
+ , compilerSettingsIncludeFlag = "-I"
+ }
+ | "flang" `isInfixOf` compiler
+ = let flags = case specifiedFlags of
+ [] -> if release
+ then
+ []
+ else
+ []
+ fs -> fs
+ in return $ CompilerSettings { compilerSettingsCompiler = compiler
+ , compilerSettingsFlags = flags
+ , compilerSettingsModuleFlag = "-module"
+ , compilerSettingsIncludeFlag = "-I"
+ }
+ | "lfc" `isInfixOf` compiler
+ = let flags = case specifiedFlags of
+ [] -> if release
+ then
+ []
+ else
+ []
+ fs -> fs
+ in return $ CompilerSettings { compilerSettingsCompiler = compiler
+ , compilerSettingsFlags = flags
+ , compilerSettingsModuleFlag = "-M"
+ , compilerSettingsIncludeFlag = "-I"
+ }
+ | "nagfor" `isInfixOf` compiler
+ = let flags = case specifiedFlags of
+ [] -> if release
+ then
+ [ "-O4"
+ , "-coarray=single"
+ , "-PIC"
+ ]
+ else
+ [ "-g"
+ , "-C=all"
+ , "-O0"
+ , "-gline"
+ , "-coarray=single"
+ , "-PIC"
+ ]
+ fs -> fs
+ in return $ CompilerSettings { compilerSettingsCompiler = compiler
+ , compilerSettingsFlags = flags
+ , compilerSettingsModuleFlag = "-mdir"
+ , compilerSettingsIncludeFlag = "-I"
+ }
+ | "crayftn" `isInfixOf` compiler
+ = let flags = case specifiedFlags of
+ [] -> if release
+ then
+ []
+ else
+ []
+ fs -> fs
+ in return $ CompilerSettings { compilerSettingsCompiler = compiler
+ , compilerSettingsFlags = flags
+ , compilerSettingsModuleFlag = "-J"
+ , compilerSettingsIncludeFlag = "-I"
+ }
+ | "xlf90" `isInfixOf` compiler
+ = let flags = case specifiedFlags of
+ [] -> if release
+ then
+ []
+ else
+ []
+ fs -> fs
+ in return $ CompilerSettings { compilerSettingsCompiler = compiler
+ , compilerSettingsFlags = flags
+ , compilerSettingsModuleFlag = "-qmoddir"
+ , compilerSettingsIncludeFlag = "-I"
+ }
| otherwise
= do
putStrLn $ "Sorry, compiler is currently unsupported: " ++ compiler
@@ -725,6 +948,24 @@ getExecutableSettings [] projectName = do
else return []
getExecutableSettings executables _ = return executables
+getExampleSettings :: [Executable] -> IO [Executable]
+getExampleSettings [] = do
+ defaultDirectoryExists <- doesDirectoryExist "example"
+ if defaultDirectoryExists
+ then do
+ defaultMainExists <- doesFileExist ("example" </> "main.f90")
+ if defaultMainExists
+ then return
+ [ Executable { executableSourceDir = "example"
+ , executableMainFile = "main.f90"
+ , executableName = "demo"
+ , executableDependencies = Map.empty
+ }
+ ]
+ else return []
+ else return []
+getExampleSettings examples = return examples
+
getTestSettings :: [Executable] -> IO [Executable]
getTestSettings [] = do
defaultDirectoryExists <- doesDirectoryExist "test"
@@ -747,7 +988,23 @@ makeBuildPrefix :: FilePath -> [String] -> IO FilePath
makeBuildPrefix compiler flags = do
-- TODO Figure out what other info should be part of this
-- Probably version, and make sure to not include path to the compiler
- versionInfo <- readProcess compiler ["--version"] []
+ versionInfo <- do
+ (exitCode, stdout, stderr) <- readProcessWithExitCode compiler
+ ["--version"]
+ []
+ case exitCode of
+ ExitSuccess -> case stdout of
+ "" -> return stderr -- Guess this compiler outputs version info to stderr instead?
+ _ -> return stdout
+ _ -> do -- guess this compiler doesn't support the --version option. let's try -version
+ (exitCode, stdout, stderr) <- readProcessWithExitCode compiler
+ ["-version"]
+ []
+ case exitCode of
+ ExitSuccess -> case stdout of
+ "" -> return stderr -- Guess this compiler outputs version info to stderr instead?
+ _ -> return stdout
+ _ -> return "" -- Don't know how to get version info, we'll let defineCompilerSettings report it as unsupported
let compilerName = last (splitDirectories compiler)
let versionHash = abs (hash versionInfo)
let flagsHash = abs (hash flags)