Commit d8a7d586 authored by Michael Hanus 's avatar Michael Hanus
Browse files

CPM updated

parent daafe021
This directory contains some documention for the Curry Package Manager:
pakcs_manual.tex:
currysystem_manual.tex:
A short description to be included in the main manual of the Curry system.
manual.tex:
......
......@@ -604,13 +604,22 @@ caches.
\section{Command Reference}
\label{sec:cmd-reference}
This section gives a short description of all available CPM commands. In
addition to the commands listed here, there is a global parameter
\code{--verbosity}
which defaults to \code{info} but can be increased to \code{debug} for
more output.
Furthermore, there is a global parameter \code{--define} to override
the configuration options of CPM, see Section~\ref{sec:config}.
This section gives a short description of all available CPM commands.
In addition to the commands listed below, there are some global options
which can be placed in front of the CPM command:
\begin{description}
\item[\code{-v$\,|\,$--verbosity [info|debug]}:]
The default value is \code{info}.
The value \code{debug} provides more output messages in order to see
what CPM is doing.
\item[\code{-t$\,|\,$--time}:]
This option adds the elapsed time to every info or debug output line.
\item[\code{-d$\,|\,$--define $option$=$value$}:]
This option overrides the configuration options of CPM,
see Section~\ref{sec:config}.
\end{description}
%
The available commands of CPM are:
\begin{description}
\item[\fbox{\code{info}}] Gives information on the current package, e.g. the
......@@ -859,8 +868,9 @@ text of the license. The suggested name for this file is \code{LICENSE}.
\item[\fbox{\code{homepage}}] The package's web site. This field should contain
a valid URL.
\item[\fbox{\code{bugReports}}] A place to report bugs found int he package. The
suggested formats are either a valid URL to a bug tracker or an email address.
\item[\fbox{\code{bugReports}}] A place to report bugs found in the package.
The suggested formats are either a valid URL to a bug tracker
or an email address.
\item[\fbox{\code{repository}}] The location of a SCM repository containing the
package's source code. Should be a valid URL to either a repository (e.g. a Git
......@@ -934,6 +944,9 @@ if this package contains also an executable application.
The name of the executable must be defined (with key \code{name})
whereas the name of the main module (key \code{main}) is optional.
If the latter is missing, CPM assumes that the main module is \code{Main}.
Furthermore, the executable specification can also contain
options for various Curry compilers. The options must be a JSON object
consisting of compiler names as keys and an option string for the compiler.
For instance, a possible specification could be as follows:
%
\begin{lstlisting}
......@@ -941,8 +954,9 @@ For instance, a possible specification could be as follows:
...,
"executable": {
"name": "cpm",
"main": "CPM.Main"
}
"main": "CPM.Main",
"options": { "kics2" : ":set rts -T" }
}
}
\end{lstlisting}
%
......@@ -998,7 +1012,7 @@ directories \code{test} and \code{examples} could be as follows:
"testsuite": [
{ "src-dir": "test",
"options": "-v",
"script": [ "test.sh" ]
"script": "test.sh"
},
{ "src-dir": "examples",
"options": "-m80",
......@@ -1009,6 +1023,63 @@ directories \code{test} and \code{examples} could be as follows:
\end{lstlisting}
\end{description}
%
In order to provide a compact overview over all metadata fields,
we provide an example of a package specification where all fields
are used:
%
\begin{lstlisting}
{
"name": "PACKAGE_NAME",
"version": "0.0.1",
"author": "YOUR NAME <YOUR EMAIL ADDRESS>",
"maintainer": "ANOTHER NAME <ANOTHER EMAIL ADDRESS>",
"synopsis": "A ONE-LINE SUMMARY ABOUT THE PACKAGE",
"synopsis": "A MORE DEATILED SUMMARY ABOUT THE PACKAGE",
"category": [ "Category1", "Category2" ],
"license": "BSD-3-Clause",
"licenseFile": "LICENSE",
"copyright": "COPYRIGHT INFORMATION",
"homepage": "THE URL OF THE WEB SITE OF THE PACKAGE",
"bugReports": "EMAIL OR BUG TRACKER URL FOR REPORTING BUGS",
"repository": "THE (GIT) URL OF THE WEB SITE REPOSITORY",
"dependencies": {
"PACKAGE1" : ">= 0.0.1, < 1.5.0",
"PACKAGE2" : "~> 1.2.3",
"PACKAGE3" : ">= 2.1.4, < 3.0.0 || >= 4.0.0"
},
"compilerCompatibility": {
"pakcs": ">= 1.14.0, < 2.0.0",
"kics2": ">= 0.5.0, < 2.0.0"
},
"sourceDirs" : [ "src", "include" ],
"exportedModules": [ "Module1", "Module2" ],
"configModule": "ConfigPackage",
"executable": {
"name": "NAME_OF_BINARY",
"main": "Main",
"options": {
"kics2" : ":set rts -T",
"pakcs" : ":set printdepth 100"
}
},
"testsuite": [
{ "src-dir": "src",
"options": "-m80",
"modules": [ "Module1", "Module2" ]
},
{ "src-dir": "examples",
"options": "-v",
"script" : "test.sh"
}
],
"source": {
"git": "URL OF THE GIT REPOSITORY",
"tag": "$\$$version"
}
}
\end{lstlisting}
\section{Error Recovery}
\label{sec:recovery}
......
......@@ -9,6 +9,7 @@ module CPM.ErrorLogger
, logLevelOf
, levelGte
, getLogLevel, setLogLevel
, setWithShowTime
, (|>=)
, (|>)
, (|->)
......@@ -30,10 +31,6 @@ import System (exitWith, system)
infixl 0 |>=
infixl 0 |>
-- Should the current time be shown with every log information?
withShowTime :: Bool
withShowTime = False
--- An error logger.
type ErrorLogger a = ([LogEntry], Either LogEntry a)
......@@ -62,6 +59,21 @@ getLogLevel = readGlobal logLevel
setLogLevel :: LogLevel -> IO ()
setLogLevel level = writeGlobal logLevel level
-- Should the current time be shown with every log information?
withShowTime :: Global Bool
withShowTime = global False Temporary
--- Gets the "show time" information.
getWithShowTime :: IO Bool
getWithShowTime = readGlobal withShowTime
--- Sets the "show time" information. If true, then timing information
--- will be shown with every log information.
setWithShowTime :: Bool -> IO ()
setWithShowTime wst = writeGlobal withShowTime wst
---------------------------------------------------------------------------
--- Chains two actions passing the result from the first to the second.
(|>=) :: IO (ErrorLogger a) -> (a -> IO (ErrorLogger b)) -> IO (ErrorLogger b)
a |>= f = do
......@@ -170,11 +182,12 @@ failIO msg = return $ fail msg
--- Create an IO action that logs a message.
log :: LogLevel -> String -> IO (ErrorLogger ())
log lvl msg =
if withShowTime
log lvl msg = do
wst <- getWithShowTime
if wst
then do
runtime <- getProcessInfos >>= return . maybe 0 id . lookup ElapsedTime
return $ ([LogEntry lvl (showTime runtime ++ ' ':msg)], Right ())
return $ ([LogEntry lvl (showTime runtime ++ 's':' ':msg)], Right ())
else
return $ ([LogEntry lvl msg], Right ())
where
......
......@@ -24,8 +24,7 @@ import CPM.ErrorLogger
import CPM.FileUtil ( fileInPath, joinSearchPath, safeReadFile, whenFileExists
, ifFileExists, inDirectory, removeDirectoryComplete
, copyDirectory )
import CPM.Config ( Config ( packageInstallDir, binInstallDir
, repositoryDir, appPackageDir, curryExec )
import CPM.Config ( Config (..)
, readConfigurationWithDefault, showCompilerVersion )
import CPM.PackageCache.Global ( GlobalCache, readInstalledPackagesFromDir
, installFromZip, checkoutPackage
......@@ -46,7 +45,7 @@ cpmBanner :: String
cpmBanner = unlines [bannerLine,bannerText,bannerLine]
where
bannerText =
"Curry Package Manager <curry-language.org/tools/cpm> (version of 19/05/2017)"
"Curry Package Manager <curry-language.org/tools/cpm> (version of 24/05/2017)"
bannerLine = take (length bannerText) (repeat '-')
main :: IO ()
......@@ -67,6 +66,7 @@ main = do
runWithArgs :: Options -> IO ()
runWithArgs opts = do
setWithShowTime (optWithTime opts)
missingExecutables <- checkExecutables
unless (null missingExecutables) $ do
putStrLn $ "The following programs could not be found on the PATH " ++
......@@ -125,6 +125,7 @@ getGlobalCache config repo = do
data Options = Options
{ optLogLevel :: LogLevel
, optDefConfig :: [(String,String)]
, optWithTime :: Bool
, optCommand :: Command }
data Command
......@@ -320,7 +321,7 @@ applyEither (f:fs) z = case f z of
applyParse :: [Options -> Either String Options] -> Either String Options
applyParse fs = applyEither fs defaultOpts
where
defaultOpts = Options Info [] NoCommand
defaultOpts = Options Info [] False NoCommand
(>.>) :: Either String a -> (a -> b) -> Either String b
a >.> f = case a of
......@@ -340,6 +341,10 @@ optionParser = optParser
<> short "d"
<> metavar "DEFINITION"
<> help "Overwrite definition of cpmrc file with 'option=value'." )
<.> flag (\a -> Right $ a { optWithTime = True })
( long "time"
<> short "t"
<> help "Show elapsed time with every log output" )
<.> commands (metavar "COMMAND")
( command "checkout" (help "Checkout a package.") Right
(checkoutArgs Checkout)
......@@ -747,13 +752,15 @@ installExecutable cfg repo pkg =
-- the installation of the package:
getGlobalCache cfg repo >>= \gc ->
maybe (succeedIO ())
(\ (PackageExecutable name mainmod) ->
(\ (PackageExecutable name mainmod eopts) ->
getLogLevel >>= \lvl ->
getEnviron "PATH" >>= \path ->
log Info ("Compiling main module: " ++ mainmod) |>
let cmd = unwords $
[":set", if levelGte Debug lvl then "v1" else "v0",
":load", mainmod, ":save", ":quit"]
let (cmpname,_,_) = compilerVersion cfg
cmd = unwords $
[":set", if levelGte Debug lvl then "v1" else "v0"
, maybe "" id (lookup cmpname eopts)
, ":load", mainmod, ":save", ":quit"]
bindir = binInstallDir cfg
binexec = bindir </> name
in compiler CompilerOptions { comCommand = cmd }
......@@ -791,7 +798,7 @@ uninstall (UninstallOptions Nothing Nothing) cfg _ _ =
tryFindLocalPackageSpec "." |>= \pkgdir ->
loadPackageSpec pkgdir |>= \pkg ->
maybe (succeedIO ())
(\ (PackageExecutable name _) ->
(\ (PackageExecutable name _ _) ->
let binexec = binInstallDir cfg </> name
in ifFileExists binexec
(removeFile binexec >>
......@@ -958,7 +965,7 @@ docCmd opts cfg getRepoGC =
let docdir = maybe "cdoc" id (docDir opts)
exports = exportedModules pkg
mainmod = maybe Nothing
(\ (PackageExecutable _ emain) -> Just emain)
(\ (PackageExecutable _ emain _) -> Just emain)
(executableSpec pkg)
(docmods,apidoc) <-
maybe (if null exports
......
......@@ -100,9 +100,11 @@ data CompilerCompatibility = CompilerCompatibility String Disjunction
data PackageId = PackageId String Version
--- The specification to generate an executable from the package.
--- It consists of the name of the executable and the name of the main
--- module (which must contain an operation `main`).
data PackageExecutable = PackageExecutable String String
--- It consists of the name of the executable, the name of the main
--- module (which must contain an operation `main`), and list
--- of options for various compilers (i.e., pairs of compiler name and
--- options for this compiler).
data PackageExecutable = PackageExecutable String String [(String,String)]
deriving (Eq,Show)
--- The specification of a single test suite for a package.
......@@ -239,9 +241,15 @@ packageSpecToJSON pkg = JObject $
revToJSON VersionAsTag = [("tag", JString "$version")]
maybeExecToJSON =
maybe [] (\ (PackageExecutable ename emain) ->
[("executable", JObject [ ("name", JString ename)
, ("main", JString emain)])])
maybe [] (\ (PackageExecutable ename emain eopts) ->
[("executable", JObject $ [ ("name", JString ename)
, ("main", JString emain)] ++
exOptsToJSON eopts)])
where
exOptsToJSON eopts =
if null eopts
then []
else [("options", JObject $ map (\ (c,o) -> (c, JString o)) eopts)]
maybeTestToJSON = maybe [] (\tests -> [("testsuite", testsToJSON tests)])
where
......@@ -705,7 +713,22 @@ execSpecFromJObject :: [(String, JValue)] -> Either String PackageExecutable
execSpecFromJObject kv =
mandatoryString "name" kv $ \name ->
optionalString "main" kv $ \main ->
Right $ PackageExecutable name (maybe "Main" id main)
case lookup "options" kv of
Nothing -> Right $ PackageExecutable name (maybe "Main" id main) []
Just (JObject o) -> case optionsFromObject o of
Left e -> Left e
Right os -> Right $ PackageExecutable name (maybe "Main" id main) os
Just _ -> Left "Expected an object for 'executable>options'"
where
optionsFromObject o =
let os = map (extractString . snd) o
in if any isLeft os
then Left $ head (lefts os)
else Right (zip (map fst o) (map fromRight os))
extractString s = case s of
JString s' -> Right s'
_ -> Left $ "'executable>options': values must be strings"
--- Reads a test suite specification from the key-value-pairs of a JObject.
testSuiteFromJObject :: [(String, JValue)] -> Either String [PackageTest]
......
......@@ -76,7 +76,8 @@ writePackageConfig :: Config -> String -> Package -> IO (ErrorLogger ())
writePackageConfig cfg pkgdir pkg =
maybe (succeedIO ())
(\ configmod ->
let binname = maybe "" (\ (PackageExecutable n _) -> n)
let binname = maybe ""
(\ (PackageExecutable n _ _) -> n)
(executableSpec pkg)
in if null configmod
then succeedIO ()
......
......@@ -244,10 +244,14 @@ renderPackageInfo allinfos plain gc pkg = pPrint doc
execspec = case executableSpec pkg of
Nothing -> empty
Just (PackageExecutable n m) ->
Just (PackageExecutable n m eopts) ->
boldText "Executable" <$$>
indent 4 (boldText "Name " <+> text n) <$$>
indent 4 (boldText "Main module " <+> text m)
indent 4 (boldText "Main module " <+> text m) <$$>
if null eopts
then empty
else indent 4 (boldText "Options ") <+>
align (vsep (map (\ (c,o) -> text $ c ++ ": " ++ o) eopts))
testsuites = case testSuite pkg of
Nothing -> []
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment