What is a Workspace?

Colcon is a command line tool to build and test multiple software packages. It builds and tests those packages in a colcon workspace, but what is a workspace?

This page assumes you have colcon-common-extensions installed.

What’s in a workspace?

A workspace has these parts:

  • Software packages
  • Build artifacts
  • Logs
  • Install artifacts

All these parts are put into different subdirectories of single directory, called the workspace root. Lets create a single directory for our workspace.

mkdir ws

Go into the root of our new workspace.

cd ws

Software packages

A workspace needs the source code of all the software to be built. Colcon will search all subdirectories of the workspace to look for packages, but an established convention is to put all the packages into a directory called src. Let’s create a directory for source code.

mkdir src

We’ll need at least one software package in the workspace. Let’s create a Python package.

mkdir src/foo
touch src/foo/setup.cfg
touch src/foo/setup.py
touch src/foo/foo.py

Put this content into src/foo/setup.py:

from setuptools import setup


Put this content into src/foo/setup.cfg:

name = foo
version = 0.1.0

py_modules =
zip_safe = true

test =

junit_suite_name = foo

Put this content into src/foo/foo.py:

def foo_func():
    print('Hello from foo.py')
    return True

Build artifacts

The software build process often produces intermediate build artifacts. They are usually not used directly, but keeping them around makes subsequent builds faster. Colcon always directs packages to build out-of-source, meaning the build artifacts are put into a directory separate from the source code. Every package gets its own build directory, but all build directories are put into a single base directory. By default it’s named build at the root of the workspace.


You can change where build artifacts are put using the --build-base option to colcon build.

Lets build the software and see its build artifacts.

# Make sure you run this command from the root of the workspace!
colcon build

You’ll see these new directories: build, install, and log.

├── build
│    └── foo/...
├── install/...
├── log/...
└── src
    └── foo
        ├── foo.py
        ├── setup.cfg
        └── setup.py

Notice the build directory has a subdirectory foo and a file COLCON_IGNORE. The foo subdirectory has all the build artifacts produced when building foo. The COLCON_IGNORE file tells colcon there are no software packages in this directory.


If you’ve built software before you know there can be a lot of console output, but you might have noticed not much was output when you ran colcon build. This output was instead written to the log directory.


You can change where logs are written to using the --log-base option to colcon.

Let’s look at the log directory:

├── build_2022-05-20_11-50-03
│    ├── events.log
│    ├── foo
│    │    ├── command.log
│    │    ├── stderr.log
│    │    ├── stdout.log
│    │    ├── stdout_stderr.log
│    │    └── streams.log
│    └── logger_all.log
├── latest -> latest_build
└── latest_build -> build_2022-05-20_11-50-03

The directory log/build_<date and time> contains all logs from the invocation of colcon build. A new directory is created every time colcon build is run. The foo sub directory contains all logs from building foo. There’s a more complete description of log files at this page: Log Files.

We’ve only built foo, so there are only build logs. Let’s add tests to foo and see the output.

Make a new file for the test.

touch src/foo/test_foo.py

Put the following content into test_foo.py:

import foo

def test_foo():
    assert foo.foo_func()

Tell colcon to run the tests.

# Make sure you run this command from the root of the workspace!
colcon test

Lets look in the log directory again.

├── build_2022-05-20_11-50-03/...
├── latest -> latest_test
├── latest_build -> build_2022-05-20_11-50-03
├── latest_test -> test_2022-05-20_11-50-05
└── test_2022-05-20_11-50-05
    ├── events.log
    ├── foo
    │    ├── command.log
    │    ├── stderr.log
    │    ├── stdout.log
    │    ├── stdout_stderr.log
    │    └── streams.log
    └── logger_all.log

There’s a new directory test_<date and time>. Let’s look at stdout_stderr.log to see the output of the latest test.

cat log/latest_test/foo/stdout_stderr.log


Use the command colcon test-result to see a summary of test results on the console after tests have been run.

Install artifacts

The last directory to talk about is the install directory. It contains both the installed software, and shell scripts that enable you to use it. This is sometimes called the install space.


You can change where packages are installed to with the --install-base option to colcon build.

Let’s look inside.

├── foo/...
├── local_setup.[bash|bat|ps1|sh|zsh|...]
├── _local_setup_util_[sh|ps1|...].py
└── setup.[bash|bat|ps1|sh|zsh|...]

The package foo was installed into the directory install/foo. By default colcon builds an isolated workspace (for more info see Isolated vs Merged Workspaces).

The shell scripts set environment variables that allow you to use the the software. Invoking the shell scripts is called sourcing a workspace.


Always source a workspace from a different terminal than the one you used colcon build. Failure to do so can prevent colcon from detecting incorrect dependencies.

Source the workspace using the appropriate script for your shell.

sh compatible shells:

# Note the . at the front; that's important!
. install/setup.sh


source install/setup.bash

Windows cmd.exe:

call install/setup.bat

Now you can use foo. Open a python interactive console and try it out.

>>> import foo
>>> foo.foo_func()
Hello from foo.py

Sourcing a workspace also allows you to build more software that depends on the packages in it. For more info about using colcon to build software that depends on packages in another workspace, see Using Multiple Workspaces.