Scripts vs. modules in CMake

In CMake, scripts and modules have different purposes, although they both are used to configure and build projects. Let’s break down the difference between scripts and modules in CMake:

CMake scripts

CMake offers a platform-agnostic programming language for setting up project builds with various helpful commands. This tool enables the creation of scripts that can be integrated into our project or operate independently.

We have the option to execute the script by using the -P option, i.e., cmake -P scripts.cmake. What specific requirements must the script file meet for it to be used?

They are minimal. The script’s complexity is entirely customizable and can even be an empty file. Nevertheless, it’s advisable to initiate the script with the cmake_minimum_required() command. This command informs CMake about the policies to enforce for subsequent commands within the project. Click “Run” and enter cmake -P scripts.cmake at the prompt.

# A script example.
cmake_minimum_required(VERSION 3.25.1)
message("Hello Educative")
file(WRITE Hello.txt "A file is being written")
Playground for CMake script program

CMake skips common stages like configure or build when executing a script and doesn’t utilize caching. Without distinguishing between source and build trees, variables like CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR reflect the current working directory. The equivalents for the current working directories are CMAKE_CURRENT_BINARY_DIR and CMAKE_CURRENT_SOURCE_DIR.

CMake modules

CMake projects enhance functionality by incorporating external modules, which are written in the CMake language. These modules consist of macrosMacros are a way to define reusable pieces of code., variables, and commands for diverse functions, ranging from complex tasks to simpler scripts like AddFileDependencies or TestBigEndian.

The CMake distribution includes around 90 utility modules, and additional content can be obtained from the internet through the curated list or by creating custom modules.

To utilize utility modules, use the include(<MODULE>) command. An example project demonstrates this by executing the cmake -B buildtree command in the terminal.

cmake_minimum_required(VERSION 3.25.1)
project(Example)

include (TestBigEndian)
test_big_endian(IS_BIG_ENDIAN)
if(IS_BIG_ENDIAN)
 message("\n BIG_ENDIAN byte ordering is present in the data.\n")
else()
 message("\n LITTLE_ENDIAN byte ordering is present in the data.\n")
endif()
Playground for CMake modules

Explanation

  • In line 1, the script specifies the minimum version of CMake required to run.

  • In line 2, the project name “Example” is assigned to the project.

  • In line 4, TestBigEndian is included, which provides a set of macros for testing the endianness.

  • In line 5, the test_big_endian(IS_BIG_ENDIAN) macro tests the endianness of the system and sets the IS_BIG_ENDIAN variable to TRUE if the system is big endian and FALSE if it’s little endian.

  • In lines 6–10, the conditional statement checks the value of IS_BIG_ENDIAN. If the system is big endian, it executes the block inside the if statement, printing a message indicating that big endian byte ordering is present, and if the system is not big endian, it executes the block inside the else statement, printing a message indicating that little endian byte ordering is present.

We’ll explore the modules related to relevant topics. The complete list of bundled modules can be found on CMake’s official website.

Key differences

Feature

CMake Script

CMake Module

File Usage

Directly included using the include() command

Imported using the include() or find_package() commands

Scope

Defines variables and functions in the including scope

Variables and functions are encapsulated in the module scope

Global Variables

Variables are global within the including scope

Variables are private to the module, controlled via export

Namespace

No built-in namespace mechanism

Uses namespace to avoid naming conflicts

Exported Variables

Not applicable

Variables explicitly marked for export in the module

Dependency Management

Limited control over dependencies

Explicitly define dependencies using find_package()

Reusability

Less modular and reusable

Encourages modular and reusable code with encapsulation

Usage

Best for simple projects or small configurations

Ideal for complex projects, modular design, and large codebases

Note: We should consider the actual usage and best practices, as they might vary based on specific project requirements and conventions.

Conclusion

The crucial distinctions between CMake scripts and modules need to be understood by developers for projects to be efficiently configured and built. Flexibility in project setup with customizable complexity is provided by CMake scripts, functioning as platform-agnostic programming entities. They can be executed independently or integrated into projects, with minimal requirements and the option to initiate them using the -P option. On the other hand, project functionality is enhanced by CMake modules, which incorporate external components written in the CMake language. These modules, comprising macros, variables, and commands, extend project capabilities, allowing utility modules from the CMake distribution to be leveraged or custom ones to be created. Empowering developers to recognize when to use scripts for standalone configurations and modules for extended functionalities is enabled, allowing the full potential of CMake to be harnessed in their projects.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved