Warning, /geant4/cmake/Modules/G4ClangFormat.cmake is written in an unsupported language. File is not indexed.
0001 #.rst
0002 # G4ClangFormat
0003 # =============
0004 #
0005 # Functions and helper targets for formatting sources of a target using
0006 # clang-format
0007
0008 # - Include guard
0009 include_guard(DIRECTORY)
0010
0011 # Default logging directory
0012 set(G4FORMAT_LOGDIR ${PROJECT_BINARY_DIR}/format CACHE PATH
0013 "Output folder of files that are formatted")
0014
0015 # Find clang-format (optional)
0016 find_program(CLANG_FORMATTER NAMES
0017 clang-format-6 # prefer clang-format version 6.0
0018 clang-format-6.0
0019 clang-format-mp-6.0 # Apple macports version
0020 clang-format)
0021
0022 function(exclude_from_format)
0023 cmake_parse_arguments(ARG "" "" "HEADERS;SOURCES;FILES" ${ARGN})
0024
0025 function(_add_labels _path)
0026 foreach(_FILE ${ARGN})
0027 if(NOT IS_ABSOLUTE ${_FILE})
0028 set(_FILE ${CMAKE_CURRENT_LIST_DIR}${_path}/${_FILE})
0029 endif()
0030 set(_LABELS "EXCLUDE_FORMAT")
0031 get_source_file_property(_EXISTING_LABELS ${_FILE} LABELS)
0032 if(_EXISTING_LABELS)
0033 list(APPEND _LABELS ${_EXISTING_LABELS})
0034 endif()
0035 set_source_files_properties(${_FILE} PROPERTIES LABELS "${_LABELS}")
0036 get_source_file_property(_EXISTING_LABELS ${_FILE} LABELS)
0037 endforeach()
0038 endfunction()
0039
0040 _add_labels("/include" ${ARG_HEADERS})
0041 _add_labels("/src" ${ARG_SOURCES})
0042 _add_labels("" ${ARG_FILES})
0043 endfunction()
0044
0045 #------------------------------------------------------------------------------#
0046
0047 function(create_format_directory)
0048 if(NOT EXISTS ${G4FORMAT_LOGDIR})
0049 execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${G4FORMAT_LOGDIR})
0050 endif()
0051 endfunction()
0052
0053 #------------------------------------------------------------------------------#
0054
0055 function(geant4_format_target)
0056 if(NOT CLANG_FORMATTER)
0057 return()
0058 endif()
0059
0060 cmake_parse_arguments(G4FMTTARGET "" "NAME" "SOURCES" ${ARGN})
0061 string(REGEX REPLACE "-format$" "" G4TARGET_NAME "${G4FMTTARGET_NAME}")
0062
0063 # ensure not empty list
0064 if("${G4FMTTARGET_SOURCES}" STREQUAL "")
0065 return()
0066 endif()
0067
0068 # create output directory
0069 create_format_directory()
0070 set(SOURCES ) # list of sources
0071 set(FILELOG ) # string of sources (for log)
0072 foreach(_SOURCE ${G4FMTTARGET_SOURCES})
0073 # files in binary directory are almost always generated files
0074 string(FIND "${_SOURCE}" "${PROJECT_BINARY_DIR}" IN_BINARY_DIR)
0075 # ignore generated files
0076 if(IN_BINARY_DIR GREATER -1)
0077 continue()
0078 endif()
0079 # check if exists (valid full path)
0080 if(EXISTS "${_SOURCE}")
0081 # do nothing -- absolute path was specified
0082 elseif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${_SOURCE}")
0083 # a relative path was specified
0084 set(_SOURCE ${CMAKE_CURRENT_LIST_DIR}/${_SOURCE})
0085 else()
0086 # neither relative nor absolute
0087 message(STATUS "[format] file not found: '${_SOURCE}'")
0088 continue()
0089 endif()
0090 #string(REPLACE "${PROJECT_SOURCE_DIR}/" "" _SOURCE ${_SOURCE})
0091 get_source_file_property(SOURCE_LABELS ${_SOURCE} LABELS)
0092 list(FIND SOURCE_LABELS "EXCLUDE_FORMAT" EXCLUDE_FORMAT)
0093 if(EXCLUDE_FORMAT GREATER -1)
0094 continue()
0095 endif()
0096 # append to log
0097 set(FILELOG "${FILELOG}${_SOURCE}\n")
0098 # add to list to be processed
0099 list(APPEND SOURCES ${_SOURCE})
0100 endforeach()
0101
0102 # write format file
0103 set(FMTLOG_OUT ${G4FORMAT_LOGDIR}/${G4TARGET_NAME}.txt)
0104 file(WRITE ${FMTLOG_OUT} "${FILELOG}")
0105 file(RELATIVE_PATH FMTLOG_RELATIVE_OUT ${PROJECT_BINARY_DIR} ${FMTLOG_OUT})
0106 # get the number of source files
0107 list(LENGTH SOURCES NUM_SOURCES)
0108 # if there are too many source files (arguments), command will fail
0109 # so process no more than 500 at a time
0110 if(NUM_SOURCES GREATER 500)
0111 # function to generate indices
0112 function(generate_indices VAR NUM)
0113 set(INDICES )
0114 set(N 0)
0115 while(N LESS NUM)
0116 list(APPEND INDICES ${N})
0117 math(EXPR N "${N}+1")
0118 endwhile()
0119 set(${VAR} ${INDICES} PARENT_SCOPE)
0120 endfunction()
0121 # generate 500 indices
0122 generate_indices(INDICES 500)
0123 set(FORMAT_COMMANDS )
0124 # while there are still sources in list
0125 while(NUM_SOURCES GREATER 0)
0126 # if below 500, re-generate indices
0127 if(NUM_SOURCES LESS 500)
0128 generate_indices(INDICES ${NUM_SOURCES})
0129 endif()
0130 # get the subset of first 500
0131 list(GET SOURCES ${INDICES} SOURCES_SUBSET)
0132 # add the target for block of 500
0133 list(APPEND FORMAT_COMMANDS COMMAND ${CLANG_FORMATTER} -i ${SOURCES_SUBSET})
0134 # remove 500 we just processed
0135 list(REMOVE_AT SOURCES ${INDICES})
0136 # update the number of sources remaining
0137 list(LENGTH SOURCES NUM_SOURCES)
0138 endwhile()
0139 # add the custom command
0140 list(LENGTH FORMAT_COMMANDS NUM_COMMANDS)
0141 if(NUM_COMMANDS GREATER 0)
0142 add_custom_target(${G4FMTTARGET_NAME}
0143 ${FORMAT_COMMANDS}
0144 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
0145 COMMENT "Running '${CLANG_FORMATTER}' on source files in '${G4TARGET_NAME}' target (see ${FMTLOG_RELATIVE_OUT})...")
0146 endif()
0147 else()
0148 list(LENGTH SOURCES NUM_SOURCES)
0149 if(NUM_SOURCES GREATER 0)
0150 # if less than 500 source files, add all in one target
0151 add_custom_target(${G4FMTTARGET_NAME}
0152 COMMAND ${CLANG_FORMATTER} -i ${SOURCES}
0153 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
0154 COMMENT
0155 "Running '${CLANG_FORMATTER}' on source files in '${G4TARGET_NAME}' target (see ${FMTLOG_RELATIVE_OUT})...")
0156 endif()
0157 endif(NUM_SOURCES GREATER 500)
0158 endfunction()