From 40e094536791023da4c6080b6208cbb1126c323d Mon Sep 17 00:00:00 2001
From: Florian Uhlig <f.uhlig@gsi.de>
Date: Wed, 19 Aug 2020 13:50:36 +0200
Subject: [PATCH] Improve code format checker

Don't download the external packages when running the code format checker.
This improves the run time from more than 4 minutes to less than  1 minute.
Test each file individually such that the results on CDash are shown for each
file separately.
---
 CMakeLists.txt                        | 48 ++++++++++++++++--
 cmake/scripts/check-format-1.sh       | 21 ++++++++
 cmake/scripts/checkformat.cmake       |  6 ++-
 cmake/scripts/find_files.sh           |  8 +++
 external/CMakeLists.txt               | 73 ++++++++++++++++-----------
 sim/transport/geosetup/CMakeLists.txt |  2 +-
 6 files changed, 122 insertions(+), 36 deletions(-)
 create mode 100755 cmake/scripts/check-format-1.sh
 create mode 100755 cmake/scripts/find_files.sh

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b25e8e1804..b69f85d748 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -326,7 +326,7 @@ EndIf(BUILD_UNITTESTS)
 
 ### Subdirectories to be compiled #####
 
-### Externals included as svn externals
+### Externals included and build from sveral sources
 add_subdirectory (external)
 
 ### Base directories
@@ -359,10 +359,50 @@ add_custom_target(cleantest
 
 find_package2(PRIVATE ClangFormat)
 if(ClangFormat_FOUND)
+  if (FAIRROOT_FORMAT_BASE)
+    set(BASE_COMMIT ${FAIRROOT_FORMAT_BASE})
+  else()
+    set(BASE_COMMIT upstream/master)
+  endif()
+
+  if (FAIRROOT_GIT_CLANG_FORMAT_BIN)
+    set(GIT_CLANG_FORMAT_BIN ${FAIRROOT_GIT_CLANG_FORMAT_BIN})
+  else()
+    set(GIT_CLANG_FORMAT_BIN git-clang-format)
+  endif()
+
+  # Create a list C, C++ and header files which have been changed in the
+  # current commit
+  execute_process(COMMAND ${CMAKE_SOURCE_DIR}/cmake/scripts/find_files.sh
+                  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+                  OUTPUT_VARIABLE FileList
+                  OUTPUT_STRIP_TRAILING_WHITESPACE
+                 )
+  string(REGEX REPLACE " " ";" FileList "${FileList}")
+
+  # Loop over the files and create the code whch is executed when running
+  # "make FormatCheck".
+  # The produced code will run clang-format on one of the files. If
+  # clang-format finds code which are not satisfying our code rules a
+  # detailed error message is created. This error message can be checked on
+  # our CDash web page.
+  foreach(file ${FileList})
+    set(file1 ${CMAKE_BINARY_DIR}/${file}.cf_out)
+
+    list(APPEND myfilelist ${file1})
+    add_custom_command(OUTPUT ${file1}
+                       COMMAND ${CMAKE_SOURCE_DIR}/cmake/scripts/check-format-1.sh ${file} ${file1}
+                       WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+                      )
+  endforeach()
+
+  # Create the target FormatCheck which only depends on the files creted in
+  # previous step. When running "make FormatCheck" clang-format is executed
+  # for all C, C++ and header files which have changed in the commit.
   add_custom_target(FormatCheck
-    ${CMAKE_COMMAND} -E env FAIRROOT_GIT_CLANG_FORMAT_BIN=${GIT_CLANG_FORMAT_BIN} ${CMAKE_SOURCE_DIR}/cmake/scripts/check-format.sh
-    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
-  )
+                     DEPENDS ${myfilelist}
+                    )
+
 endif()
 
 Option(BUILD_DOXYGEN "Build Doxygen" OFF)
diff --git a/cmake/scripts/check-format-1.sh b/cmake/scripts/check-format-1.sh
new file mode 100755
index 0000000000..f4ce7c6016
--- /dev/null
+++ b/cmake/scripts/check-format-1.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+infile=$1
+outfile=$2
+
+BASE_COMMIT=${FAIRROOT_FORMAT_BASE:-HEAD}
+GIT_CLANG_FORMAT_BIN=${FAIRROOT_GIT_CLANG_FORMAT_BIN:-git-clang-format}
+
+RESULT=$($GIT_CLANG_FORMAT_BIN --commit $BASE_COMMIT --diff $infile --extensions h,hpp,c,C,cpp,cxx,tpl)
+
+if [ "$RESULT" == "no modified files to format" ] || [ "$RESULT" == "clang-format did not modify any files" ]; then
+  exit 0
+else
+  echo "ERROR: format check failed for file $infile. Suggested changes:" > $outfile
+  echo  >> $outfile
+  echo "$RESULT" >> $outfile
+  echo "ERROR: format check failed for file $infile. Suggested changes:"
+  echo
+  echo "$RESULT"
+  exit 1
+fi
diff --git a/cmake/scripts/checkformat.cmake b/cmake/scripts/checkformat.cmake
index 61d3814beb..1e3a1acfa0 100644
--- a/cmake/scripts/checkformat.cmake
+++ b/cmake/scripts/checkformat.cmake
@@ -1,11 +1,13 @@
 cmake_host_system_information(RESULT fqdn QUERY FQDN)
 
-set(CTEST_SOURCE_DIRECTORY .)
-set(CTEST_BINARY_DIRECTORY build)
+Set(CTEST_SOURCE_DIRECTORY $ENV{SOURCEDIR})
+Set(CTEST_BINARY_DIRECTORY $ENV{BUILDDIR})
 Set(CTEST_PROJECT_NAME "CbmRoot")
 set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
 set(CTEST_USE_LAUNCHERS ON)
 
+Set(CTEST_CONFIGURE_COMMAND " \"${CMAKE_EXECUTABLE_NAME}\" \"-G${CTEST_CMAKE_GENERATOR}\" \"-DCTEST_USE_LAUNCHERS=${CTEST_USE_LAUNCHERS}\" \"-DDOWNLOAD_EXTERNALS=OFF\" \"${CTEST_SOURCE_DIRECTORY}\" ")
+
 if ("$ENV{CTEST_SITE}" STREQUAL "")
   set(CTEST_SITE "${fqdn}")
 else()
diff --git a/cmake/scripts/find_files.sh b/cmake/scripts/find_files.sh
new file mode 100755
index 0000000000..b680f3ae5b
--- /dev/null
+++ b/cmake/scripts/find_files.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+BASE_COMMIT=${FAIRROOT_FORMAT_BASE:-HEAD}
+GIT_CLANG_FORMAT_BIN=${FAIRROOT_GIT_CLANG_FORMAT_BIN:-git-clang-format}
+
+FILES=$(git diff --name-only $BASE_COMMIT | grep -E '.*\.(h|hpp|c|C|cpp|cxx|tpl)$' | grep -viE '.*LinkDef.h$')
+
+echo $FILES
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
index e92f1b7f6d..9c3c36f707 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
@@ -1,36 +1,51 @@
 # Build all libraries which come from external sources like other subversion or git repositories
 
-download_project_if_needed(PROJECT         cppzmq
-                           GIT_REPOSITORY  "https://github.com/zeromq/cppzmq/"
-                           GIT_TAG         "05a0256d0eeea8063690fde6a156e14b70ed2280"
-                           SOURCE_DIR      ${CMAKE_CURRENT_SOURCE_DIR}/cppzmq
-                           TEST_FILE       zmq.hpp
-                          )
+# Exclude dowload of external packages. The external packages are not needed
+# to run the code format checker and slows down the execution.
+# Without the externals it isn't possible to build CbmRoot so don't switch
+# it off execept for the checker.
+Option(DOWNLOAD_EXTERNALS "Download the code from the external repositories." ON)
 
-download_project_if_needed(PROJECT         flib_dpb_20
-                           GIT_REPOSITORY  "https://git.cbm.gsi.de/f.uhlig/flib_dpb_20.git"
-                           GIT_TAG         "9ce7c7c0ccc7c9ea2f8c396c35d7fe39ac9aafb6"
-                           SOURCE_DIR      ${CMAKE_CURRENT_SOURCE_DIR}/flib_dpb_20
-                           TEST_FILE       CMakeLists.txt
-                          )
+if(DOWNLOAD_EXTERNALS)
+  download_project_if_needed(PROJECT         cppzmq
+                             GIT_REPOSITORY  "https://github.com/zeromq/cppzmq/"
+                             GIT_TAG         "05a0256d0eeea8063690fde6a156e14b70ed2280"
+                             SOURCE_DIR      ${CMAKE_CURRENT_SOURCE_DIR}/cppzmq
+                             TEST_FILE       zmq.hpp
+                            )
 
-Set(IPC_INCLUDE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ipc/ipc/lib/fles_ipc PARENT_SCOPE)
-Set(IPCLOG_INCLUDE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ipc/ipc/lib/logging PARENT_SCOPE)
+  download_project_if_needed(PROJECT         flib_dpb_20
+                             GIT_REPOSITORY  "https://git.cbm.gsi.de/f.uhlig/flib_dpb_20.git"
+                             GIT_TAG         "9ce7c7c0ccc7c9ea2f8c396c35d7fe39ac9aafb6"
+                             SOURCE_DIR      ${CMAKE_CURRENT_SOURCE_DIR}/flib_dpb_20
+                             TEST_FILE       CMakeLists.txt
+                            )
 
-Add_Subdirectory(ipc)
-Add_Subdirectory(ipc_legacy)
-Add_Subdirectory(flib_dpb)
-Add_Subdirectory(flib_dpb_20)
-Add_Subdirectory(spadic)
+  Set(IPC_INCLUDE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ipc/ipc/lib/fles_ipc PARENT_SCOPE)
+  Set(IPCLOG_INCLUDE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ipc/ipc/lib/logging PARENT_SCOPE)
 
-Include(InstallVC.cmake)
-Include(InstallKFParticle.cmake)
-Include(InstallDataTree.cmake)
-Include(InstallDataTreeQA.cmake)
-Include(InstallNicaFemto.cmake)
-Include(InstallAnalysisTree.cmake)
-Include(InstallAnalysisTreeQA.cmake)
+  Add_Subdirectory(ipc)
+  Add_Subdirectory(ipc_legacy)
+  Add_Subdirectory(flib_dpb)
+  Add_Subdirectory(flib_dpb_20)
+  Add_Subdirectory(spadic)
 
-Include(InstallParameter.cmake)
-Include(InstallInput.cmake)
-Include(InstallGeometry.cmake)
+  Include(InstallVC.cmake)
+  Include(InstallKFParticle.cmake)
+  Include(InstallDataTree.cmake)
+  Include(InstallDataTreeQA.cmake)
+  Include(InstallNicaFemto.cmake)
+  Include(InstallAnalysisTree.cmake)
+  Include(InstallAnalysisTreeQA.cmake)
+
+  Include(InstallParameter.cmake)
+  Include(InstallInput.cmake)
+  Include(InstallGeometry.cmake)
+else()
+  # Define targets which are needed by CbmRoot but are not available
+  # whithout the external packages
+  add_library(DATATREE SHARED IMPORTED GLOBAL)
+  add_library(ANALYSISTREE SHARED IMPORTED GLOBAL)
+  add_library(NICAFEMTO SHARED IMPORTED GLOBAL)
+  add_library(KFPARTICLE SHARED IMPORTED GLOBAL)
+endif()
diff --git a/sim/transport/geosetup/CMakeLists.txt b/sim/transport/geosetup/CMakeLists.txt
index 9075e5f0e3..f512c21913 100644
--- a/sim/transport/geosetup/CMakeLists.txt
+++ b/sim/transport/geosetup/CMakeLists.txt
@@ -2,7 +2,7 @@
 # the array .
 # The extension is already found.  Any number of sources could be listed here.
 
-If(NOT EXISTS geodb.tar.gz)
+If(NOT EXISTS geodb.tar.gz AND DOWNLOAD_EXTERNALS)
   Message(STATUS "Download geometry database")
   FILE(DOWNLOAD http://cbmdb.jinr.ru/geometry/download_file.php?type=all&tag=all ${CMAKE_BINARY_DIR}/geodb.tar.gz SHOW_PROGRESS)
 
-- 
GitLab