3.7.4. Scripts

CMake can be used as a cross-platform scripting language.

CMake documentation

3.7.4.1. Example

Script for creating a file:

# create-file.cmake

file(WRITE Hello.txt "Created by script")

Run the script by cmake -P:

[cmake-sources]> rm -f Hello.txt
[cmake-sources]> cmake -P script/create-file.cmake
[cmake-sources]> ls Hello.txt
Hello.txt
[cmake-sources]> cat Hello.txt
Created by script

3.7.4.2. Minimum required (bad)

We should use cmake_minimum_required as the first command in a script just like with the regular CMakeLists.txt. Lack of cmake_minimum_required may lead to problems:

# script.cmake

set("Jane Doe" "")
set(MYNAME "Jane Doe")

message("MYNAME: ${MYNAME}")

if("${MYNAME}" STREQUAL "")
  message("MYNAME is empty!")
endif()
[cmake-sources]> cmake -P minimum-required-bad/script.cmake
MYNAME: Jane Doe
CMake Warning (dev) at minimum-required-bad/script.cmake:6 (if):
  Policy CMP0054 is not set: Only interpret if() arguments as variables or
  keywords when unquoted.  Run "cmake --help-policy CMP0054" for policy
  details.  Use the cmake_policy command to set the policy and suppress this
  warning.

  Quoted variables like "Jane Doe" will no longer be dereferenced when the
  policy is set to NEW.  Since the policy is not set the OLD behavior will be
  used.
This warning is for project developers.  Use -Wno-dev to suppress it.

MYNAME is empty!

3.7.4.3. Minimum required (good)

Same example with cmake_minimum_required works correctly and without warning:

# script.cmake

cmake_minimum_required(VERSION 3.1)

set("Jane Doe" "")
set(MYNAME "Jane Doe")

message("MYNAME: ${MYNAME}")

if("${MYNAME}" STREQUAL "")
  message("MYNAME is empty!")
endif()
[cmake-sources]> cmake -P minimum-required-good/script.cmake
MYNAME: Jane Doe

3.7.4.4. cmake -E

Example of using cmake -E remove_directory instead of native rm/rmdir commands:

CMake documentation

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

set(dir_to_remove "${CMAKE_CURRENT_BINARY_DIR}/__temp")

if(WIN32)
  # 'rmdir' will exit with error if directory doesn't exist
  # so we have to put 'if' here
  if(EXISTS "${dir_to_remove}")
    # need to convert to windows-style path
    file(TO_NATIVE_PATH "${dir_to_remove}" native_path)
    execute_process(
        COMMAND cmd /c rmdir "${native_path}" /S /Q
        RESULT_VARIABLE result
    )
  endif()
else()
  # no need to put 'if', 'rm -rf' produce no error if directory doesn't exist
  execute_process(
      COMMAND rm -rf "${dir_to_remove}"
      RESULT_VARIABLE result
  )
endif()

if(NOT result EQUAL 0)
  # Error
endif()

Same code with cmake -E:

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

execute_process(
    COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/__temp"
    RESULT_VARIABLE result
)

if(NOT result EQUAL 0)
  # Error
endif()

Note

It’s easier to use file(REMOVE_RECURSE ...) in this particular example