-
Notifications
You must be signed in to change notification settings - Fork 19
Creating a cppdep.yaml file from CMake
jsinge edited this page Jan 16, 2022
·
1 revision
In a large scale project you might not want to maintain yet another config file with all the packages and source locations. This script may be helpful to create a cppdep.yaml config file automatically for all targets in a CMake project.
First, add a cppdep-header.yaml with the static parts of the config, i.e. the external packages and name of your package group:
external:
- name: Platform
path: /
packages:
- name: Standard Libraries
pattern:
- "[a-z_]+$"
- ^std[a-z_]+.h$
- string.h
- math.h
- limits.h
- name: Thirdparties
path: /
packages:
- name: boost
pattern:
- boost\\
internal: # A list of package groups for analysis.
- name: your-project-name # The name of a package-group.
path: C:/projects/your-project-name # The root path for the packages in the group.
packages: # A list of member packages, generated by CMake.
Then, add a file cppdep.cmake to your project with these contents:
function(get_all_targets result targets_category)
set(targets)
get_all_targets_recursive(targets ${CMAKE_CURRENT_SOURCE_DIR} ${targets_category})
set(${result} ${targets} PARENT_SCOPE)
endfunction()
macro(get_all_targets_recursive result dir targets_category)
get_property(subdirectories DIRECTORY ${dir} PROPERTY SUBDIRECTORIES)
foreach(subdir ${subdirectories})
get_all_targets_recursive(${result} ${subdir} ${targets_category})
endforeach()
get_property(current_targets DIRECTORY ${dir} PROPERTY ${targets_category})
list(APPEND ${result} ${current_targets})
endmacro()
function(cppdep_get_package_yaml_section target target_type_exclusion_regex target_exclusion_regex result )
set(package_description)
get_target_property(target_source_dir ${target} SOURCE_DIR)
get_target_property(sourcefiles ${target} SOURCES)
get_target_property(target_type ${target} TYPE)
if( NOT sourcefiles
OR (target_type_exclusion_regex AND target_type MATCHES "${target_type_exclusion_regex}")
OR (target_exclusion_regex AND target MATCHES "${target_exclusion_regex}"))
set(${result} "" PARENT_SCOPE)
return()
endif()
set(package_description " - name: ${target}\n include:\n - .\n src:\n")
foreach(src ${sourcefiles})
string(APPEND package_description " - ${target_source_dir}/${src}\n")
endforeach()
set(${result} ${package_description} PARENT_SCOPE)
endfunction()
function(cppdep_create_yaml)
cmake_parse_arguments(arg "" "TARGET_TYPE_EXCLUSION_REGEX;TARGET_EXCLUSION_REGEX" "" "${ARGN}")
if(arg_UNPARSED_ARGUMENTS)
message( SEND_ERROR "Unknown arguments: ${arg_UNPARSED_ARGUMENTS}")
endif()
file(READ "${CMAKE_SOURCE_DIR}/cppdep-header.yaml" cppdep_header)
SET(cppdep_yaml_contents "${cppdep_header}\n")
get_all_targets(build_targets BUILDSYSTEM_TARGETS)
foreach(target ${build_targets})
cppdep_get_package_yaml_section(${target} "${arg_TARGET_TYPE_EXCLUSION_REGEX}" "${arg_TARGET_EXCLUSION_REGEX}" section)
string(APPEND cppdep_yaml_contents ${section})
endforeach()
file(GENERATE OUTPUT "${PROJECT_BINARY_DIR}/cppdep.yaml" CONTENT ${cppdep_yaml_contents})
endfunction()
Invoke the cppdep_create_yaml method like this at the end of the root CMakeLists.txt:
Include(cppdep.cmake)
cppdep_create_yaml()
Or if you want to exclude some of the targets by their name:
cppdep_create_yaml(TARGET_EXCLUSION_REGEX ".*Test")
Now, CMake will create a cppdep.yaml file in the builder folder during project configuration that may be used for the cppdep analysis.