{-# OPTIONS_GHC -fno-warn-missing-signatures #-} {-# LANGUAGE UnicodeSyntax, LambdaCase #-} import Data.List (isPrefixOf) import Distribution.Simple import Distribution.Types.HookedBuildInfo import System.Directory import System.Exit (ExitCode (..)) import System.Process (callProcess, readProcessWithExitCode) main = defaultMainWithHooks simpleUserHooks { preBuild = buildDuktape } outputDir = "dukconfig/dist" scriptFile = "duktape/tools/configure.py" scriptArgs = [ "--output-directory", outputDir , "--source-directory", "duktape/src-input" , "--config-metadata", "duktape/config" , "--option-file", "dukconfig/config.yaml" ] repoSource = "duktape/src/duktape.c" builtSource = "dukconfig/dist/duktape.c" buildDuktape _ _ = do script ← doesFileExist scriptFile if script then do createDirectoryIfMissing True outputDir needBuild ← filesCurrent if needBuild then do runScript done else done else done where done = return emptyHookedBuildInfo filesCurrent = do builtExists ← doesFileExist builtSource if builtExists then do repoTime ← getModificationTime repoSource builtTime ← getModificationTime builtSource return $ repoTime > builtTime else return True runScript = findPython >>= \case Right python → callProcess python (scriptFile : scriptArgs) Left reason → do putStrLn "Couldn't find Python 2 with PyYAML, which is required to configure duktape." putStrLn reason -- Duketape's configure script requires python2 with PyYAML installed. -- Check candidates "python2, python" and return one that will work or reasons why findPython ∷ IO (Either String FilePath) findPython = tryPython "python2" >>= \case Left reason2 → tryPython "python" >>= \case Left reason → return $ Left $ concat ["python2: ", reason2, "\npython: ", reason] found → return found found → return found where tryPython exe = findExecutable exe >>= \case Nothing → return $ Left "Executable not found." Just path → checkPython path checkPython path = readProcessWithExitCode path ["--version"] "" >>= \case (ExitSuccess, "", version) → checkPrefix version path (ExitSuccess, version, "") → checkPrefix version path (ExitFailure _, out, err) → return $ Left (out ++ err) _ → return $ Left "Execution failed." checkPrefix version path | "Python 2" `isPrefixOf` version = checkPyYAML path | otherwise = return $ Left version checkPyYAML path = readProcessWithExitCode path ["-c", "import yaml"] "" >>= \case (ExitSuccess, "", _) → return $ Right path _ → return $ Left "No PyYaml installed."