Command-Line Tools¶
This section describes the Coco Platform command-line tools. These tools can be separately installed from Downloads.
coco¶
The coco
tool provides command-line access to all of the core features of the Coco Platform, including validating Coco
files, formally verifying them, and then generating code. The main purpose of the command-line tools is to enable Coco
to be integrated into a larger build process, but the tools are also designed to be human-usable as well.
-
coco [«global options»] «subcommand» [«options»] [«input files»]
«global options»: The options that can be used with every «subcommand». See Global Options.
«subcommand»: One of the following subcommands:
format
:Format Coco source files. generate-cpp
:Generates C++ code graph-component
:Creates an architecture diagram of an encapsulating component graph-states
:Creates a graph of a state machine metadata
:Outputs metadata about a Coco package support-bundle
:Generates a zip file suitable for emailing to support transform
:Transforms Coco source files using Coco’s semantically-aware transformations. typecheck
:Type check Coco source files. «options»: Options specific to the chosen «subcommand».
«input files»: The set of files to be processed.
The coco
tool will either operate in package or standalone mode, depending on whether a Coco.toml
file can be
found to describe the Coco package to operate on. By default, coco
will search the current working directory and every
parent directory for a Coco.toml
file. If none is found, then the tool is operating in standlone mode, and will only
perform the given subcommand on the specified files. In general, when operating in package mode, the subcommand will
apply to all files in the package, unless otherwise specified, whereas in standalone mode, the subcommand will always
operate on the specified files.
For example, suppose the current working directory is MyProject
and this contains a Coco.toml
file, then:
coco verify
will execute the verify subcommand on all of the Coco files belonging to MyProject
.
Suppose there are Coco files in MyProject/src
. The following command:
coco verify src/M.coco src/N.coco
will execute the verify subcommand on the files named M.coco
and N.coco
in the
subdirectory src
.
Global Options¶
These options are common to every subcommand.
-
--colour
<boolean>
¶ Specify whether or not the console text output is coloured.
-
--diagnostic-format
<option>
¶ Specify the format of error and warning messages.
Option: checkstyle-xml
Errors and warnings are output in the Checkstyle XML format.
Option: console
Error and warnings are output in plain text.
Default: console
-
--error-limit
<limit>
¶ Specify a limit for the number of errors to emit.
-
--import-path
,
-i
<path>
¶ Specify an additional directory to be searched for imported files. This option can be specified multiple times. If the tool is operating in package mode, then the given directory is used to search for dependencies of the current package, as specified by
package.dependencies
. If the tool is operating in standalone mode, this folder will be added to the back of the search path of Coco modules when resolving an import likeimport X
.
-
--no-crash-reporter
¶
Prevent the Coco Platform crash reporter from starting.
-
--no-license-server
¶
Prevent the Cocotec license server from starting. If specified, it prevents a license server from being started. A valid license must already have been installed in the default location on your computer. If not, this option will prevent
coco
from executing.
-
--override-licenses
<path>
¶ Override the path to the file containing the Coco licenses. This option is only allowed together with the
--no-license-server
option. When specified, there must be a valid license in the specified directory.Option: The name of the directory containing a valid license file to be used. Default: The license file is searched for in the default location.
-
--override-preferences
<path>
¶ Override the default preferences file. By default, coco shares the preferences specified in Eclipse.
-
--package
<path>
¶ Specify the directory containing the package file. This means that:
$ coco --package $dir verify
is equivalent to:
$ cd $dir $ coco verify
For example:
$ coco --package ~/src/pkg verify
If
~/src/pkg
contains aCoco.toml
file, thencoco
will verify all modules in the package.
-
--stats
¶
Display timing and resource usage information.
-
--version
¶
Display current version information.
-
--warning-limit
<limit>
¶ Specify a limit for the number of warnings to emit.
Subcommands¶
format
¶
Automatically reformats all of the Coco files according to a specified style. In package mode, the settings specified in the [format] section will be used. In standalone mode, default formatting settings are used.
-
--verify
¶
The specified files are not modified. Instead, the console output shows the changes that would be made to them to conform to the applicable format preference settings. In this case, the exit code of the tool will be 0 only when no changes need to be made, and will be 1 if the files are not correctly formatted.
Common generation options¶
-
--code-index-format
<option>
¶ Specify the format of the generated code index.
Option: json
Minimised JSON (i.e. no linebreaks, no spaces etc).
Option: pretty-json
Pretty-printed JSON.
Default: json
-
--output-code-index
<path>
¶ If set to a path, then a code index of the generated code will be created.
See also
C++ Code Index for details on the C++ code index.
-
--output
<path>
,
-o
<path>
¶ Specify the directory in which the generated C++ files are created. If the directory does not exist, it is automatically created. If it does exist, its contents are merged with any new files that are generated. If this option is not specified, then the default value is
generated
, relative to the current package.
-
--output-deps
¶
Specify if gcc-style deps files with dependency information should be generated together with the generated files.
-
--output-empty-files
¶
Coco will generate one header file and one implementation file for every Coco file processed, even if the file would be empty.
See also
-
--output-unchanged-files
¶
Normally the command-line tool will not update generated files whose contents have not changed. With this flag, the tool will touch files that have not changed if the timestamp of the .coco file from which they were generated is newer than the timestamp of the generated file. This flag is primarily for compatibility with timestamp-based build systems such as make.
See also
generator.cpp.outputUnchagedFiles
generate-cpp
¶
Generate C++ source files from the specified Coco files according to the preference settings in the [generator.cpp] section of applicable package file. In addition to the options below, the options from Common generation options are also permitted.
-
--header-file-suffix
<string>
¶ Equivalent to
package.headerFileSuffix
.
-
--header-for
<path>
¶ If
path
is a path to a .coco file, will cause the generator to only generate the header file corresponding to the given .coco file.
-
--include-prefix
<path>
¶ Prepend the specified path to all include paths in the generated code.
Option: The path to prepend all include paths in the generated code.
-
--mocks
<option>
¶ Specify whether or not mocks should be generated and if so, which format should be used.
Option: none
No mocks are generated.
Option: gmock
Generate mocks compatible with the
MOCK_METHOD
macros.Option: gmock-legacy
Generate mocks compatible with the old-style deprecated
MOCK_METHODn
macros.Default: none
-
--implementation-file-suffix
<string>
¶ Equivalent to
package.implementationFileSuffix
.
-
--implementation-for
<path>
¶ If
path
is a path to a .coco file, will cause the generator to only generate the implementation file corresponding to the given .coco file.
-
--output-runtime-header
¶
Equivalent to
package.outputRuntimeHeader
.
graph-component
¶
Produces a graphical representation of the architecture of a Coco component, like that produced in the Eclipse Architecture Diagram View. For example:
$ coco graph-component --component=Comp -o - src/M.coco
Will generate the architecture diagram of Comp
in M.coco
, and will write it to standard out.
-
--component
<name>
¶ The name of the component or port whose state machine should be graphed. This can be specified multiple times.
-
--hide-ports
¶
Specifies that all ports should be hidden.
-
--multi
¶
Specifies that multiple components can be graphed, which may result in multiple output files being produced.
-
--output
<path>
¶ The path to where to save the generated diagram. If this is not specified, then the file is placed alongside the .coco file. If this is set to ‘-‘, then the diagram is written to standard out.
graph-states
¶
Produces a graphical representation of a state machine, like that produced in the Eclipse State Diagram View. For example:
$ coco graph-states --target=Comp -o - src/M.coco
This will generate the state diagram for the state machine of Comp
in M.coco
, and will write it to standard out.
-
--target
<name>
¶ The name of the component or port whose state machine should be graphed.
-
--format
<option>
¶ Option: dot
The Graphviz’s dot format will be used.
Option: svg
A SVG image will be produced.
Default: svg
-
--hide-labels
¶
Specify that all labels on transitions should be hidden in the generated diagram.
-
--output
<path>
¶ The path to where to save the generated diagram. If this is not specified, then the file is placed alongside the .coco file. If this is set to ‘-‘, then the diagram is written to standard out.
-
--separate-edges
¶
Whether to produce a separate edge for each transition. By default transition edges are collapsed by generating one shared edge for all transitions between a given pair of states.
metadata
¶
Outputs metdata about a Coco package, depending on the option that is selected:
-
--selected-tool-version
¶
Prints the value of the
tool.selectedVersion
property to stdout, including interpreting any special values that are permitted as part of this property.
support-bundle
¶
This command copies a project, together with all of its dependencies, and creates a single zip file that is suitable for sending to support@cocotec.io. This command is intended for sharing confidential projects with Cocotec, as in addition to bundling all the files together, the bundler also renames all Coco identifies to randomly chosen names in a semantically-preserving fashion, and removes all comments.
-
--output
<path>
¶ The path where the .zip file should be saved.
transform
¶
Executes one of Coco’s semantically aware transformations. When operating in package mode, all files in the current package are transformed (depending on the transformation selected), whereas when operating in standalone mode, just the specified files are transformed.
The following options are common to all transformations:
-
--format
<option>
¶ Option: none
No files are formatted.
Option: modified-files
All modified files are formatted.
Default: none
Specifies whether the transformed files should be automatically formatted using the Coco formatter.
-
--output-mode
<option>
¶ Option: in-place
Files are overwritten with the modified contents.
Option: preview
Modified files are printed to stdout.
Default: in-place
Specifies where the results of the transformation should be saved.
-
--selection
<name>
¶ A fully qualified name to the declaration to apply the transformation to, or the string
:all
to specify that the transformation should be applied to all declarations that it makes sense to apply it to.
transform-flatten-port
¶
This transformation converts a composite port into a leaf port. This can be useful when there are only a small number of functions and signals defined amongst the different child ports, and therefore the composite port only serves to complicate the representation.
As an example, given:
port Composite {
port P1 {
function f1() : Nil
}
port P2 {
enum AnEnum {
case AMember
case AnotherMember
}
outgoing signal cb(y : AnEnum)
}
val p1 : P1
val p2 : P2
machine {
state Operational {
p.f1() = p2.cb(P2.AnEnum.AMember)
}
}
}
The transformation will produce:
port Composite {
function f1() : Nil
enum AnEnum {
case AMember
case AnotherMember
}
outgoing signal cb(y : AnEnum)
machine {
state Operational {
f1() = cb(AnEnum.AMember)
}
}
}
In addition to rewriting the port, the transformation also updates all components that use the port to use the correct functions and signals.
To apply this transformation:
- The port must be composite and have a state machine.
- The nested ports must be defined within the main port, not use inheritance, and there must be exactly one instance of each child field.
transform-merge-signals
¶
This transformation converts pairs of signals into a single signal that has a parameter of type Result
in order to
distinguish between the two cases. This transformation can be useful when there are many layers of a system that do not
need to distinguish between the cases, and instead just pass on the signal to the layer above. In such cases, this
transformation can eliminate a lot of redundancy.
As an example, given:
port P {
function fn() : Nil
outgoing signal fn_cb_OK()
outgoing signal fn_cb_ERROR()
machine M {
fn() = nondet { fn_cb_OK(), fn_cb_ERROR() }
}
}
This is transformed to:
This transformation will attempt to identify pairs of signals of the form: x_cb_OK
and x_cb_ERROR
and will merge
them into a single signal called x_cb
. These suffixes can be customised using the following options:
-
--error-suffix
<suffix>
¶ Default: _cb_ERROR
This specifies a string that should be searched for to identify the error signal. This will be used as the error case of the
Result
.
-
--ok-suffix
<suffix>
¶ Default: _cb_OK
This specifies a string that should be searched for to identify the success signal. This will be used as the ok case of the
Result
.
-
--new-suffix
<suffix>
¶ Default: _cb
This is used to compute the name of the combined signal. More precisely, the name of the combined signal is calculated by removing the error-suffix, and then adding new-suffix.
transform-to-external-functions
¶
This transformation converts a stateless port into a collection of external functions. This can be useful when the functions are simple (e.g. logging functions), as the resulting Coco model will be simpler, easier to maintain, and will have better performance at runtime.
As an example, consder the port:
This is transformed to:
enum E {
case X
case Y
}
external function fn(x : Bool) : E = E.X
In addition to rewriting the port, the transformation also updates all components that have required ports of type P
to instead use the external functions, and removes any such ports from encapsulating components.
In order to apply this transformation, the port must:
- Not be composite, or contain signals, or inherit from another port.
- Must have a stateless state machine (i.e. a state machine with no states and no variables), where every transition
is an
event transition
whose handler is anexpression
.
typecheck
¶
Checks that the specified Coco files are all type-correct. When operating in package mode, all files in the current package are typechecked, whereas when operating in standalone mode, just the specified files are typechecked.
verify
¶
Verifies all of the specified Coco files. When operating in package mode, all files in the current package are verified, whereas when operating in standalone mode, just the specified files are verified.
-
--backend
<option>
¶ Specify which verification backend is to be used.
Option: local
Verification is performed locally.
Option: attempt-remote
If the remote verification service is available, verification is carried out using the remote service. Otherwise, it is carried out locally.
Option: remote
Verification is carried out using the remote verification service only, raising an error if it is not reachable.
Default: if a preference has been set in Eclipse, then that is used, otherwise
local
.
-
--benchmark
¶
Output performance data that can be used for verification benchmark comparisons.
-
--ignore-cache
¶
Ignores all cached verification results when using the remote verification backend.
-
--format
<option>
¶ Specify verification output format.
Option: junit
Verification output is formatted as JUnit-compatible XML.
Option: console
Verification output is formatted as text.
Default: console
-
--quiet
¶
Suppresses progress information that is normlaly output whilst the verification is running.
-
--max-local-jobs
¶
The maximum number of verification jobs that should be executed concurrently when running verification on the local machine.
Using coco
in CI pipelines¶
The commands described above should allow coco to be easily used as part of a continuous integration (CI) pipeline. For example:
coco format --verify
can be used to validate that all Coco code conforms to the Coco standard style. This outputs a diff if it detects any violations.coco --diagnostic-format=checkstyle-xml typechecker
can be used to check that all Coco code is syntactically and type correct, and will output diagnostics in Checkstyle-compatible XML, as accepted by some CI tools.coco verify --format=junit
can be used to verify all models, and to output the verification results as JUnit-compatible XML, which many CI tools can display.coco generate-cpp
and other generation commands can be used to generate code as part of the build.
See the Coco command-line tool for further details on these options and other useful options.
Licensing¶
To use Coco as part of a continuous integration (CI) pipeline, each machine that coco
executes on will require a
license. Since CI machines are often ephemeral, it can be inconvienient to license them using the usual interactive
commands. Instead, Coco can be configured to use a license token that is not tied to any specific machine, but can
instead be exchanged by a specific machine for a real license when it is required by connecting to a license server.
Further, this license server can either be run on-premise, or Cocotec’s licensing server can be used, providing the CI
machines are able to access the internet.
To setup Coco to use a machine token:
Contact support@cocotec.io to request a machine license token, unless your organisation already has an existing on-premise license server in which case please contact your local administrators. When contacting Cocotec Support, please indicate if you require a on-premise license server to be setup, or if your CI systems have access to the internet and can therefore use Cocotec’s licensing servers.
Store the machine license token securely using whatever secret storage mechanism you use. For example, common CI providers have builtin solutions for storing secrets:
Configure your CI pipeline to pass the authentication token to coco. The best way of doing this depends upon the number of times that you execute coco during the build:
coco
is only executed once:Set the environment variable
COCOTEC_AUTH_TOKEN
to the value of machine token before executingcoco
.coco
will read this environment variable and then connect to the appropriate license server to obtain a license.coco
is executed multiple times:To avoid the overhead of connecting to the license server everytime
coco
is invoked, it is instead best to obtain a license up-front, and then reuse the license for the rest of the pipeline. This can be done by firstly executingcocotec-licensing-server
to obtain the license, and then passing the cached license tococo
. For example:$ export COCO_LICENSE_CACHE_FILE=<path> $ cocotec-licensing-server --acquire=coco-platform --license-file=$COCO_LICENSE_CACHE_FILE ... $ coco --no-license-server --override-licenses=$COCO_LICENSE_CACHE_FILE
This will obtain a license using
cocotec-licensing-server
and then save the path specified in$COCO_LICENSE_CACHE_FILE
. Whencoco
is executed later, it will use the license that was obtained earlier. To make this work,cocotec-licensing-server
has to be supplied the machine authentication token. This can be done either by setting theCOCOTEC_AUTH_TOKEN
environment variable only when invokingcocotec-licensing-server
:COCOTEC_AUTH_TOKEN=... cocotec-licensing-server --acquire=coco-platform --license-file=$COCO_LICENSE_CACHE_FILE
or, if the authentication token is available in a file called
cocotec_token
:cocotec-licensing-server --acquire=coco-platform --license-file=$COCO_LICENSE_CACHE_FILE --auth-token=cocotec_token