packages feed

hs-duktape-1.0.0: Setup.hs

{-# 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."