diff --git a/Doxygen/main.cmake b/Doxygen/main.cmake index 73695b7..f886eb5 100644 --- a/Doxygen/main.cmake +++ b/Doxygen/main.cmake @@ -1,13 +1,17 @@ -function(ys_add_doxygen_target target_name) +function(psc_join_doxygen_list out_value) + string(REPLACE ";" " " value "${ARGN}") + set(${out_value} "${value}" PARENT_SCOPE) +endfunction() +function(psc_generate_doxygen_directory_scripts script_name) set(options) set(oneValueArgs PROJECT_NAME OUTPUT_DIR WORKING_DIRECTORY DOXYGEN_EXECUTABLE DOT_EXECUTABLE) - set(multiValueArgs INPUT EXCLUDE FILE_PATTERNS PREDEFINED) + set(multiValueArgs INPUT_DIRS EXCLUDE_DIRS FILE_PATTERNS PREDEFINED) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if (NOT ARG_PROJECT_NAME) set(ARG_PROJECT_NAME "${PROJECT_NAME}") endif () if (NOT ARG_OUTPUT_DIR) - set(ARG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doxygen/${target_name}") + set(ARG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doxygen/${script_name}") endif () if (NOT ARG_WORKING_DIRECTORY) set(ARG_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") @@ -18,23 +22,51 @@ function(ys_add_doxygen_target target_name) if (NOT ARG_DOT_EXECUTABLE) set(ARG_DOT_EXECUTABLE "C:/Program Files/Graphviz/bin/dot.exe") endif () - if (NOT ARG_INPUT) - set(ARG_INPUT "${CMAKE_SOURCE_DIR}") + if (NOT ARG_INPUT_DIRS) + set(ARG_INPUT_DIRS "${CMAKE_SOURCE_DIR}") endif () if (NOT ARG_FILE_PATTERNS) set(ARG_FILE_PATTERNS "*.h" "*.hpp" "*.hh" "*.cpp" "*.cxx" "*.cc") endif () get_filename_component(dot_dir "${ARG_DOT_EXECUTABLE}" DIRECTORY) - string(REPLACE ";" " " doxygen_input "${ARG_INPUT}") - string(REPLACE ";" " " doxygen_exclude "${ARG_EXCLUDE}") - string(REPLACE ";" " " doxygen_file_patterns "${ARG_FILE_PATTERNS}") - string(REPLACE ";" " " doxygen_predefined "${ARG_PREDEFINED}") - set(doxygen_file "${CMAKE_CURRENT_BINARY_DIR}/${target_name}.Doxyfile") + psc_join_doxygen_list(doxygen_input ${ARG_INPUT_DIRS}) + psc_join_doxygen_list(doxygen_exclude ${ARG_EXCLUDE_DIRS}) + psc_join_doxygen_list(doxygen_file_patterns ${ARG_FILE_PATTERNS}) + psc_join_doxygen_list(doxygen_predefined ${ARG_PREDEFINED}) + set(script_dir "${CMAKE_CURRENT_BINARY_DIR}/psc_doc_scripts/${script_name}") + file(MAKE_DIRECTORY "${script_dir}") + set(doxygen_file "${script_dir}/${script_name}.Doxyfile") + set(power_shell_script "${script_dir}/${script_name}_doxygen.ps1") + set(bash_script "${script_dir}/${script_name}_doxygen.sh") configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Doxyfile.in" "${doxygen_file}" @ONLY) - add_custom_target(${target_name} - COMMAND "${CMAKE_COMMAND}" -E make_directory "${ARG_OUTPUT_DIR}" - COMMAND "${ARG_DOXYGEN_EXECUTABLE}" "${doxygen_file}" - WORKING_DIRECTORY "${ARG_WORKING_DIRECTORY}" - VERBATIM - ) + file(WRITE "${power_shell_script}" "$ErrorActionPreference = 'Stop'\n$outputDir = '${ARG_OUTPUT_DIR}'\nNew-Item -ItemType Directory -Force -Path $outputDir | Out-Null\n& '${ARG_DOXYGEN_EXECUTABLE}' '${doxygen_file}'\nif ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }\nSet-Content -LiteralPath (Join-Path $outputDir 'index.html') -Encoding UTF8 -Value 'Open Doxygen HTML'\nSet-Content -LiteralPath (Join-Path $outputDir 'html_index.html') -Encoding UTF8 -Value 'Open Doxygen HTML'\nif (Test-Path -LiteralPath (Join-Path $outputDir 'xml/index.xml')) { Copy-Item -LiteralPath (Join-Path $outputDir 'xml/index.xml') -Destination (Join-Path $outputDir 'index.xml') -Force }\n") + file(WRITE "${bash_script}" "#!/usr/bin/env bash\nset -euo pipefail\noutput_dir='${ARG_OUTPUT_DIR}'\nmkdir -p \"$output_dir\"\n'${ARG_DOXYGEN_EXECUTABLE}' '${doxygen_file}'\nprintf '%s\\n' 'Open Doxygen HTML' > \"$output_dir\"/index.html\nprintf '%s\\n' 'Open Doxygen HTML' > \"$output_dir\"/html_index.html\nif [ -f \"$output_dir\"/xml/index.xml ]; then cp \"$output_dir\"/xml/index.xml \"$output_dir\"/index.xml; fi\n") + set(${script_name}_DOXYGEN_FILE "${doxygen_file}" PARENT_SCOPE) + set(${script_name}_POWERSHELL_SCRIPT "${power_shell_script}" PARENT_SCOPE) + set(${script_name}_BASH_SCRIPT "${bash_script}" PARENT_SCOPE) + set(${script_name}_OUTPUT_DIR "${ARG_OUTPUT_DIR}" PARENT_SCOPE) +endfunction() +function(psc_add_doxygen_directory_target target_name) + psc_generate_doxygen_directory_scripts(${target_name} ${ARGN}) + if (WIN32) + add_custom_target(${target_name} + COMMAND pwsh -NoProfile -ExecutionPolicy Bypass -File "${${target_name}_POWERSHELL_SCRIPT}" + VERBATIM + ) + else () + add_custom_target(${target_name} + COMMAND bash "${${target_name}_BASH_SCRIPT}" + VERBATIM + ) + endif () +endfunction() +function(psc_generate_doxygen_scripts script_name) + psc_generate_doxygen_directory_scripts(${script_name} ${ARGN}) + set(${script_name}_DOXYGEN_FILE "${${script_name}_DOXYGEN_FILE}" PARENT_SCOPE) + set(${script_name}_POWERSHELL_SCRIPT "${${script_name}_POWERSHELL_SCRIPT}" PARENT_SCOPE) + set(${script_name}_BASH_SCRIPT "${${script_name}_BASH_SCRIPT}" PARENT_SCOPE) + set(${script_name}_OUTPUT_DIR "${${script_name}_OUTPUT_DIR}" PARENT_SCOPE) +endfunction() +function(psc_add_doxygen_target target_name) + psc_add_doxygen_directory_target(${target_name} ${ARGN}) endfunction() diff --git a/Graphviz/main.cmake b/Graphviz/main.cmake index 4499deb..d5eafe6 100644 --- a/Graphviz/main.cmake +++ b/Graphviz/main.cmake @@ -1,10 +1,35 @@ -function(ys_add_graphviz_render_target target_name) +function(psc_graphviz_ps_array out_value) + set(values) + foreach(item IN LISTS ARGN) + string(REPLACE "\\" "/" normalized "${item}") + list(APPEND values "'${normalized}'") + endforeach() + string(REPLACE ";" "," value "${values}") + set(value "@(${value})") + set(${out_value} "${value}" PARENT_SCOPE) +endfunction() +function(psc_graphviz_sh_array out_value) + set(value "") + foreach(item IN LISTS ARGN) + string(REPLACE "\\" "/" normalized "${item}") + string(APPEND value "'${normalized}' ") + endforeach() + set(${out_value} "${value}" PARENT_SCOPE) +endfunction() +function(psc_graphviz_bool out_value value) + if (${value}) + set(${out_value} "$true" PARENT_SCOPE) + else () + set(${out_value} "$false" PARENT_SCOPE) + endif () +endfunction() +function(psc_generate_graphviz_render_scripts script_name) set(options) set(oneValueArgs OUTPUT_DIR FORMAT DOT_EXECUTABLE) set(multiValueArgs INPUT) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if (NOT ARG_OUTPUT_DIR) - set(ARG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/graphviz/${target_name}") + set(ARG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/graphviz/${script_name}") endif () if (NOT ARG_FORMAT) set(ARG_FORMAT "svg") @@ -12,36 +37,42 @@ function(ys_add_graphviz_render_target target_name) if (NOT ARG_DOT_EXECUTABLE) set(ARG_DOT_EXECUTABLE "C:/Program Files/Graphviz/bin/dot.exe") endif () - set(outputs) - foreach(dot_file IN LISTS ARG_INPUT) - get_filename_component(dot_name "${dot_file}" NAME_WE) - list(APPEND outputs "${ARG_OUTPUT_DIR}/${dot_name}.${ARG_FORMAT}") - endforeach() - add_custom_target(${target_name} - COMMAND "${CMAKE_COMMAND}" -E make_directory "${ARG_OUTPUT_DIR}" - VERBATIM - ) - foreach(dot_file IN LISTS ARG_INPUT) - get_filename_component(dot_name "${dot_file}" NAME_WE) - add_custom_command(TARGET ${target_name} POST_BUILD - COMMAND "${ARG_DOT_EXECUTABLE}" "-T${ARG_FORMAT}" "${dot_file}" "-o" "${ARG_OUTPUT_DIR}/${dot_name}.${ARG_FORMAT}" + psc_graphviz_ps_array(PSC_INPUT_FILES ${ARG_INPUT}) + psc_graphviz_sh_array(PSC_INPUT_FILES_SH ${ARG_INPUT}) + set(PSC_OUTPUT_DIR "${ARG_OUTPUT_DIR}") + set(PSC_FORMAT "${ARG_FORMAT}") + set(PSC_DOT_EXECUTABLE "${ARG_DOT_EXECUTABLE}") + set(script_dir "${CMAKE_CURRENT_BINARY_DIR}/psc_doc_scripts/${script_name}") + file(MAKE_DIRECTORY "${script_dir}") + set(power_shell_script "${script_dir}/${script_name}_graphviz_render.ps1") + set(bash_script "${script_dir}/${script_name}_graphviz_render.sh") + configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Graphviz_Render.ps1.in" "${power_shell_script}" @ONLY) + configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Graphviz_Render.sh.in" "${bash_script}" @ONLY) + set(${script_name}_POWERSHELL_SCRIPT "${power_shell_script}" PARENT_SCOPE) + set(${script_name}_BASH_SCRIPT "${bash_script}" PARENT_SCOPE) + set(${script_name}_OUTPUT_DIR "${ARG_OUTPUT_DIR}" PARENT_SCOPE) +endfunction() +function(psc_add_graphviz_render_target target_name) + psc_generate_graphviz_render_scripts(${target_name} ${ARGN}) + if (WIN32) + add_custom_target(${target_name} + COMMAND pwsh -NoProfile -ExecutionPolicy Bypass -File "${${target_name}_POWERSHELL_SCRIPT}" VERBATIM ) - endforeach() + else () + add_custom_target(${target_name} + COMMAND bash "${${target_name}_BASH_SCRIPT}" + VERBATIM + ) + endif () endfunction() -function(ys_add_cmake_graphviz_target target_name) - set(options) - set(oneValueArgs SOURCE_DIR BINARY_DIR OUTPUT_DIR FORMAT DOT_EXECUTABLE) - set(multiValueArgs) +function(psc_generate_graphviz_directory_scripts script_name) + set(options EXCLUDE_THIRD_PARTY) + set(oneValueArgs OUTPUT_DIR FORMAT DOT_EXECUTABLE MAX_DEPTH COLLAPSE_THRESHOLD) + set(multiValueArgs INPUT_DIRS EXCLUDE_DIRS) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - if (NOT ARG_SOURCE_DIR) - set(ARG_SOURCE_DIR "${CMAKE_SOURCE_DIR}") - endif () - if (NOT ARG_BINARY_DIR) - set(ARG_BINARY_DIR "${CMAKE_BINARY_DIR}") - endif () if (NOT ARG_OUTPUT_DIR) - set(ARG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/graphviz/${target_name}") + set(ARG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/graphviz/${script_name}") endif () if (NOT ARG_FORMAT) set(ARG_FORMAT "svg") @@ -49,12 +80,116 @@ function(ys_add_cmake_graphviz_target target_name) if (NOT ARG_DOT_EXECUTABLE) set(ARG_DOT_EXECUTABLE "C:/Program Files/Graphviz/bin/dot.exe") endif () - set(dot_file "${ARG_OUTPUT_DIR}/${target_name}.dot") - set(image_file "${ARG_OUTPUT_DIR}/${target_name}.${ARG_FORMAT}") - add_custom_target(${target_name} - COMMAND "${CMAKE_COMMAND}" -E make_directory "${ARG_OUTPUT_DIR}" - COMMAND "${CMAKE_COMMAND}" -S "${ARG_SOURCE_DIR}" -B "${ARG_BINARY_DIR}" "--graphviz=${dot_file}" - COMMAND "${ARG_DOT_EXECUTABLE}" "-T${ARG_FORMAT}" "${dot_file}" "-o" "${image_file}" - VERBATIM - ) + if (NOT ARG_INPUT_DIRS) + set(ARG_INPUT_DIRS "${CMAKE_SOURCE_DIR}") + endif () + if (NOT ARG_MAX_DEPTH) + set(ARG_MAX_DEPTH 4) + endif () + if (NOT ARG_COLLAPSE_THRESHOLD) + set(ARG_COLLAPSE_THRESHOLD 20) + endif () + psc_graphviz_ps_array(PSC_INPUT_DIRS ${ARG_INPUT_DIRS}) + psc_graphviz_ps_array(PSC_EXCLUDE_DIRS ${ARG_EXCLUDE_DIRS}) + psc_graphviz_sh_array(PSC_INPUT_DIRS_SH ${ARG_INPUT_DIRS}) + psc_graphviz_sh_array(PSC_EXCLUDE_DIRS_SH ${ARG_EXCLUDE_DIRS}) + psc_graphviz_bool(PSC_EXCLUDE_THIRD_PARTY ${ARG_EXCLUDE_THIRD_PARTY}) + set(PSC_OUTPUT_DIR "${ARG_OUTPUT_DIR}") + set(PSC_FORMAT "${ARG_FORMAT}") + set(PSC_DOT_EXECUTABLE "${ARG_DOT_EXECUTABLE}") + set(PSC_MAX_DEPTH "${ARG_MAX_DEPTH}") + set(PSC_COLLAPSE_THRESHOLD "${ARG_COLLAPSE_THRESHOLD}") + set(script_dir "${CMAKE_CURRENT_BINARY_DIR}/psc_doc_scripts/${script_name}") + file(MAKE_DIRECTORY "${script_dir}") + set(power_shell_script "${script_dir}/${script_name}_graphviz_directory.ps1") + set(bash_script "${script_dir}/${script_name}_graphviz_directory.sh") + configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Project_Graphs.ps1.in" "${power_shell_script}" @ONLY) + configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Project_Graphs.sh.in" "${bash_script}" @ONLY) + set(${script_name}_POWERSHELL_SCRIPT "${power_shell_script}" PARENT_SCOPE) + set(${script_name}_BASH_SCRIPT "${bash_script}" PARENT_SCOPE) + set(${script_name}_OUTPUT_DIR "${ARG_OUTPUT_DIR}" PARENT_SCOPE) +endfunction() +function(psc_add_graphviz_directory_target target_name) + psc_generate_graphviz_directory_scripts(${target_name} ${ARGN}) + if (WIN32) + add_custom_target(${target_name} + COMMAND pwsh -NoProfile -ExecutionPolicy Bypass -File "${${target_name}_POWERSHELL_SCRIPT}" + VERBATIM + ) + else () + add_custom_target(${target_name} + COMMAND bash "${${target_name}_BASH_SCRIPT}" + VERBATIM + ) + endif () +endfunction() +function(psc_target_graph_add_edge out_nodes out_edges left right) + set(nodes ${${out_nodes}}) + set(edges ${${out_edges}}) + list(APPEND nodes "${left}" "${right}") + list(APPEND edges "${left}|${right}") + list(REMOVE_DUPLICATES nodes) + list(REMOVE_DUPLICATES edges) + set(${out_nodes} ${nodes} PARENT_SCOPE) + set(${out_edges} ${edges} PARENT_SCOPE) +endfunction() +function(psc_generate_cmake_graphviz_scripts script_name) + set(options) + set(oneValueArgs OUTPUT_DIR FORMAT DOT_EXECUTABLE) + set(multiValueArgs TARGETS) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if (NOT ARG_OUTPUT_DIR) + set(ARG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/graphviz/${script_name}") + endif () + if (NOT ARG_FORMAT) + set(ARG_FORMAT "svg") + endif () + if (NOT ARG_DOT_EXECUTABLE) + set(ARG_DOT_EXECUTABLE "C:/Program Files/Graphviz/bin/dot.exe") + endif () + set(target_nodes) + set(target_edges) + foreach(target_name IN LISTS ARG_TARGETS) + if (TARGET ${target_name}) + list(APPEND target_nodes "${target_name}") + get_target_property(link_libs ${target_name} LINK_LIBRARIES) + get_target_property(interface_libs ${target_name} INTERFACE_LINK_LIBRARIES) + foreach(link_name IN LISTS link_libs interface_libs) + if (TARGET ${link_name}) + psc_target_graph_add_edge(target_nodes target_edges "${target_name}" "${link_name}") + endif () + endforeach() + endif () + endforeach() + list(REMOVE_DUPLICATES target_nodes) + psc_graphviz_ps_array(PSC_TARGETS ${target_nodes}) + psc_graphviz_ps_array(PSC_TARGET_EDGES ${target_edges}) + psc_graphviz_sh_array(PSC_TARGETS_SH ${target_nodes}) + psc_graphviz_sh_array(PSC_TARGET_EDGES_SH ${target_edges}) + set(PSC_OUTPUT_DIR "${ARG_OUTPUT_DIR}") + set(PSC_FORMAT "${ARG_FORMAT}") + set(PSC_DOT_EXECUTABLE "${ARG_DOT_EXECUTABLE}") + set(script_dir "${CMAKE_CURRENT_BINARY_DIR}/psc_doc_scripts/${script_name}") + file(MAKE_DIRECTORY "${script_dir}") + set(power_shell_script "${script_dir}/${script_name}_cmake_graphviz.ps1") + set(bash_script "${script_dir}/${script_name}_cmake_graphviz.sh") + configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Cmake_Target_Graph.ps1.in" "${power_shell_script}" @ONLY) + configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Cmake_Target_Graph.sh.in" "${bash_script}" @ONLY) + set(${script_name}_POWERSHELL_SCRIPT "${power_shell_script}" PARENT_SCOPE) + set(${script_name}_BASH_SCRIPT "${bash_script}" PARENT_SCOPE) + set(${script_name}_OUTPUT_DIR "${ARG_OUTPUT_DIR}" PARENT_SCOPE) +endfunction() +function(psc_add_cmake_graphviz_target target_name) + psc_generate_cmake_graphviz_scripts(${target_name} ${ARGN}) + if (WIN32) + add_custom_target(${target_name} + COMMAND pwsh -NoProfile -ExecutionPolicy Bypass -File "${${target_name}_POWERSHELL_SCRIPT}" + VERBATIM + ) + else () + add_custom_target(${target_name} + COMMAND bash "${${target_name}_BASH_SCRIPT}" + VERBATIM + ) + endif () endfunction()