leponceau.org

Programming And Stuff, You Know The Thing…

CMake Cheat Sheet

Posted at — Apr 15, 2021

List Properties And Project Options

cmake --help-property-list
cmake -LA

Build Types

Restrict build types:

set(CMAKE_BUILD_TYPES "Debug;Release")

Install-Prefix-Sharing By Debug And Release Builds

-DCMAKE_DEBUG_POSTFIX=_dbg

find_package

Tracing

set(CMAKE_FIND_DEBUG_MODE TRUE)
find_package(tinyobjloader PATHS "D:/cmi" NO_DEFAULT_PATH REQUIRED)
set(CMAKE_FIND_DEBUG_MODE FALSE)

Notes

IDE Integration

Debugger Configuration

set_target_properties(targetName
    PROPERTIES
        # start some executable, for example if you are developing a library:
        VS_DEBUGGER_COMMAND "C:/some/exe/to/launch.exe"
        # run the debugger in a specific directory, eg. to find assets:
        VS_DEBUGGER_WORKING_DIRECTORY "C:/some/directory"
)

Clean Up Your Workspace

source_group("Resources/Other" REGULAR_EXPRESSION "(\.rc|CMakeLists.txt)$")

Build Customization

Hint: add_dependency() is just an ordering constraint for top level targets. It does not trigger any builds or compilation. We are stuck with add_custom_command() for the purpose of adding external compiler/processing/translation support. In MSVC you can either declare a custom build command per file, or you can customize your entire build. In CMake you define each source file individually, so the in-between option is to define a macro that makes that process more concise:

# usage:
#
#   add_vulkan_sdk()
#   add_executable(my.exe my.c my.h)
#   add_shaders(TARGET my.exe SOURCES shader.frag shader.vert ...)
#
# To run your debugger where the compiled shaders are:
#   set_target_properties(my.exe
#       PROPERTIES
#           VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
#   )
#
macro(add_shaders)
    cmake_parse_arguments("MY" "" "TARGET" "SOURCES" ${ARGN})

    source_group("Shaders" REGULAR_EXPRESSION "\.(vert|frag)$")
    # 'hide' the compiled shader files
    source_group("Shaders/Compiled" REGULAR_EXPRESSION "\.spv$")

    foreach(src ${MY_SOURCES})
        set(OUTF "${CMAKE_CURRENT_BINARY_DIR}/shaders/${src}.spv")
        get_filename_component(PARENT_DIR "${OUTF}" DIRECTORY)
        add_custom_command(
            OUTPUT "${OUTF}"
            COMMAND ${CMAKE_COMMAND} -E make_directory "${PARENT_DIR}"
            COMMAND "${shaderCompiler}" "${CMAKE_CURRENT_SOURCE_DIR}/${src}" -o "${OUTF}"
            DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${src}"
            VERBATIM
        )
        # src in order to get listed in the IDE, OUTF to declare the build relationship
        target_sources("${MY_TARGET}" PRIVATE "${src}" "${OUTF}")
    endforeach()
endmacro()

macro(add_vulkan_sdk)
    if(NOT DEFINED ENV{VULKAN_SDK})
        message(FATAL_ERROR "VULKAN_SDK env var not set")
    endif()

    set(shaderCompiler "$ENV{VULKAN_SDK}/Bin/glslc.exe")
    if(NOT EXISTS "${shaderCompiler}")
        message(FATAL_ERROR "shader compiler not found: ${shaderCompiler}")
    endif()

    include_directories("$ENV{VULKAN_SDK}/Include")
    link_directories("$ENV{VULKAN_SDK}/Lib")
endmacro()

You’ll likely need some adjustment to put the final shaders in the correct place.