diff --git a/cmake_support/PROMOD3.cmake b/cmake_support/PROMOD3.cmake index 8f9c97eceb95c37e1fdebf38a26c73986771bf69..1ad5fb7e82f5f72230240aeda8adf6ceedd261ae 100644 --- a/cmake_support/PROMOD3.cmake +++ b/cmake_support/PROMOD3.cmake @@ -661,62 +661,62 @@ macro(promod3_unittest) add_unit_test_data_target(DAT "test_data_${_ARG_MODULE}") endforeach() endif(_ARG_DATA) - foreach(src ${_SOURCES}) - if(${src} MATCHES "\\.py$") - list(APPEND PY_TESTS "${src}") - else() - list(APPEND CPP_TESTS "${CMAKE_CURRENT_SOURCE_DIR}/${src}") - endif() - endforeach() - set(_SOURCES ${CPP_TESTS}) - set(_test_name "test_suite_${_ARG_MODULE}") - if(DEFINED CPP_TESTS) - if(COMPILE_TESTS) - add_executable(${_test_name} ${_SOURCES}) - else() - add_executable(${_test_name} EXCLUDE_FROM_ALL ${_SOURCES}) - endif() - set_target_properties(${_test_name} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - set_target_properties(${_test_name} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}) - set_target_properties(${_test_name} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}) - add_dependencies(${_test_name} "test_data_${_ARG_MODULE}") - target_link_libraries(${_test_name} ${BOOST_UNIT_TEST_LIBRARIES} - "${_ARG_PREFIX}_${_ARG_MODULE}") - add_custom_target("${_test_name}_run" - COMMAND - PROMOD3_ROOT=${STAGE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${_test_name} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "running checks for module ${_ARG_MODULE}" - DEPENDS ${_test_name}) - add_dependencies("${_test_name}_run" "_${_ARG_MODULE}") - set(_xml_test_cmd "PROMOD3_ROOT=${STAGE_DIR}") - set(_xml_test_cmd ${_xml_test_cmd} ${CMAKE_CURRENT_BINARY_DIR}) - set(_xml_test_cmd "${_xml_test_cmd}/${_test_name}") - set(_xml_test_cmd ${_xml_test_cmd} "--log_format=xml" "--log_level=all") - # XML test outputgets an logical OR to 'echo' so if sth fails, make - # continues and we get output for all unit tests. Just calling 'echo' - # giveth $?=0. - add_custom_target("${_test_name}_run_xml" - COMMAND ${_xml_test_cmd} > ${_test_name}_log.xml || echo - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "running checks for module ${_ARG_MODULE}" - DEPENDS "_${_ARG_MODULE}" ${_test_name}) - add_test("${_test_name}" ${CMAKE_CURRENT_BINARY_DIR}/${_test_name} ) - add_dependencies(check_xml "${_test_name}_run_xml") - add_dependencies(codetest "${_test_name}_run") - - if(_ARG_LINK) - target_link_libraries("${_test_name}" ${_ARG_LINK}) - endif() + foreach(src ${_SOURCES}) + if(${src} MATCHES "\\.py$") + list(APPEND PY_TESTS "${src}") + else() + list(APPEND CPP_TESTS "${CMAKE_CURRENT_SOURCE_DIR}/${src}") + endif() + endforeach() + set(_SOURCES ${CPP_TESTS}) + set(_test_name "test_suite_${_ARG_MODULE}") + if(DEFINED CPP_TESTS) + if(COMPILE_TESTS) + add_executable(${_test_name} ${_SOURCES}) + else() + add_executable(${_test_name} EXCLUDE_FROM_ALL ${_SOURCES}) + endif() + set_target_properties(${_test_name} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + set_target_properties(${_test_name} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}) + set_target_properties(${_test_name} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}) + add_dependencies(${_test_name} "test_data_${_ARG_MODULE}") + target_link_libraries(${_test_name} ${BOOST_UNIT_TEST_LIBRARIES} + "${_ARG_PREFIX}_${_ARG_MODULE}") + add_custom_target("${_test_name}_run" + COMMAND + PROMOD3_ROOT=${STAGE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${_test_name} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "running checks for module ${_ARG_MODULE}" + DEPENDS ${_test_name}) + add_dependencies("${_test_name}_run" "_${_ARG_MODULE}") + set(_xml_test_cmd "PROMOD3_ROOT=${STAGE_DIR}") + set(_xml_test_cmd ${_xml_test_cmd} ${CMAKE_CURRENT_BINARY_DIR}) + set(_xml_test_cmd "${_xml_test_cmd}/${_test_name}") + set(_xml_test_cmd ${_xml_test_cmd} "--log_format=xml" "--log_level=all") + # XML test outputgets an logical OR to 'echo' so if sth fails, make + # continues and we get output for all unit tests. Just calling 'echo' + # giveth $?=0. + add_custom_target("${_test_name}_run_xml" + COMMAND ${_xml_test_cmd} > ${_test_name}_log.xml || echo + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "running checks for module ${_ARG_MODULE}" + DEPENDS "_${_ARG_MODULE}" ${_test_name}) + add_test("${_test_name}" ${CMAKE_CURRENT_BINARY_DIR}/${_test_name} ) + add_dependencies(check_xml "${_test_name}_run_xml") + add_dependencies(codetest "${_test_name}_run") - set_target_properties(${_test_name} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY - "${CMAKE_CURRENT_BINARY_DIR}") + if(_ARG_LINK) + target_link_libraries("${_test_name}" ${_ARG_LINK}) endif() + set_target_properties(${_test_name} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_CURRENT_BINARY_DIR}") + endif() + foreach(py_test ${PY_TESTS}) set(py_twp "${CMAKE_CURRENT_SOURCE_DIR}/${py_test}") if(NOT EXISTS "${py_twp}") diff --git a/extras/pre_commit/pm3_csc/filecheck/cmake.py b/extras/pre_commit/pm3_csc/filecheck/cmake.py index 3eb899982a2252aca6c2d2f16072bf11f4eff29a..9bc06c24f7c5315da19f9ce9f17896929ea7538f 100644 --- a/extras/pre_commit/pm3_csc/filecheck/cmake.py +++ b/extras/pre_commit/pm3_csc/filecheck/cmake.py @@ -2,7 +2,7 @@ Checking CMake files. """ -import re +import re, os from .. import pm3_csc from . import base @@ -12,8 +12,34 @@ class Cmake(base.FileCheck): Checking CMake setups/ code. """ def __init__(self, filepath): + self._documented_macros = list() + self.doc_file = "<NOT YET SET>" base.FileCheck.__init__(self, filepath) + @property + def documented_macros(self): + ''' + Load documentation only on demand. + ''' + if len(self._documented_macros): + return self._documented_macros + doc_path = os.path.split(__file__)[0] + doc_path = os.path.join(doc_path, os.pardir, os.pardir, os.pardir, + os.pardir) + doc_path = os.path.join(doc_path, 'cmake_support', 'doc', 'index.rst') + doc_path = os.path.abspath(doc_path) + self.doc_file = doc_path + dfh = open(doc_path) + for d_line in dfh: + # we follow our own format very rigidly, here: commands are defined + # by '.. cmake:command:: <command name>', with all the white spaces + m_dc = re.match(r'\.\.\scmake:command::\s([^\s]+)', d_line) + if m_dc: + m_dcn = m_dc.group(1) + self._documented_macros.append(m_dcn) + dfh.close() + return self._documented_macros + def CheckClosingStatement(self, line): ''' Check closing statement to carry identifier for the opening one. @@ -53,6 +79,29 @@ class Cmake(base.FileCheck): "this is a function/ macro call, "+ "omit the space", 16) + def CheckFuncDoc(self, line): + ''' + Check that functions/ macros have documentation in the correpsonding + cmake/support/doc/index.rst. + ''' + m_open = re.match(r'(?:macro|function)\(([^\s]*)\)', line) + if m_open: + m_name = m_open.group(1) + if not len(m_name): + pm3_csc.FailMsg("Line %d: Found a " % self.current_line+ + "'nameless' function macro definition? "+ + "This should not happen.", 17) + if m_name not in self.documented_macros: + pm3_csc.FailMsg("Line %d: Command '%s' " % (self.current_line, + m_name)+ + "has no documentation in '%s'." % self.doc_file+ + "If you just wrote that command, please write "+ + "documentation. CMake code is rarely visited, "+ + "so what exactly a command does is forgotten "+ + "rather quickly. So do write down, WHAT the "+ + "command does and HOW, the strategy behind it.", + 18) + def Check(self, ignore_line_width=False): # for .cmake files: documentation of macros in index.rst for line in self.GetLine(ignore_line_width): @@ -62,5 +111,7 @@ class Cmake(base.FileCheck): if len(ex_line): self.CheckClosingStatement(ex_line) self.CheckWhitespace(line) + if self.filepath.endswith('.cmake'): + self.CheckFuncDoc(ex_line) __all__ = ('Cmake', )