Common Syntax of CMake (Mathematical Calculations)

Previous Highlights:CMake Hello, WorldCMake VariablesCMake Official Tutorial (Basic Project Setup)CMake Official Tutorial (Library Creation)CMake Official Tutorial (Usage Requirements)CMake Official Tutorial (Installation and Testing)CMake Common Syntax (if Statements)CMake Common Syntax (Cache Variables)CMake Common Syntax (Environment Variables)

The math command in CMake is primarily used to perform simple integer mathematical operations during the build configuration phase, making it particularly useful in scenarios where dynamic value calculations and variable assignments are required.

The command syntax is as follows:

math(EXPR <variable> "<expression>" [OUTPUT_FORMAT <format>])
  • • variable: Stores the result of the expression calculation
  • • expression: The expression, which must be enclosed in double quotes, supports C-style operators (<span>+</span>, <span>-</span>, <span>*</span>, <span>/</span>, <span>%</span>, <span>|</span>, <span>&</span>, <span>^</span>, <span>~</span>, <span><<</span>, <span>>></span>, and parentheses <span>(...)</span>)
  • • OUTPUT_FORMAT (optional): Controls the output format, can be HEXADECIMAL or DECIMAL (default)

The math command has the following limitations:

  1. 1. Integer-only operations: Floating-point numbers are not supported (e.g., <span>3/2=1</span>)
  2. 2. Value range limitations: The result must be a 64-bit signed integer (range: <span>-2^63</span> to <span>2^63-1</span>)
  3. 3. Complex expressions: Nested operations must use parentheses to clarify precedence, for example <span>"((a + b) * c) >> 2"</span>

Here is a simple example:

set(expr "(3*10)+5")
math(EXPR out ${expr})
message("${expr}=${out}")
math(EXPR out ${expr} OUTPUT_FORMAT HEXADECIMAL)
message("${expr}=${out}")

The output will be:

(3*10)+5=35
(3*10)+5=0x23

Typical application scenarios are as follows:

Dynamic Version Number Generation

Combining the various parts of the version number (major, minor, patch) into a single value for embedding in code or filenames:

set(MAJOR 2)
set(MINOR 5)
set(PATCH 3)
math(EXPR VERSION_CODE "${MAJOR} * 10000 + ${MINOR} * 100 + ${PATCH}")
message("Version Code: ${VERSION_CODE}")  # Outputs 20503

Path or File Offset Calculations

Calculating offsets in file paths, memory alignment, and other scenarios requiring integer operations:

# Calculate the address after memory alignment
set(BASE_ADDR 0x1000)
set(OFFSET 256)
math(EXPR ALIGNED_ADDR "${BASE_ADDR} + (${OFFSET} - ${BASE_ADDR} % ${OFFSET})")
message("Aligned Address: 0x${ALIGNED_ADDR}")

Numeric Configuration of Conditional Compilation Options

Dynamic calculation of macro definitions based on platform or compilation mode:

if(WIN32)
    set(PLATFORM_FLAG 0x1)
else()
    set(PLATFORM_FLAG 0x2)
endif()
math(EXPR CONFIG_FLAGS "0x8000 | ${PLATFORM_FLAG}" OUTPUT_FORMAT HEXADECIMAL)
add_definitions(-DCONFIG_FLAGS=${CONFIG_FLAG})  # Use CONFIG_FLAGS macro in code

Bit Width Calculation for Platform Adaptation

if(CMAKE_SIZEOF_VOID_P EQUAL 8)
    set(ADDR_BITS 64)
else()
    set(ADDR_BITS 32)
endif()
math(EXPR BUFFER_SIZE "${ADDR_BITS} * 1024")  # 64-bit system sets to 65536, 32-bit sets to 32768

Leave a Comment