Managing the Makefile for ModusToolbox™ software v2.x

The ModusToolbox™ build infrastructure creates a project based on information in a Makefile. This document explains how you can manage the Makefile to accomplish common tasks, and it is in the form of questions and answers. As appropriate, the answer provides a common use case, what you need to know to get the task done, and an example snippet. For a more general view of ModusToolbox™ software, including the build system, refer to the ModusToolbox™ user guide.

This document uses the following terms:

  • Makefile directory: The folder that contains the Makefile; this may be a code example (starter application) or your project.

  • project directory: The folder created during the project creation process; contains all files for the project, including a copy of the Makefile.

  • .lib file: A text file that contains a URL to a GitHub repository and a tag or SHA for a specific commit (this file is only relevant in ModusToolbox™ version 2.1 and older).

  • .mtb file: A text file that contains a URL to a GitHub repository, a tag or SHA for a specific commit, and information on where to place the content on disk.

  • auto-discovery: The process by which the build infrastructure automatically finds files.

  • tools_<version> directory: This directory contains all the tools, configurators and files required by ModusToolbox™ software to work. This directory is available in the ModusToolbox™ installation directory.

  • mtb_shared directory: The folder that contains libraries that can be shared across projects in the workspace. This is applicable only from ModusToolbox™ 2.2 and newer. In older versions, this is the libs directory at the root of the project folder.

    When you create a project using the ModusToolbox™ build system, all files required by the project are copied into the project directory and all libraries are copied into the mtb_shared directory. This includes the original Makefile found in the code example (starter application).

What is the Makefile and how do I use it?

The Makefile describes how to create and build a project. It contains information about what files to use, what libraries to include, what build tools to use, and so forth. This Makefile is specific to the ModusToolbox™ build system. For general background and reference information on the command line interface, refer to the ModusToolbox™ user guide.

We provide many code examples on GitHub, which can be thought of as starter applications. Each contains a Makefile and source files specific to the application. A code example is not self-contained. When you use the Eclipse IDE’s New Application wizard, or the stand-alone Project Creator tool, the build system is invoked, and all files required for the project appear in the project directory. If you use the Eclipse IDE for ModusToolbox™, this folder is in your Eclipse workspace. If you use the Project Creator, the project directory is wherever you put it. You can then add the files to your preferred IDE, or work from the command line.

The Makefile controls the project creation and build process. The original Makefile from the code example is duplicated in the project directory.

Which Makefile should I edit, the one in the code example or the one in the project directory?

Typically, you create a project from a code example, and then edit the Makefile in your project directory. The changes are local to your project.

However, you can download a local copy of the code example from GitHub and edit that Makefile. If you edit the Makefile in your copy of the code example, any project built from that example has your changes.

In other questions and answers, this document refers to the Makefile directory. This could be either your project directory or a local copy of the code example.

What build system does ModusToolbox™ software use?

ModusToolbox™ software uses a build system that is make based. The make folder in the tools directory contains .mk files that are used to bootstrap the build process (e.g., implements the make getlibs target that downloads the rest of the build system from git).

Additionally, once the project is created, the BSPs and libraries contain .mk files that define the flow and configuration of how the build must execute. Here are some of the important files/directories and their effect on the build system:

  • core-make: This is the common core of the build system that implements auto-discovery (see file, build (see file, IDE support (see file, target search (see file, compilation and linking (see file and integration (see file

  • recipe-make-<category>: This customizes the build process for a particular device family (e.g., make sure correct CPU type flags and linker scripts are used).

  • TARGET_<BSP>/release-v1.x.x/<BSP>.mk: This customizes the build process even further for a particular board.

How do I add files to the project so that auto-discovery finds them?

The build infrastructure automatically finds all source files in the Makefile directory. This includes .c, .cpp, .h, .hpp, .S, .s, .o, and .a files.

As a result, a simple solution is to add the files to the Makefile directory. The search is recursive, so you can add the files anywhere in the Makefile directory tree and the make build command finds them.

However, the common use case is that you have files that exist outside the Makefile directory; for example, a collection of source code on a company server. To discover files outside the Makefile directory, you can add the path to the external directory using the CY_EXTAPP_PATH variable.


Use the SOURCES and INCLUDES variables to explicitly specify the source and header files to the build process from a location not searched by the build system.

The SOURCES value must be a space-separated list of specific files. Paths can be absolute or relative to the Makefile directory to locate the files. You can create a search pattern with wildcards to find multiple files.

SOURCES=$(wildcard ../MySource1/.c) $(wildcard ../MySource2/.c)

Use the INCLUDES variable to specify the folder for header files. The value is a space-separated list of relative paths to the directories.

INCLUDES=../MySource1 ../MySource2

You can also specify that certain files or folders should be ignored. See How do I make sure auto-discovery ignores certain files?

For more information refer to the section “Adding Source Files” in the ModusToolbox™ user guide.

How can I add a path that contains spaces?

Spaces in paths are problematic with many build tools, so avoid them whenever possible. If you must have spaces in a path, use the $(wildcard) function to properly escape paths that contain spaces.

INCLUDES=$(wildcard ../My Source/)

CY_COMPILER_PATH=$(wildcard C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.3/arm/bin)

How can I use an absolute path when the variable value requires a relative path?

The files you want to add may live someplace specific on a company server or your local machine. An absolute path can be easier to manage. In this case, you can create a make variable configured with an absolute path and use that as part of your “relative” path.

ABS_PATH=C:/<path_to_source>/ExternalSourceFiles/ SOURCES=$(ABS_PATH)/external_source.c

How are slashes handled by the build system?

On Windows, ModusToolbox™ software uses Cygwin make under the hood. Cygwin is a POSIX-compatible environment. POSIX paths use forward slash “/” as the separator for paths. Therefore, “/” must be used when specifying any path in the Makefile.

Windows path names use backslash “” as the path separator. In cases when there is a long absolute path and you need to replace “” with “/”, you can use the $(subst) function to make the conversion easier.

WIN_PATH=C:Users<some_long_path>HeaderFiles HEADER_FILE=$(subst\,/,$(WIN_PATH)) INCLUDES=$(HEADER_FILE)

When specifying a value for ModusToolbox™ make variables using the System Variable in the Environment Variable dialog, ensure you use forward slashes. For example, to specify the tools directory to be used, you can make use of the CY_TOOLS_PATHS system variable. Note that the value you enter must use forward slashes.

How do I make sure auto-discovery ignores certain files?

For example, you may have a subfolder with files used by a test or verification system, and you don’t want those compiled into your executable.

Use the CY_IGNORE variable. The value is a space-separated list of folders and/or specific files you want ignored by auto-discovery. Use paths relative to the Makefile directory. You can create a search pattern with wildcards to ignore multiple files.

CY_IGNORE=./filename.c ./TestFolder


How do I add an external library using a .lib/.mtb text file?

The ModusToolbox™ build infrastructure uses the git version control system. An external library can be specified using the .lib or the .mtb file, but the latter is recommended.

Using the .lib file:

A .lib file is typically a single line of text that represents a URL to a git repository, and a specific commit within that repository. The only difference here is that it does not specify where the repo should be created. It places it in the local libs folder at the root of the project folder by default. The .lib files provided by Cypress always point to a publicly available Cypress-owned repository, typically on GitHub. For example, this .lib file imports the latest version of the Peripheral Driver Library into a project.

To add your own library, create a .lib file that points to a git repository. Place the .lib file in the Makefile directory. For example:

The make getlibs command finds and processes all .mtb/.lib files and uses the git command to clone or pull the code as appropriate. Then, it checks out the specific hash or tag listed in the .mtb/.lib file. The Project Creator and Library Manager tools invoke make getlibs automatically.

How do I add an external library by specifying files and file paths?

How do I add a precompiled binary to my project?

The build infrastructure automatically finds .o and .a binary files in the Makefile directory. A simple solution is to add the files to the Makefile directory.

However, a common use case is that the binary file(s) exist outside the Makefile directory. Use the LDLIBS variable to specify application-specific precompiled binaries. The LDLIBS value must be a space-separated list of specific files. Use paths relative to the Makefile directory to locate the files. You can create a search pattern with wildcards to find multiple files. These files are included in the link process.


LDLIBS+=$(wildcard ../lib/*.a)

If you need to include the header files for the binary, use the INCLUDES variable. See How do I add files to the project so that auto-discovery finds them?

How do I specify a set of build tools?

The Makefile by default uses GCC, which comes packaged with the ModusToolbox installer. In the Makefile, the combination of variables TOOLCHAIN and CY_COMPILER_PATH are used to specify the build tools you want to use.

The other supported toolchains include the ARM Compiler and the IAR compiler, which must be installed separately.

The options for the TOOLCHAIN variable include:

  • TOOLCHAIN=GCC_ARM (Uses GCC provided with the Eclipse IDE)

  • TOOLCHAIN=ARM (Uses ARM Compiler)

  • TOOLCHAIN=IAR (Uses IAR Compiler)

    Based on the compiler chosen, specify the absolute path to the compiler’s bin directory using the CY_COMPILER_PATH variable.

    CY_COMPILER_PATH=”C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.4/arm” CY_COMPILER_PATH=”C:/Keil_v5/ARM/ARMCLANG”

How do I tell the build system where custom build tools are?

To use a custom toolchain that is not directly supported by ModusToolbox, follow these steps:

  1. In your project directory, navigate to mtb_sharedrecipe-make-<category>release-v1.x.xmaketoolchains.


    These files do not exist in the original code example folder. They are added to the project by the build system when you create the project. The <category> values are described in the ModusToolbox™ user guide.

  2. Create a new file <NEW_TOOLCHAIN>.mk and add the toolchain configuration.

  3. In the BSP directory, navigate to TARGET_<BSP>COMPONENT_<CPU> and create a directory named TOOLCHAIN_<NEW_TOOLCHAIN>. Add the custom linker script inside this directory. Note that the prefix TOOLCHAIN_ is important.

  4. Add the custom startup file inside the same directory.

  5. Follow the steps mentioned in How do I specify a set of build tools? to add the toolchain and the compiler path. Make sure the value you provide for TOOLCHAIN is same as the name of the .mk file you created in the Step 2.

  6. Build the application.

ModusToolbox™ BSPs include startup and linker files for supported toolchains. If your toolchain requires different files, you need to provide them.

How do I pass compiler flags?

Use the CFLAGS and CXXFLAGS variables to add additional C and C++ compiler flags respectively. Refer to the respective toolchain documentation for various options.

Example: For the GNU ARM Toolchain, the various options for the compiler can be found here. They can be added as follows:

CFLAGS=-Wall -O2


The value of each variable is a space-separated list of flags supported by the compiler.

To view the changes taking effect, set the variable VERBOSE to ‘1’ in the Makefile. This displays the full command-line messages when building.

Precisely where the compiler flags appear depends upon the toolchain or IDE in use.

Similarly, when using the command line, you can specify make build VERBOSE=1 to display the full command-line messages when building.

How do I create a custom build configuration?

By default, ModusToolbox provides Debug and Release build configurations for different toolchains. They are defined in the respective <TOOLCHAIN>.mk file in libspsoc6makemaketoolchains in the project folder. To create your own build configuration, set the CONFIG variable to a value. For example:


The build system also uses the value in the CONFIG variable to generate the name of the output directory inside the project folder on this path: build<BSP>.

Do not set this variable to a null or empty value.

How do I pass linker flags?

Use the LDFLAGS variable to add custom linker flags. Refer to the respective toolchain documentation for various options. Example: For the GNU ARM Toolchain, the various options for the linker can be found here.


The values must be space-separated.

How do I use a custom linker script?

The build infrastructure automatically uses default linker scripts. Default linker scripts are provided in the board support package for all supported toolchains (Arm, GCC, and IAR).

To use a custom linker script, specify the file in the LINKER_SCRIPT variable. The value must be a relative path from the Makefile to the linker script.


The script must be compatible with your toolchain (.sct, .ld, .icf).

How do I specify a pre-build or post-build task?

Refer to the section “Pre-builds and Post-builds” in the ModusToolbox™ user guide.

How do I build a static library?

The build system supports creating either an executable or a library. If the project builds an executable, it has the APPNAME variable set, and the LIBNAME variable is empty.

To build a library file, ensure that the APPNAME variable is empty, and specify the library name in LIBNAME.

What is a COMPONENT?

A COMPONENT is a folder that contains a collection of files. Typically, a component consists of files that implement some feature or functionality in an application. For example, in a typical BSP, the hardware design is encapsulated in a folder named COMPONENT_BSP_DESIGN_MODUS. It contains the design.modus file and may contain other hardware configuration files associated with the BSP.

You can add or disable components.

How do I create a custom COMPONENT and add it to the application?

Create a folder named COMPONENT_<MYNAME>. It can be created in any location found by auto-discovery. Put the files for that component in the folder. Note that the folder must have the prefix COMPONENT_.

You then add the component to your application using COMPONENTS+=<NAME>. Note that the folder prefix is not used. For example, if you created a folder named COMPONENT_MY_COMPONENT, to add that component to the application you would do this in the Makefile:


How do I disable a COMPONENT?

Use DISABLE_COMPONENTS+=<NAME> to disable a component. For example:


How do I override the default design.modus file in a BSP?

You may wish to have a custom hardware configuration for your project. The design.modus file is part of the default COMPONENT_BSP_DESIGN_MODUS component. To do this, you disable the default component and add a custom component.

# Disable default component


# Add my custom component


Detailed information about how to do this is in the “Overriding the BSP Configuration Files” section of the ModusToolbox™ user guide.

How do I create my own BSP?

You need a custom BSP when your project does not use one of our kits.

Detailed information about how to do this is in the ModusToolbox™ creating a custom BSP document.

How do I use a custom BSP for my application?

You are likely to create a project for hardware that is not one of our kits. You use a custom BSP to support your board. The custom BSP is in a folder named TARGET_<BSP_NAME>. In the Makefile, you set the value of the TARGET make variable to match your custom BSP.

For example, if your BSP is named “MyBoard”, the contents of the BSP must be in a folder named TARGET_MyBoard, and your Makefile looks like this:

# Target board/hardware


When you execute make getlibs, your BSP files appear in a folder named TARGET_MyBoard inside your project.