1# 2# Arm SCP/MCP Software 3# Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved. 4# 5# SPDX-License-Identifier: BSD-3-Clause 6# 7 8# cmake-lint: disable=C0301 9 10cmake_minimum_required(VERSION 3.18.3) 11 12list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 13 14# 15# Individual firmware targets are configured based on the 'Firmware.cmake' 16# living in the firmware source directory that the user provides to us, which 17# determines the default set of configuration options we are given, including 18# the toolchain file. 19# 20 21if(SCP_FIRMWARE_SOURCE_DIR) 22 get_filename_component(SCP_FIRMWARE_SOURCE_DIR "${SCP_FIRMWARE_SOURCE_DIR}" 23 ABSOLUTE BASE_DIR "${CMAKE_SOURCE_DIR}/product") 24 25 include("${SCP_FIRMWARE_SOURCE_DIR}/Firmware.cmake") 26 27 if((NOT SCP_FIRMWARE) OR (NOT SCP_FIRMWARE_TARGET)) 28 # cmake-format: off 29 message(FATAL_ERROR 30 "Insufficient firmware metadata provided.\n" 31 32 "Please ensure your 'Firmware.cmake' has set both `SCP_FIRMWARE` " 33 "and `SCP_FIRMWARE_TARGET` to the name of your firmware and the " 34 "firmware's CMake target respectively.") 35 # cmake-format: on 36 endif() 37 38 if(NOT SCP_FIRMWARE_BINARY_DIR) 39 # 40 # Derive the binary directory from the location of the source directory 41 # if it's in-tree. 42 # 43 44 file(RELATIVE_PATH SCP_FIRMWARE_BINARY_DIR "${CMAKE_SOURCE_DIR}" 45 "${SCP_FIRMWARE_SOURCE_DIR}") 46 endif() 47 48 if(SCP_FIRMWARE_BINARY_DIR MATCHES "\\.\\.") 49 # cmake-format: off 50 message(FATAL_ERROR 51 "Invalid firmware binary directory.\n" 52 53 "Please ensure your firmware binary directory is a relative path. " 54 "This path is used as the location within the project binary " 55 "directory that will be used for firmware artifacts.") 56 # cmake-format: on 57 endif() 58endif() 59 60# 61# Handle automatic selection of the toolchain. This only occurs if the user has 62# not explicitly provided the path to a toolchain file and the firmware has 63# given us a default preference. 64# 65 66if(SCP_TOOLCHAIN_INIT AND (NOT CMAKE_TOOLCHAIN_FILE)) 67 # 68 # Let the firmware decide what its default toolchain should be, but allow 69 # the user to override it. 70 # 71 72 if(NOT SCP_TOOLCHAIN) 73 set(SCP_TOOLCHAIN "${SCP_TOOLCHAIN_INIT}") 74 endif() 75 76 set(CMAKE_TOOLCHAIN_FILE 77 "${SCP_FIRMWARE_SOURCE_DIR}/Toolchain-${SCP_TOOLCHAIN}.cmake") 78endif() 79 80if(SCP_TOOLCHAIN STREQUAL "Clang" AND NOT SCP_LLVM_SYSROOT_CC) 81 message( 82 FATAL_ERROR 83 "When Clang is set as toolchain SCP_LLVM_SYSROOT_CC must be defined" 84 ) 85endif() 86 87project( 88 SCP 89 VERSION 2.15.0 90 DESCRIPTION "Arm SCP/MCP Software" 91 HOMEPAGE_URL 92 "https://developer.arm.com/tools-and-software/open-source-software/firmware/scp-firmware" 93 LANGUAGES C ASM) 94 95# 96# Configure the default build type to be "Release". We choose to default to a 97# release build as non-developer consumers will generally want a release build, 98# whereas developers who need a debug build are generally familiar with how to 99# enable it in the build system. 100# 101 102if((NOT CMAKE_BUILD_TYPE) AND (NOT CMAKE_CONFIGURATION_TYPES)) 103 set(CMAKE_BUILD_TYPE 104 "Release" 105 CACHE STRING "Build type." FORCE) 106 107 set_property( 108 CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" 109 "RelWithDebInfo") 110endif() 111 112# 113# Set the default C standard to C11 plus any compiler extensions. 114# 115 116set(CMAKE_C_STANDARD 11) 117set(CMAKE_C_STANDARD_REQUIRED TRUE) 118set(CMAKE_C_EXTENSIONS TRUE) 119 120# 121# We use `__declspec` when available, but Clang needs to explicitly enable 122# support for it before we can use them. 123# 124 125if(CMAKE_C_COMPILER_ID STREQUAL "Clang") 126 string(APPEND CMAKE_C_FLAGS " -fms-extensions") 127endif() 128 129# 130# Enable inter-procedural optimization for all targets if we can. 131# `CheckIPOSupported` doesn't play particularly nicely with toolchains that 132# cannot build executables right off the bat, so we skip this check if we're 133# cross compiling. 134# 135 136include(CheckIPOSupported) 137include(CMakeDependentOption) 138 139check_ipo_supported(RESULT SCP_IPO_SUPPORTED) 140 141cmake_dependent_option( 142 SCP_ENABLE_IPO 143 "Enable the interprocedural optimization (IPO) if supported?" 144 "${SCP_ENABLE_IPO_INIT}" "DEFINED SCP_ENABLE_IPO_INIT" "${SCP_ENABLE_IPO}") 145 146if(CMAKE_CROSSCOMPILING 147 AND (CMAKE_C_COMPILER_ID STREQUAL "GNU") 148 AND SCP_ENABLE_IPO) 149 set(SCP_IPO_SUPPORTED TRUE) 150endif() 151 152cmake_dependent_option( 153 CMAKE_INTERPROCEDURAL_OPTIMIZATION "Enable interprocedural optimization?" 154 TRUE "SCP_IPO_SUPPORTED;SCP_ENABLE_IPO" FALSE) 155 156# 157# Export a `compile_commands.json` file for generators that support it. 158# 159 160set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) 161 162# 163# Set up Cppcheck if it's available and enabled. 164# 165if(NOT DISABLE_CPPCHECK) 166 find_program(CMAKE_C_CPPCHECK NAMES "cppcheck") 167 168 if(NOT CMAKE_C_CPPCHECK) 169 unset(CMAKE_C_CPPCHECK CACHE) 170 endif() 171 172 if(CMAKE_C_CPPCHECK) 173 # Prepend cppcheck_wrapper.py before binary to perform pre and post 174 # cppcheck operations. 175 set(CPPCHECK_WRAPPER ${CMAKE_SOURCE_DIR}/tools/cppcheck_wrapper.py) 176 # cmake-format: off 177 178 list(PREPEND CMAKE_C_CPPCHECK ${CPPCHECK_WRAPPER}) 179 list(APPEND CMAKE_C_CPPCHECK "--quiet") 180 list(APPEND CMAKE_C_CPPCHECK "--suppressions-list=${CMAKE_CURRENT_SOURCE_DIR}/tools/config/cppcheck/cppcheck_suppress_list.txt") 181 list(APPEND CMAKE_C_CPPCHECK "--enable=all") 182 list(APPEND CMAKE_C_CPPCHECK "--error-exitcode=1") 183 184 if(SCP_ARCHITECTURE STREQUAL "arm-m") 185 if(CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m(33|55|85)") 186 list(APPEND CMAKE_C_CPPCHECK "--library=${CMAKE_CURRENT_SOURCE_DIR}/tools/config/cppcheck/.armv8m.cppcheck.cfg") 187 elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m(3|7)") 188 list(APPEND CMAKE_C_CPPCHECK "--library=${CMAKE_CURRENT_SOURCE_DIR}/tools/config/cppcheck/.armv7m.cppcheck.cfg") 189 endif() 190 endif() 191 192 if(CMAKE_C_COMPILER_ID STREQUAL "ARMClang") 193 list(APPEND CMAKE_C_CPPCHECK "--library=${CMAKE_CURRENT_SOURCE_DIR}/tools/config/cppcheck/.armclang.cppcheck.cfg") 194 else() 195 list(APPEND CMAKE_C_CPPCHECK "--library=${CMAKE_CURRENT_SOURCE_DIR}/tools/config/cppcheck/.gnu.cppcheck.cfg") 196 endif() 197 198 if(COMMAND_OUTPUT_VERBOSE) 199 list(APPEND CMAKE_C_CPPCHECK "verbose") 200 endif() 201 202 # cmake-format: on 203 endif() 204endif() 205 206# 207# Try to locate Arm Compiler's 'fromelf' tool. 208# 209 210if(CMAKE_C_COMPILER_ID MATCHES "ARMClang") 211 get_filename_component(base ${CMAKE_C_COMPILER} DIRECTORY) 212 213 find_program(SCP_FROMELF fromelf ${base}) 214 215 if(SCP_FROMELF) 216 mark_as_advanced(SCP_FROMELF) 217 endif() 218endif() 219 220# 221# Try to identify any standard libraries that require special treatment. 222# 223 224include(CheckSymbolExists) 225 226check_symbol_exists("__NEWLIB__" "sys/features.h" SCP_HAVE_NEWLIB) 227 228# 229# If the user asks for it, we can save them some time by creating a flat binary 230# from the firmware's compiled ELF image. 231# 232 233include(CMakeDependentOption) 234 235cmake_dependent_option( 236 SCP_GENERATE_FLAT_BINARY "Generate a flat binary (.bin) image?" 237 "${SCP_GENERATE_FLAT_BINARY_INIT}" "DEFINED SCP_GENERATE_FLAT_BINARY_INIT" 238 "${SCP_GENERATE_FLAT_BINARY}") 239 240# 241# If the firmware developer has given us initial values for these configuration 242# options, we can expose them to the user. 243# 244 245include(CMakeDependentOption) 246 247# Common build options 248 249if(SCP_ARCHITECTURE STREQUAL "optee") 250 set(SCP_ENABLE_SUB_SYSTEM_MODE_INIT TRUE) 251endif() 252 253set(SCP_ENABLE_OVERRIDE_FIRMWARE_NAME 254 ${SCP_ENABLE_OVERRIDE_FIRMWARE_NAME_INIT} 255 CACHE STRING "Override firmware binary name") 256 257cmake_dependent_option( 258 SCP_ENABLE_SUB_SYSTEM_MODE "Enable the execution as a sub-system?" 259 "${SCP_ENABLE_SUB_SYSTEM_MODE_INIT}" 260 "DEFINED SCP_ENABLE_SUB_SYSTEM_MODE_INIT" 261 "${SCP_ENABLE_SUB_SYSTEM_MODE}") 262 263cmake_dependent_option( 264 SCP_ENABLE_NOTIFICATIONS "Enable the notification subsystem?" 265 "${SCP_ENABLE_NOTIFICATIONS_INIT}" "DEFINED SCP_ENABLE_NOTIFICATIONS_INIT" 266 "${SCP_ENABLE_NOTIFICATIONS}") 267 268cmake_dependent_option( 269 SCP_ENABLE_OUTBAND_MSG_SUPPORT 270 "Enable Transport Out Band Message Support?" 271 "${SCP_ENABLE_OUTBAND_MSG_SUPPORT_INIT}" 272 "DEFINED SCP_ENABLE_OUTBAND_MSG_SUPPORT_INIT" 273 "${SCP_ENABLE_OUTBAND_MSG_SUPPORT}") 274 275cmake_dependent_option( 276 SCP_ENABLE_RESOURCE_PERMISSIONS 277 "Enable the resource permission support?" 278 "${SCP_ENABLE_RESOURCE_PERMISSIONS_INIT}" 279 "DEFINED SCP_ENABLE_RESOURCE_PERMISSIONS_INIT" 280 "${SCP_ENABLE_RESOURCE_PERMISSIONS}") 281 282cmake_dependent_option( 283 SCP_ENABLE_SCMI_NOTIFICATIONS 284 "Enable the SCMI notifications?" 285 "${SCP_ENABLE_SCMI_NOTIFICATIONS_INIT}" 286 "DEFINED SCP_ENABLE_SCMI_NOTIFICATIONS_INIT" 287 "${SCP_ENABLE_SCMI_NOTIFICATIONS}") 288 289cmake_dependent_option( 290 SCP_ENABLE_SCMI_SENSOR_EVENTS 291 "Enable the SCMI sensor events?" 292 "${SCP_ENABLE_SCMI_SENSOR_EVENTS_INIT}" 293 "DEFINED SCP_ENABLE_SCMI_SENSOR_EVENTS_INIT" 294 "${SCP_ENABLE_SCMI_SENSOR_EVENTS}") 295 296cmake_dependent_option( 297 SCP_ENABLE_FAST_CHANNELS 298 "Enable the transport Fast Channels?" 299 "${SCP_ENABLE_FAST_CHANNELS_INIT}" 300 "DEFINED SCP_ENABLE_FAST_CHANNELS_INIT" 301 "${SCP_ENABLE_FAST_CHANNELS}") 302 303# Include firmware specific build options 304include("${SCP_FIRMWARE_SOURCE_DIR}/Buildoptions.cmake" OPTIONAL) 305 306# 307# Wrap `add_executable` in a way that allows us to do some extra processing on 308# the firmware target.(e.g. flat binary generation) This is necessary almost 309# exclusively because `add_custom_command` cannot be used with a target created 310# in a different directory. 311# 312 313# cmake-lint: disable=C0103,C0111 314 315macro(add_executable target) 316 _add_executable(${target} ${ARGN}) 317 318 if("${target}" STREQUAL "${SCP_FIRMWARE_TARGET}") 319 if(SCP_GENERATE_FLAT_BINARY) 320 # 321 # Invoke 'objcopy' or 'fromelf', which we use to generate a flat 322 # binary for the generated firmware image. We make this optional 323 # because some binaries consist of disjoint sections far apart from 324 # one another, which can generate huge binaries. 325 # 326 327 if(SCP_FROMELF) 328 # cmake-format: off 329 add_custom_command( 330 TARGET ${target} POST_BUILD 331 COMMAND ${SCP_FROMELF} 332 ARGS 333 --bin "$<TARGET_FILE:${target}>" 334 --output "$<TARGET_FILE_DIR:${target}>/$<TARGET_PROPERTY:${target},OUTPUT_NAME>.bin" 335 COMMENT "Generating flat binary ${target}.bin") 336 # cmake-format: on 337 elseif(CMAKE_OBJCOPY) 338 # cmake-format: off 339 add_custom_command( 340 TARGET ${target} POST_BUILD 341 COMMAND ${CMAKE_OBJCOPY} 342 ARGS -O binary 343 "$<TARGET_FILE:${target}>" 344 "$<TARGET_FILE_DIR:${target}>/$<TARGET_FILE_BASE_NAME:${target}>.bin" 345 COMMENT "Generating flat binary ${target}.bin") 346 # cmake-format: on 347 endif() 348 endif() 349 endif() 350endmacro() 351 352if(SCP_FIRMWARE) 353 # 354 # Pull in the CMSIS package. 355 # 356 357 add_subdirectory("contrib/cmsis" EXCLUDE_FROM_ALL) 358 359 # 360 # Load in the firmware. We do this now so that the firmware list files can 361 # make adjustments to any modules it wishes to load in, configure the 362 # architecture library, etc. 363 # 364 365 add_subdirectory("${SCP_FIRMWARE_SOURCE_DIR}" "${SCP_FIRMWARE_BINARY_DIR}" 366 EXCLUDE_FROM_ALL) 367 368 # 369 # Generate a map file for the firmware. 370 # 371 372 if(CMAKE_C_COMPILER_ID STREQUAL "ARMClang") 373 target_link_options( 374 ${SCP_FIRMWARE_TARGET} 375 PRIVATE "LINKER:--map" 376 "LINKER:--list=$<TARGET_FILE_DIR:${SCP_FIRMWARE_TARGET}>/$<TARGET_FILE_BASE_NAME:${SCP_FIRMWARE_TARGET}>.map") 377 else() 378 target_link_options( 379 ${SCP_FIRMWARE_TARGET} 380 PRIVATE "LINKER:--cref" 381 "LINKER:-Map=$<TARGET_FILE_DIR:${SCP_FIRMWARE_TARGET}>/$<TARGET_FILE_BASE_NAME:${SCP_FIRMWARE_TARGET}>.map") 382 endif() 383 384 # 385 # Make the firmware target a part of the 'all' pseudo-target and give it a 386 # fixed output binary name so that different toolchains don't generate 387 # different names (which is desirable especially for higher-level build 388 # systems). 389 # 390 391 if("${SCP_ENABLE_OVERRIDE_FIRMWARE_NAME}" STREQUAL "") 392 set(SCP_FIRMWARE_NAME ${SCP_FIRMWARE_TARGET}) 393 else() 394 set(SCP_FIRMWARE_NAME ${SCP_ENABLE_OVERRIDE_FIRMWARE_NAME}) 395 endif() 396 397 set_target_properties( 398 ${SCP_FIRMWARE_TARGET} 399 PROPERTIES EXCLUDE_FROM_ALL FALSE 400 OUTPUT_NAME "${SCP_FIRMWARE_NAME}" 401 RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") 402 403 set_target_properties( 404 ${SCP_FIRMWARE_TARGET} 405 PROPERTIES EXCLUDE_FROM_ALL FALSE 406 SUFFIX ".elf") 407 # 408 # Load in the CLI debugger if it was requested. 409 # 410 411 cmake_dependent_option( 412 SCP_ENABLE_DEBUGGER "Enable the debugger-cli subsystem?" 413 "${SCP_ENABLE_DEBUGGER_INIT}" "DEFINED SCP_ENABLE_DEBUGGER_INIT" 414 "${SCP_ENABLE_DEBUGGER}") 415 416 if(SCP_ENABLE_DEBUGGER) 417 add_subdirectory("debugger" EXCLUDE_FROM_ALL) 418 endif() 419 420 # 421 # Load in the architecture support library. 422 # 423 424 add_subdirectory("arch" EXCLUDE_FROM_ALL) 425 426 # 427 # Load in the modules specified, plus any that need to be included to 428 # support other modules. 429 # 430 431 add_subdirectory("module" EXCLUDE_FROM_ALL) 432 433 # 434 # Load in the framework. This should be the last of the targets we need. 435 # 436 437 add_subdirectory("framework" EXCLUDE_FROM_ALL) 438 439 # 440 # Collect up all the source files used to build the various targets created 441 # above. 442 # 443 444 # cmake-format: off 445 446 string(APPEND scp_sources "$<TARGET_PROPERTY:framework,INTERFACE_SOURCES>$<SEMICOLON>") 447 string(APPEND scp_sources "$<TARGET_PROPERTY:framework,SOURCES>$<SEMICOLON>") 448 string(APPEND scp_sources "$<TARGET_PROPERTY:${SCP_ARCHITECTURE_TARGET},INTERFACE_SOURCES>$<SEMICOLON>") 449 string(APPEND scp_sources "$<TARGET_PROPERTY:${SCP_ARCHITECTURE_TARGET},SOURCES>$<SEMICOLON>") 450 string(APPEND scp_sources "$<TARGET_PROPERTY:${SCP_FIRMWARE_TARGET},INTERFACE_SOURCES>$<SEMICOLON>") 451 string(APPEND scp_sources "$<TARGET_PROPERTY:${SCP_FIRMWARE_TARGET},SOURCES>$<SEMICOLON>") 452 453 string(APPEND scp_includes "$<TARGET_PROPERTY:framework,INTERFACE_INCLUDE_DIRECTORIES>$<SEMICOLON>") 454 string(APPEND scp_includes "$<TARGET_PROPERTY:framework,INCLUDE_DIRECTORIES>$<SEMICOLON>") 455 string(APPEND scp_includes "$<TARGET_PROPERTY:${SCP_ARCHITECTURE_TARGET},INTERFACE_INCLUDE_DIRECTORIES>$<SEMICOLON>") 456 string(APPEND scp_includes "$<TARGET_PROPERTY:${SCP_ARCHITECTURE_TARGET},INCLUDE_DIRECTORIES>$<SEMICOLON>") 457 string(APPEND scp_includes "$<TARGET_PROPERTY:${SCP_FIRMWARE_TARGET},INTERFACE_INCLUDE_DIRECTORIES>$<SEMICOLON>") 458 string(APPEND scp_includes "$<TARGET_PROPERTY:${SCP_FIRMWARE_TARGET},INCLUDE_DIRECTORIES>$<SEMICOLON>") 459 460 string(APPEND scp_defines "$<TARGET_PROPERTY:framework,INTERFACE_COMPILE_DEFINITIONS>$<SEMICOLON>") 461 string(APPEND scp_defines "$<TARGET_PROPERTY:framework,COMPILE_DEFINITIONS>$<SEMICOLON>") 462 string(APPEND scp_defines "$<TARGET_PROPERTY:${SCP_ARCHITECTURE_TARGET},INTERFACE_COMPILE_DEFINITIONS>$<SEMICOLON>") 463 string(APPEND scp_defines "$<TARGET_PROPERTY:${SCP_ARCHITECTURE_TARGET},COMPILE_DEFINITIONS>$<SEMICOLON>" ) 464 string(APPEND scp_defines "$<TARGET_PROPERTY:${SCP_FIRMWARE_TARGET},INTERFACE_COMPILE_DEFINITIONS>$<SEMICOLON>") 465 string(APPEND scp_defines "$<TARGET_PROPERTY:${SCP_FIRMWARE_TARGET},COMPILE_DEFINITIONS>$<SEMICOLON>") 466 467 list(APPEND scp_libraries "$<TARGET_FILE:framework>") 468 list(APPEND scp_libraries "$<TARGET_FILE:${SCP_ARCHITECTURE_TARGET}>") 469 list(APPEND scp_libraries "$<TARGET_FILE:${SCP_FIRMWARE_TARGET}>") 470 471 foreach(module IN LISTS SCP_MODULE_TARGETS) 472 string(APPEND scp_sources "$<TARGET_PROPERTY:${module},INTERFACE_SOURCES>$<SEMICOLON>") 473 string(APPEND scp_sources "$<TARGET_PROPERTY:${module},SOURCES>$<SEMICOLON>") 474 475 string(APPEND scp_includes "$<TARGET_PROPERTY:${module},INTERFACE_INCLUDE_DIRECTORIES>$<SEMICOLON>") 476 string(APPEND scp_includes "$<TARGET_PROPERTY:${module},INCLUDE_DIRECTORIES>$<SEMICOLON>") 477 478 string(APPEND scp_defines "$<TARGET_PROPERTY:${module},INTERFACE_COMPILE_DEFINITIONS>$<SEMICOLON>") 479 string(APPEND scp_defines "$<TARGET_PROPERTY:${module},COMPILE_DEFINITIONS>$<SEMICOLON>") 480 481 list(APPEND scp_libraries "$<TARGET_FILE:${module}>") 482 endforeach() 483 484 set(scp_sources $<REMOVE_DUPLICATES:${scp_sources}>) 485 set(scp_includes $<REMOVE_DUPLICATES:${scp_includes}>) 486 set(scp_defines $<REMOVE_DUPLICATES:${scp_defines}>) 487 488 # cmake-format: on 489 490 # 491 # Load in the documentation generation. 492 # 493 add_subdirectory("doc" EXCLUDE_FROM_ALL) 494endif() 495 496 497set(SCP_FIRMWARE_LIB "${SCP_FIRMWARE_TARGET}-all") 498 499# merged libraries is only built when `make ${SCP_FIRMWARE_LIB}` is issued 500add_custom_target(${SCP_FIRMWARE_LIB} 501 # COMMAND/COMMENT must be upper case 502 COMMAND ${CMAKE_AR} rcT $<TARGET_FILE_DIR:${SCP_FIRMWARE_TARGET}>/lib${SCP_FIRMWARE_LIB}.a ${scp_libraries} 503 COMMENT " Merging all libraries in a single lib${SCP_FIRMWARE_LIB}.a" 504) 505 506add_dependencies(${SCP_FIRMWARE_LIB} ${SCP_FIRMWARE_TARGET}) 507 508# 509# Set up global inclusions and exclusions for source file quality assurance 510# tools. This is intended to filter in external directories (e.g. out-of-tree 511# modules) and filter out third-party directories. 512# 513 514list(APPEND glob_includes "${SCP_SOURCE_DIR}") 515 516list(APPEND glob_excludes "^${SCP_SOURCE_DIR}/contrib/cmsis/git") 517 518list(APPEND cmake_globs "CMakeLists.txt") 519list(APPEND cmake_globs "*.cmake") 520 521# 522# Glob sources and place them in their respective variables. Globs for source 523# types can be with specified with a `${type}_globs` variable, which should be a 524# list of globs to be fed into `file(GLOB_RECURSE ...)`. 525# 526 527# cmake-lint: disable=C0103 528 529foreach(type cmake) 530 unset(sources) 531 532 foreach(include IN LISTS glob_includes) 533 foreach(glob IN LISTS ${type}_globs) 534 file(GLOB_RECURSE _sources "${include}/${glob}") 535 list(APPEND sources ${_sources}) 536 endforeach() 537 endforeach() 538 539 foreach(exclude IN LISTS glob_excludes) 540 list(FILTER sources EXCLUDE REGEX "${exclude}") 541 endforeach() 542 543 set(${type}_sources ${sources}) 544endforeach() 545 546# 547# Configure cmake-format. 548# 549 550find_package(CMakeFormat OPTIONAL_COMPONENTS Format Lint) 551 552if(TARGET CMakeFormat::Format) 553 add_custom_target( 554 format-cmake 555 COMMAND CMakeFormat::Format -i "${cmake_sources}" 556 WORKING_DIRECTORY "${SCP_SOURCE_DIR}" 557 COMMENT "Formatting CMake sources..." 558 COMMAND_EXPAND_LISTS) 559 560 list(APPEND format_targets "format-cmake") 561 562 add_custom_target( 563 check-cmake 564 COMMAND CMakeFormat::Format --check "${cmake_sources}" 565 WORKING_DIRECTORY "${SCP_SOURCE_DIR}" 566 COMMENT "Checking CMake sources..." 567 COMMAND_EXPAND_LISTS) 568 569 list(APPEND check_targets "check-cmake") 570endif() 571 572if(TARGET CMakeFormat::Lint) 573 add_custom_target( 574 lint-cmake 575 COMMAND CMakeFormat::Lint --suppress-decorations "${cmake_sources}" 576 WORKING_DIRECTORY "${SCP_SOURCE_DIR}" 577 COMMENT "Linting CMake sources..." 578 COMMAND_EXPAND_LISTS) 579 580 list(APPEND lint_targets "lint-cmake") 581endif() 582 583# 584# Create the final check targets. These targets consist of miscellaneous quality 585# assurance tasks like linting and formatting, and act as dummy targets that 586# invoke the various tools we set up above. 587# 588 589add_custom_target( 590 format 591 DEPENDS ${format_targets} 592 COMMENT "Formatting all sources...") 593 594add_custom_target( 595 lint 596 DEPENDS ${lint_targets} 597 COMMENT "Linting all sources...") 598 599add_custom_target( 600 check 601 DEPENDS ${check_targets} lint 602 COMMENT "Checking lint...") 603