Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
MITKDashboardDriverScript.cmake
Go to the documentation of this file.
1 
2 #
3 # Included from a dashboard script, this cmake file will drive the configure and build
4 # steps of MITK
5 #
6 
7 #-----------------------------------------------------------------------------
8 # The following variable are expected to be define in the top-level script:
9 set(expected_variables
10  CTEST_NOTES_FILES
11  CTEST_SITE
12  CTEST_DASHBOARD_ROOT
13  CTEST_CMAKE_COMMAND
14  CTEST_CMAKE_GENERATOR
15  WITH_MEMCHECK
16  WITH_COVERAGE
17  WITH_DOCUMENTATION
18  CTEST_BUILD_CONFIGURATION
19  CTEST_TEST_TIMEOUT
20  CTEST_BUILD_FLAGS
21  TEST_TO_EXCLUDE_REGEX
22  CTEST_SOURCE_DIRECTORY
23  CTEST_BINARY_DIRECTORY
24  CTEST_BUILD_NAME
25  SCRIPT_MODE
26  CTEST_COVERAGE_COMMAND
27  CTEST_MEMORYCHECK_COMMAND
28  CTEST_GIT_COMMAND
29  PROJECT_BUILD_DIR
30  )
31 
32 foreach(var ${expected_variables})
33  if(NOT DEFINED ${var})
34  message(FATAL_ERROR "Variable ${var} should be defined in top-level script !")
35  endif()
36 endforeach()
37 
38 string(REPLACE " " "%20" _build_name_escaped "${CTEST_BUILD_NAME}")
39 
40 # Check if "mbits" is reachable
41 file(DOWNLOAD "http://mbits" "${CTEST_SCRIPT_DIRECTORY}/mbits.html" TIMEOUT 2 STATUS _status)
42 list(GET _status 0 _status_code)
43 if(_status_code EQUAL 0) # successful completion
44  set(MBITS_AVAILABLE 1)
45 else()
46  set(MBITS_AVAILABLE 0)
47 endif()
48 
49 #
50 # Site specific options
51 #
52 if(NOT CDASH_ADMIN_URL_PREFIX AND MBITS_AVAILABLE)
53  set(CDASH_ADMIN_URL_PREFIX "http://mbits")
54 endif()
55 
56 if(NOT DEFINED GIT_BRANCH OR GIT_BRANCH STREQUAL "")
57  set(GIT_BRANCH "")
58 else()
59  set(GIT_BRANCH "-b ${GIT_BRANCH}")
60 endif()
61 
62 # Should binary directory be cleaned?
63 set(empty_binary_directory FALSE)
64 
65 # Attempt to build and test also if 'ctest_update' returned an error
66 set(initial_force_build FALSE)
67 
68 # Set model options
69 set(model "")
70 if(SCRIPT_MODE STREQUAL "experimental")
71  set(empty_binary_directory FALSE)
72  set(initial_force_build TRUE)
73  set(model Experimental)
74 elseif(SCRIPT_MODE STREQUAL "continuous")
75  set(empty_binary_directory FALSE)
76  set(initial_force_build FALSE)
77  set(model Continuous)
78 elseif(SCRIPT_MODE STREQUAL "nightly")
79  set(empty_binary_directory TRUE)
80  set(initial_force_build TRUE)
81  set(model Nightly)
82 else()
83  message(FATAL_ERROR "Unknown script mode: '${SCRIPT_MODE}'. Script mode should be either 'experimental', 'continuous' or 'nightly'")
84 endif()
85 
86 #message("script_mode:${SCRIPT_MODE}")
87 #message("model:${model}")
88 #message("empty_binary_directory:${empty_binary_directory}")
89 #message("force_build:${initial_force_build}")
90 
91 set(CTEST_CONFIGURATION_TYPE ${CTEST_BUILD_CONFIGURATION})
92 
93 if(empty_binary_directory)
94  message("Directory ${CTEST_BINARY_DIRECTORY} cleaned !")
95  ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY})
96 endif()
97 
98 if(NOT DEFINED CTEST_CHECKOUT_DIR)
99  set(CTEST_CHECKOUT_DIR ${CTEST_SOURCE_DIRECTORY})
100 endif()
101 
102 if(NOT EXISTS "${CTEST_CHECKOUT_DIR}")
103  set(CTEST_CHECKOUT_COMMAND "\"${CTEST_GIT_COMMAND}\" clone ${GIT_BRANCH} ${GIT_REPOSITORY} \"${CTEST_CHECKOUT_DIR}\"")
104 endif()
105 
106 set(CTEST_UPDATE_TYPE "git")
107 set(CTEST_UPDATE_COMMAND "${CTEST_GIT_COMMAND}")
108 
109 #----------------------------------------------------------------------
110 # Utility macros
111 #----------------------------------------------------------------------
112 
113 function(func_build_target target build_dir)
114  set(CTEST_BUILD_TARGET ${target})
115  ctest_build(BUILD "${build_dir}" APPEND
116  RETURN_VALUE res
117  NUMBER_ERRORS num_errors
118  NUMBER_WARNINGS num_warnings)
119  ctest_submit(PARTS Build RETRY_DELAY 3 RETRY_COUNT 3)
120 
121  if(num_errors)
122  math(EXPR build_errors "${build_errors} + ${num_errors}")
123  set(build_errors ${build_errors} PARENT_SCOPE)
124  endif()
125  if(num_warnings)
126  math(EXPR build_warnings "${build_warnings} + ${num_warnings}")
127  set(build_warnings ${build_warnings} PARENT_SCOPE)
128  endif()
129 endfunction()
130 
131 function(func_test label build_dir)
132  if(NOT TESTING_PARALLEL_LEVEL)
133  set(TESTING_PARALLEL_LEVEL 8)
134  endif()
135 
136  if(label MATCHES "Unlabeled")
137  set(_include_label EXCLUDE_LABEL .*)
138  else()
139  set(_include_label INCLUDE_LABEL ${label})
140  endif()
141 
142  ctest_test(BUILD "${build_dir}"
143  ${_include_label}
144  PARALLEL_LEVEL ${TESTING_PARALLEL_LEVEL}
145  EXCLUDE ${TEST_TO_EXCLUDE_REGEX}
146  RETURN_VALUE res
147  )
148  ctest_submit(PARTS Test RETRY_DELAY 3 RETRY_COUNT 3)
149 
150  if(res)
151  math(EXPR test_errors "${test_errors} + 1")
152  set(test_errors ${test_errors} PARENT_SCOPE)
153  endif()
154 
155  if(ARG3)
156  set(WITH_COVERAGE ${ARG3})
157  endif()
158  if(ARG4)
159  set(WITH_MEMCHECK ${ARG4})
160  endif()
161 
162  if(WITH_COVERAGE AND CTEST_COVERAGE_COMMAND)
163  message("----------- [ Coverage ${label} ] -----------")
164  ctest_coverage(BUILD "${build_dir}" LABELS ${label})
165  ctest_submit(PARTS Coverage RETRY_DELAY 3 RETRY_COUNT 3)
166  endif()
167 
168  if(WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND)
169  if(NOT CTEST_MEMORYCHECK_SUPPRESSIONS_FILE)
170  if(EXISTS "${CTEST_SOURCE_DIRECTORY}/CMake/valgrind.supp")
171  set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "${CTEST_SOURCE_DIRECTORY}/CMake/valgrind.supp")
172  endif()
173  endif()
174  if(NOT CTEST_MEMORYCHECK_COMMAND_OPTIONS)
175  set(CTEST_MEMORYCHECK_COMMAND_OPTIONS "-q --tool=memcheck --leak-check=yes --show-reachable=no --show-possibly-lost=no --workaround-gcc296-bugs=yes --num-callers=50")
176  endif()
177  ctest_memcheck(BUILD "${build_dir}" INCLUDE_LABEL ${label})
178  ctest_submit(PARTS MemCheck RETRY_DELAY 3 RETRY_COUNT 3)
179  endif()
180 
181 endfunction()
182 
183 macro(finalize_submission)
184 
185  # Note should be at the end
186  ctest_submit(PARTS Notes RETRY_DELAY 3 RETRY_COUNT 3)
187 
188  # Send status to the "CDash Web Admin"
189  if(CDASH_ADMIN_URL_PREFIX)
190  set(cdash_admin_url "${CDASH_ADMIN_URL_PREFIX}/cdashadmin-web/index.php?pw=4da12ca9c06d46d3171d7f73974c900f")
191  string(REGEX REPLACE ".*\\?project=(.*)&?" "\\1" _ctest_project "${CTEST_DROP_LOCATION}")
192  file(DOWNLOAD
193  "${cdash_admin_url}&action=submit&name=${_build_name_escaped}&hasTestErrors=${test_errors}&hasBuildErrors=${build_errors}&hasBuildWarnings=${build_warnings}&ctestDropSite=${CTEST_DROP_SITE}&ctestProject=${_ctest_project}"
194  "${CTEST_BINARY_DIRECTORY}/cdashadmin.txt"
195  STATUS status
196  )
197  list(GET status 0 error_code)
198  list(GET status 1 error_msg)
199  if(error_code)
200  message(FATAL_ERROR "error: Failed to communicate with cdashadmin-web - ${error_msg}")
201  endif()
202  endif()
203 
204 endmacro()
205 
206 macro(check_for_errors)
207 
208  set(_curr_target ${ARGV0})
209  if(build_errors AND _curr_target)
210  # try to remove the stamp file for external projects
211  set(_stamp_file "${CTEST_BINARY_DIRECTORY}/ep/src/${_curr_target}-stamp/${_curr_target}-configure")
212  if(EXISTS "${_stamp_file}")
213  file(REMOVE "${_stamp_file}")
214  endif()
215  endif()
216 
217  if(build_errors OR test_errors)
218  finalize_submission()
219  # this should return from run_ctest()
220  return()
221  endif()
222 
223 endmacro()
224 
225 #---------------------------------------------------------------------
226 # run_ctest macro
227 #---------------------------------------------------------------------
228 function(run_ctest)
229 
230  set(build_warnings 0)
231  set(build_errors 0)
232  set(test_errors 0)
233 
234  ctest_start(${model})
235 
236  ctest_update(SOURCE "${CTEST_CHECKOUT_DIR}" RETURN_VALUE res)
237 
238  if(res LESS 0)
239  # update error
240  math(EXPR build_errors "${build_errors} + 1")
241  endif()
242 
243  set(force_build ${initial_force_build})
244 
245  # Check if a forced run was requested
246  set(cdash_remove_rerun_url )
247  if(CDASH_ADMIN_URL_PREFIX)
248  set(cdash_rerun_url "${CDASH_ADMIN_URL_PREFIX}/rerun/${_build_name_escaped}")
249  set(cdash_remove_rerun_url "${CDASH_ADMIN_URL_PREFIX}/rerun/rerun.php?name=${_build_name_escaped}&remove=1")
250  file(DOWNLOAD
251  "${cdash_rerun_url}"
252  "${CTEST_BINARY_DIRECTORY}/tmp.txt"
253  STATUS status
254  )
255  list(GET status 0 error_code)
256  file(READ "${CTEST_BINARY_DIRECTORY}/tmp.txt" rerun_content LIMIT 1)
257  if(NOT error_code AND NOT rerun_content)
258  set(force_build 1)
259  endif()
260  endif()
261 
262  if(COMMAND MITK_OVERRIDE_FORCE_BUILD)
263  MITK_OVERRIDE_FORCE_BUILD(force_build)
264  endif()
265 
266  # force a build if this is the first run and the build dir is empty
267  if(NOT EXISTS "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt")
268  message("First time build - Initialize CMakeCache.txt")
269  set(res 1)
270 
271  # Write initial cache.
272  if(NOT DEFINED BUILD_TESTING)
273  set(BUILD_TESTING ON)
274  endif()
275 
276  # Write initial cache.
277  file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" "
278 CTEST_USE_LAUNCHERS:BOOL=${CTEST_USE_LAUNCHERS}
279 CTEST_PROJECT_ADDITIONAL_TARGETS:INTERNAL=${CTEST_PROJECT_ADDITIONAL_TARGETS}
280 BUILD_TESTING:BOOL=${BUILD_TESTING}
281 MITK_CTEST_SCRIPT_MODE:STRING=${SCRIPT_MODE}
282 CMAKE_BUILD_TYPE:STRING=${CTEST_BUILD_CONFIGURATION}
283 WITH_COVERAGE:BOOL=${WITH_COVERAGE}
284 MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL:STRING=${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}
285 ${INITIAL_CMAKECACHE_OPTIONS}
286 ")
287  endif()
288 
289  if(res GREATER 0 OR force_build)
290 
291  # Clear the forced rerun request
292  if(CDASH_ADMIN_URL_PREFIX AND cdash_remove_rerun_url)
293  file(DOWNLOAD "${cdash_remove_rerun_url}" "${CTEST_BINARY_DIRECTORY}/tmp.txt")
294  file(REMOVE "${CTEST_BINARY_DIRECTORY}/tmp.txt")
295  endif()
296 
297  if(CTEST_PROJECT_NAME_SUPERBUILD)
298  set(ctest_project_name_orig ${CTEST_PROJECT_NAME})
299  set(CTEST_PROJECT_NAME ${CTEST_PROJECT_NAME_SUPERBUILD})
300  endif()
301 
302  message("----------- [ Configure SuperBuild ] -----------")
303 
304  set_property(GLOBAL PROPERTY SubProject SuperBuild)
305  set_property(GLOBAL PROPERTY Label SuperBuild)
306 
307  ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res OPTIONS "${SUPERBUILD_CONFIG_OPTIONS}")
308 
309  if(res)
310  math(EXPR build_errors "${build_errors} + 1")
311  endif()
312 
313  # Project.xml is generated during the superbuild configure step
314  ctest_submit(FILES "${CTEST_BINARY_DIRECTORY}/Project.xml" RETRY_DELAY 3 RETRY_COUNT 3)
315 
316  ctest_read_custom_files("${CTEST_BINARY_DIRECTORY}")
317 
318  ctest_submit(PARTS Configure RETRY_DELAY 3 RETRY_COUNT 3)
319 
320  # submit the update results *after* the submitting the Configure info,
321  # otherwise CDash is somehow confused and cannot add the update info
322  # to the superbuild project
323  ctest_submit(PARTS Update RETRY_DELAY 3 RETRY_COUNT 3)
324 
325  check_for_errors()
326 
327  # To get CTEST_PROJECT_SUBPROJECTS and CTEST_PROJECT_EXTERNALS definition
328  include("${CTEST_BINARY_DIRECTORY}/CTestConfigSubProject.cmake")
329 
330  # Read in a list of super-build targets (SUPERBUILD_TARGETS). If an error
331  # occurs in one of the listed projects, the ctest superbuild make step stops
332  # and the error is reported in the dashboard. If this variable would be empty
333  # the errors are still reported but make would keep building external
334  # projects which leads to potentially more errors because of dependencies.
335  set(MITK_SUPERBUILD_TARGETS_FILE "${CTEST_BINARY_DIRECTORY}/SuperBuildTargets.cmake")
336  if(EXISTS "${MITK_SUPERBUILD_TARGETS_FILE}")
337  include("${MITK_SUPERBUILD_TARGETS_FILE}")
338  endif()
339 
340  # Build top level (either all or the supplied targets at
341  # superbuild level
342  if(SUPERBUILD_TARGETS)
343  foreach(superbuild_target ${SUPERBUILD_TARGETS})
344 
345  message("----------- [ Build ${superbuild_target} - SuperBuild ] -----------")
346  func_build_target(${superbuild_target} "${CTEST_BINARY_DIRECTORY}")
347  check_for_errors(${superbuild_target})
348 
349  # runs only tests that have a LABELS property matching "SuperBuild"
350  func_test("SuperBuild" "${CTEST_BINARY_DIRECTORY}")
351  check_for_errors()
352  endforeach()
353 
354  # HACK Unfortunately ctest_coverage ignores the build argument, back-up the original dirs
355  file(READ "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" old_coverage_dirs)
356 
357  # explicitly build requested external projects as subprojects
358  foreach(external_project_with_build_dir ${CTEST_PROJECT_EXTERNALS})
359 
360  string(REPLACE "^^" ";" external_project_with_build_dir_list "${external_project_with_build_dir}")
361  list(GET external_project_with_build_dir_list 0 external_project_name)
362  list(GET external_project_with_build_dir_list 1 external_project_builddir)
363 
364  set_property(GLOBAL PROPERTY SubProject ${external_project_name})
365  set_property(GLOBAL PROPERTY Label ${external_project_name})
366 
367  message("----------- [ Build ${external_project_name} ] -----------")
368 
369  func_build_target("${external_project_name}" "${CTEST_BINARY_DIRECTORY}")
370  check_for_errors()
371 
372  # HACK Unfortunately ctest_coverage ignores the build argument, try to force it...
373  file(READ "${CTEST_BINARY_DIRECTORY}/${external_project_builddir}/CMakeFiles/TargetDirectories.txt" mitk_build_coverage_dirs)
374  file(APPEND "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${mitk_build_coverage_dirs}")
375 
376  message("----------- [ Test ${external_project_name} ] -----------")
377 
378  # runs only tests that have a LABELS property matching "${external_project_name}"
379  func_test(${external_project_name} "${CTEST_BINARY_DIRECTORY}/${external_project_builddir}")
380 
381  # restore old coverage dirs
382  file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${old_coverage_dirs}")
383 
384  endforeach()
385 
386  # switch back to SuperBuild label
387  set_property(GLOBAL PROPERTY SubProject SuperBuild)
388  set_property(GLOBAL PROPERTY Label SuperBuild)
389 
390  message("----------- [ Finish SuperBuild ] -----------")
391  else()
392  message("----------- [ Build SuperBuild ] -----------")
393  endif()
394 
395  # build everything at superbuild level which has not yet been built
396  func_build_target("" "${CTEST_BINARY_DIRECTORY}")
397  check_for_errors()
398 
399  # runs only tests that have a LABELS property matching "SuperBuild"
400  #func_test("SuperBuild" "${CTEST_BINARY_DIRECTORY}")
401 
402  set(build_dir "${CTEST_BINARY_DIRECTORY}/${PROJECT_BUILD_DIR}")
403  if(CTEST_PROJECT_NAME_SUPERBUILD)
404  set(CTEST_PROJECT_NAME ${ctest_project_name_orig})
405  endif()
406 
407  message("----------- [ Configure ${build_dir} ] -----------")
408  # Configure target
409  ctest_configure(BUILD "${build_dir}"
410  OPTIONS "-DCTEST_USE_LAUNCHERS=${CTEST_USE_LAUNCHERS}"
411  RETURN_VALUE res
412  )
413  ctest_read_custom_files("${CTEST_BINARY_DIRECTORY}")
414  ctest_submit(PARTS Configure RETRY_DELAY 3 RETRY_COUNT 3)
415 
416  if(res)
417  math(EXPR build_errors "${build_errors} + 1")
418  endif()
419  check_for_errors()
420 
421  foreach(subproject ${CTEST_PROJECT_SUBPROJECTS})
422  set_property(GLOBAL PROPERTY SubProject ${subproject})
423  set_property(GLOBAL PROPERTY Label ${subproject})
424 
425  if(subproject MATCHES "Unlabeled")
426  message("----------- [ Build All (Unlabeled) ] -----------")
427  # Build target
428  func_build_target("" "${build_dir}")
429  else()
430  message("----------- [ Build ${subproject} ] -----------")
431  # Build target
432  func_build_target(${subproject} "${build_dir}")
433  endif()
434  check_for_errors()
435  endforeach()
436 
437  # HACK Unfortunately ctest_coverage ignores the build argument, try to force it...
438  file(READ ${build_dir}/CMakeFiles/TargetDirectories.txt mitk_build_coverage_dirs)
439  file(APPEND "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${mitk_build_coverage_dirs}")
440 
441  foreach(subproject ${CTEST_PROJECT_SUBPROJECTS})
442  set_property(GLOBAL PROPERTY SubProject ${subproject})
443  set_property(GLOBAL PROPERTY Label ${subproject})
444  message("----------- [ Test ${subproject} ] -----------")
445 
446  # runs only tests that have a LABELS property matching "${subproject}"
447  func_test(${subproject} "${build_dir}")
448  endforeach()
449 
450  # Build any additional target which is not build by "all"
451  # i.e. the "package" target
452  if(CTEST_PROJECT_ADDITIONAL_TARGETS)
453  foreach(additional_target ${CTEST_PROJECT_ADDITIONAL_TARGETS})
454  set_property(GLOBAL PROPERTY SubProject ${additional_target})
455  set_property(GLOBAL PROPERTY Label ${additional_target})
456 
457  message("----------- [ Build ${additional_target} ] -----------")
458  func_build_target(${additional_target} "${build_dir}")
459  check_for_errors()
460 
461  message("----------- [ Test ${additional_target} ] -----------")
462  # runs only tests that have a LABELS property matching "${subproject}"
463  func_test(${additional_target} "${build_dir}")
464  endforeach()
465  endif()
466 
467  if(WITH_DOCUMENTATION)
468  message("----------- [ Build Documentation ] -----------")
469  set(ctest_use_launchers_orig ${CTEST_USE_LAUNCHERS})
470  set(CTEST_USE_LAUNCHERS 0)
471  # Build Documentation target
472  set_property(GLOBAL PROPERTY SubProject Documentation)
473  set_property(GLOBAL PROPERTY Label Documentation)
474  func_build_target("doc" "${build_dir}")
475  set(CTEST_USE_LAUNCHERS ${ctest_use_launchers_orig})
476  endif()
477 
478  set_property(GLOBAL PROPERTY SubProject SuperBuild)
479  set_property(GLOBAL PROPERTY Label SuperBuild)
480 
481  # Global coverage ...
482  if(WITH_COVERAGE AND CTEST_COVERAGE_COMMAND)
483  message("----------- [ Global coverage ] -----------")
484  ctest_coverage(BUILD "${build_dir}" APPEND)
485  ctest_submit(PARTS Coverage RETRY_DELAY 3 RETRY_COUNT 3)
486  endif()
487 
488  # Global dynamic analysis ...
489  if(WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND)
490  message("----------- [ Global memcheck ] -----------")
491  ctest_memcheck(BUILD "${build_dir}")
492  ctest_submit(PARTS MemCheck RETRY_DELAY 3 RETRY_COUNT 3)
493  endif()
494 
495  check_for_errors()
496  finalize_submission()
497 
498  endif()
499 
500  # Clear the CTEST_CHECKOUT_COMMAND variable to prevent continuous clients
501  # to try to checkout again
502  set(CTEST_CHECKOUT_COMMAND "")
503 
504 endfunction()
505 
506 if(SCRIPT_MODE STREQUAL "continuous")
507  while(1)
508  run_ctest()
509  # Loop no faster than once every 5 minutes
510  message("Wait for 5 minutes ...")
511  ctest_sleep(300)
512  endwhile()
513 else()
514  run_ctest()
515 endif()
516