Using CMake Command for Unix Commands: The Modern Way


What is FindUnixCommands?

  • These commands could include utilities like bash, cp, mv, rm, etc.
  • It's a deprecated CMake module (since version 3.26) that used to locate common Unix commands on the system.

How it Worked

  • Your CMake code could then use these variables to invoke the commands during the build process.
  • If found, it would set CMake variables indicating their paths.
  • The module searched for the existence of these commands in standard locations.

Why is it Deprecated?

  • This method allows you to directly execute Unix commands within your CMake scripts without relying on a separate module.
  • The primary reason for deprecation is the introduction of a more flexible and recommended approach: using ${CMAKE_COMMAND} -E subcommands.

Recommended Approach: Using ${CMAKE_COMMAND} -E subcommands

  • This method provides more control and avoids the need for an external module.
if(NOT EXISTS "${CMAKE_COMMAND} -E TYPE bash")
  message(WARNING "bash command not found")
endif()
  • If bash is present, the code proceeds normally. Otherwise, a warning message is displayed.
  • You can use various subcommands with -E for different tasks, such as checking file existence, creating directories, etc.
  • The -E flag tells CMake to execute an external command.
  • The ${CMAKE_COMMAND} variable stores the path to the CMake executable itself.


Checking for Common Unix Commands

# Check for the existence of 'cp' (copy) command
if(NOT EXISTS "${CMAKE_COMMAND} -E TYPE cp")
  message(WARNING "cp command not found")
endif()

# Check for the existence of 'mv' (move) command
if(NOT EXISTS "${CMAKE_COMMAND} -E TYPE mv")
  message(WARNING "mv command not found")
endif()

Creating a Directory

# Create a directory named 'build' if it doesn't exist
if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/build")
  ${CMAKE_COMMAND} -E  mkdir build
endif()
# Check if a file named 'config.h' exists
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/config.h")
  message(FATAL_ERROR "config.h not found")
endif()


Using execute_process Command

  • It provides options for capturing output, setting working directories, and specifying environment variables.
  • The execute_process command in CMake allows you to execute external commands with more control over the execution environment.
execute_process(
  COMMAND ${CMAKE_COMMAND} -E TYPE bash
  OUTPUT_VARIABLE bash_exists
  OUTPUT_STRIP_TRAILING_WHITESPACE
  RESULT_VARIABLE bash_result
)

if(NOT bash_result EQUAL 0)
  message(WARNING "bash command not found")
endif()

Custom Modules

  • This approach offers more flexibility but requires writing and maintaining the module yourself.
  • If you have specific requirements beyond the capabilities of ${CMAKE_COMMAND} -E subcommands or execute_process, you can create your own custom CMake module.
  • Custom modules are a last resort for very specific needs that aren't met by the built-in options.
  • If you need to capture command output, set environment variables, or have more complex execution requirements, consider execute_process.
  • For most scenarios, using ${CMAKE_COMMAND} -E subcommands is the simplest and recommended approach.