Automating your Rust workflows with cargo-make - Part 5 (final) - Predefined Tasks, CI Support and Conventions

Predefined Tasks

When cargo-make starts, it first reads an internal Makefile.toml (found here) which gives you a very large set of tasks that can be used right away without writing any external Makefile.toml or configuring anything in your machine.

In this section I’ll go over on some of the most common tasks and flows. The actual list is much bigger.

  • The default flow - Can be invoked without writing any task name in the command line (simply run cargo make), points to the dev-test-flow which runs formatting, build and tests. This task is particularly useful during development when you want to cleanup your code and test it which means you would probably run this one a lot and therefore is defined as the default task.
  • ci-flow - This is the task you would run for standalone Rust modules in your build server or in online CI servers. I will explain more about this one later on in this article.
  • workspace-ci-flow - The workspace CI task. Like ci-flow, I’ll explain more about this special flow later on in this article.
  • publish-flow - Cleans the target directory of any old stuff and runs the cargo publish command.
  • github-publish - Creates a new release in Github.

A more detailed list of tasks can be found here.

Predefined Coverage Flows

Creating a coverage report was never that easy in Rust, however cargo-make has built in support for that and will require no additional manual installations on your part.

cargo-make has built in support for multiple coverage tasks. Switching between them without modifying the flows is done by changing the main coverage task alias.

Currently the main coverage task is defined as follows:

alias = "coverage-kcov"

To switch to another provider simply change the alias to that specific task name, for example if we would like to use the already defined tarpaulin provider:

alias = "coverage-tarpaulin"

You can run:

cargo make --list-all-steps | grep "coverage-"

To view all currently supported providers. Example output:

ci-coverage-flow: Runs the coverage flow and uploads the results to codecov.
coverage-tarpaulin: Runs coverage using tarpaulin rust crate (linux only)
coverage-flow: Runs the full coverage flow.
coverage-kcov: Installs (if missing) and runs coverage using kcov (not supported on windows)

Continuous Integration Support

As shown in previous section, cargo-make comes with two predefined flows for continuous integration builds executed by internal or online services such as travis-ci and appveyor.

The predefined CI flows (ci-flow and workspace-ci-flow) run the following actions:

  • Run build with verbose output
  • Run tests with verbose output
  • For linux based platforms and if configured, it will also generate coverage report and upload to codecov.

For workspace projects that require coverage report containing all data from all members, the workspace-ci-flow is needed as it will not publish each members coverage on its own and instead collect from all members their reports and submit it entirely in one bundle.


For travis, we need to replace the default behavior and instead install cargo-make and run the ci-flow as follows:

- cargo install --debug cargo-make
- cargo make ci-flow

If you want a coverage report to be generated and uploaded to codecov, simply define the following environment variable.


You can see full yaml file here.

When working with workspaces, in order to run the ci-flow for each member and package all coverage data, use the following command:

- cargo install --debug cargo-make
- cargo make workspace-ci-flow --no-workspace


For window based builds, appveyor is the most common online service. The process of modifying the appveyor.yml is very similar to travis, however coverage is currently not supported on windows.

In your appveyor.yml just write the following:

build: false

- cargo install --debug cargo-make
- cargo make ci-flow

You can see full yaml file here.


This section explains the logic behind the default task names.
While the default names logic can be used as a convention for any new task defined in some project Makefile.toml, it is not required.

The default Makefile.toml file comes with three types of tasks:

  • Single command or script task (for example cargo build)
  • Tasks that come before or after the single command tasks
  • Tasks that define flows using dependencies

Single command tasks are named based on their commmand (in most cases), for example the task that runs cargo build is named build.

command = "cargo"
args = ["build"]

This allows to easily understand what this task does.

Tasks that are invoked before/after those tasks as part of a flow, are named the same way as the original task but with the pre/post prefix.
For example for task build the default toml also defines pre-build and post-build tasks.



In the default Makefile.toml file, all pre/post tasks are empty and are there as placeholders for external Makefile.toml to override so custom functionality can be defined easily before/after running a specific task.

Flows are named with the flow suffix, for example: ci-flow

# CI task will run cargo build and cargo test with verbose output
dependencies = [

This prevents flow task names to conflict with single command task names and quickly allow users to understand that this task is a flow definition.

Wrapping Up

We reached the end of this set of articles on cargo-make and most of the features were described in detail. However, if you wish to learn more and keep up to date with changes, you are welcome to look at the official github repo for more info.

I hope you enjoyed these articles and give cargo-make a try. I would love to get some feedback from the community, from missing features to questions.

Thanks All.