{-# LANGUAGE LambdaCase #-} import Haskus.Apps.System.Build.Config import Haskus.Apps.System.Build.Linux import Haskus.Apps.System.Build.Syslinux import Haskus.Apps.System.Build.CmdLine import Haskus.Apps.System.Build.Utils import Haskus.Apps.System.Build.Ramdisk import Haskus.Apps.System.Build.Stack import Haskus.Apps.System.Build.GMP import Haskus.Apps.System.Build.QEMU import Haskus.Apps.System.Build.ISO import Haskus.Apps.System.Build.Disk import qualified Data.Text as Text import Haskus.Utils.Flow import Options.Applicative.Simple import Paths_haskus_system_build import Data.Version import System.IO.Temp import System.Directory import System.FilePath main :: IO () main = do -- read command-line options (_,runCmd) <- simpleOptions (showVersion version) "haskus-system-build" "This tool lets you build systems using haskus-system framework. It manages Linux/Syslinux (download and build), it builds ramdisk, it launches QEMU, etc." (pure ()) $ do addCommand "init" "Create a new project from a template" initCommand initOptions addCommand "build" "Build a project" buildCommand buildOptions addCommand "test" "Test a project with QEMU" testCommand testOptions addCommand "make-iso" "Create an ISO image" (const makeISOCommand) (pure ()) addCommand "test-iso" "Test an ISO image" (const testISOCommand) (pure ()) addCommand "make-disk" "Create a disk directory" makeDiskCommand (makeDiskOptions) addCommand "make-device" "Create a bootable device (WARNING: IT ERASES IT). You must be in the sudoers list" makeDeviceCommand (makeDeviceOptions) runCmd initCommand :: InitOptions -> IO () initCommand opts = do let template = initOptTemplate opts cd <- getCurrentDirectory withSystemTempDirectory "haskus-system-build" $ \fp -> do -- get latest templates showStep "Retrieving templates..." shellInErr fp "git clone --depth=1 https://github.com/haskus/haskus-system-templates.git" $ failWith "Cannot retrieve templates. Check that `git` is installed and that github is reachable using https." let fp2 = fp "haskus-system-templates" dirs <- listDirectory fp2 unless (any (== template) dirs) $ failWith $ "Cannot find template \"" ++ template ++"\"" -- copy template showStep $ "Copying \"" ++ template ++ "\" template..." shellInErr fp2 ("cp -i -r ./" ++ template ++ "/* " ++ cd) $ failWith "Cannot copy the selected template" readConfig :: IO SystemConfig readConfig = do let configFile = "system.yaml" unlessM (doesFileExist configFile) $ failWith $ "Cannot find \"" ++ configFile ++ "\"" mconfig <- readSystemConfig configFile case mconfig of Nothing -> failWith $ "Cannot parse \"" ++ configFile ++ "\"" Just c -> return c buildCommand :: BuildOptions -> IO () buildCommand opts = do config' <- readConfig -- override config let config = if buildOptInit opts /= "" -- TODO: use lenses then config' { ramdiskConfig = (ramdiskConfig config') { ramdiskInit = Text.pack (buildOptInit opts) } } else config' showStatus config gmpMain linuxMain (linuxConfig config) _ <- syslinuxMain (syslinuxConfig config) stackBuild testCommand :: TestOptions -> IO () testCommand opts = do config' <- readConfig -- override config let config = if testOptInit opts /= "" -- TODO: use lenses then config' { ramdiskConfig = (ramdiskConfig config') { ramdiskInit = Text.pack (testOptInit opts) } } else config' showStatus config gmpMain linuxMain (linuxConfig config) stackBuild ramdiskMain (ramdiskConfig config) qemuExecRamdisk config showStatus :: SystemConfig -> IO () showStatus config = do let linuxVersion' = Text.unpack (linuxConfigVersion (linuxConfig config)) let syslinuxVersion' = config |> syslinuxConfig |> syslinuxVersion |> Text.unpack let initProgram = config |> ramdiskConfig |> ramdiskInit |> Text.unpack ghcVersion <- stackGetGHCVersion stackResolver <- stackGetResolver putStrLn "===================================================" putStrLn " Haskus system - build config" putStrLn "---------------------------------------------------" putStrLn ("GHC version: " ++ ghcVersion) putStrLn ("Stack resolver: " ++ stackResolver) putStrLn ("Linux version: " ++ linuxVersion') putStrLn ("Syslinux version: " ++ syslinuxVersion') putStrLn ("Init program: " ++ initProgram) putStrLn "===================================================" makeISOCommand :: IO () makeISOCommand = do config <- readConfig showStatus config gmpMain linuxMain (linuxConfig config) stackBuild ramdiskMain (ramdiskConfig config) _ <- isoMake config return () makeDiskCommand :: MakeDiskOptions -> IO () makeDiskCommand opts = do config <- readConfig showStatus config gmpMain linuxMain (linuxConfig config) stackBuild ramdiskMain (ramdiskConfig config) makeDisk config (diskOptPath opts) testISOCommand :: IO () testISOCommand = do config <- readConfig showStatus config gmpMain linuxMain (linuxConfig config) stackBuild ramdiskMain (ramdiskConfig config) isoFile <- isoMake config qemuExecISO config isoFile makeDeviceCommand :: MakeDeviceOptions -> IO () makeDeviceCommand opts = do config <- readConfig showStatus config gmpMain linuxMain (linuxConfig config) stackBuild ramdiskMain (ramdiskConfig config) makeDevice config (deviceOptPath opts)