You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1678 lines
56 KiB
1678 lines
56 KiB
# @HEADER
|
|
# ************************************************************************
|
|
#
|
|
# TriBITS: Tribal Build, Integrate, and Test System
|
|
# Copyright 2013 Sandia Corporation
|
|
#
|
|
# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
|
# the U.S. Government retains certain rights in this software.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are
|
|
# met:
|
|
#
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
#
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
#
|
|
# 3. Neither the name of the Corporation nor the names of the
|
|
# contributors may be used to endorse or promote products derived from
|
|
# this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
|
|
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
|
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
#
|
|
# ************************************************************************
|
|
# @HEADER
|
|
|
|
|
|
include(TribitsGetCDashUrlsInsideCTestS)
|
|
|
|
|
|
# Wrapper used for unit testing purposes
|
|
#
|
|
macro(extrarepo_execute_process_wrapper)
|
|
if (NOT CTEST_DEPENDENCY_HANDLING_UNIT_TESTING)
|
|
execute_process(${ARGN}
|
|
RESULT_VARIABLE EXTRAREPO_EXECUTE_PROCESS_WRAPPER_RTN_VAL)
|
|
if (NOT EXTRAREPO_EXECUTE_PROCESS_WRAPPER_RTN_VAL STREQUAL "0")
|
|
message(SEND_ERROR
|
|
"Error: execute_process(${ARGN}) returned"
|
|
" '${EXTRAREPO_EXECUTE_PROCESS_WRAPPER_RTN_VAL}'")
|
|
endif()
|
|
else()
|
|
message("execute_process(${ARGN})")
|
|
endif()
|
|
endmacro()
|
|
|
|
|
|
# Update an existing git repo
|
|
#
|
|
function(tribits_update_git_extrarepo GIT_EXE EXTRAREPO_SRC_DIR)
|
|
|
|
set(EXTRAREPO_FETCH_OUT_FILE
|
|
"${CTEST_BINARY_DIRECTORY}/${EXTRAREPO_NAME_IN}.fetch.out")
|
|
set(EXTRAREPO_CLEAN_OUT_FILE
|
|
"${CTEST_BINARY_DIRECTORY}/${EXTRAREPO_NAME_IN}.clean.out")
|
|
set(EXTRAREPO_RESET_OUT_FILE
|
|
"${CTEST_BINARY_DIRECTORY}/${EXTRAREPO_NAME_IN}.reset.out")
|
|
set(EXTRAREPO_SET_BRANCH_OUT_FILE
|
|
"${CTEST_BINARY_DIRECTORY}/${EXTRAREPO_NAME_IN}.set_branch.out")
|
|
|
|
set(FETCH_CMND_ARGS
|
|
COMMAND "${GIT_EXE}" fetch ${${PROJECT_NAME}_GIT_REPOSITORY_REMOTE}
|
|
TIMEOUT 600 # seconds
|
|
WORKING_DIRECTORY "${EXTRAREPO_SRC_DIR}"
|
|
OUTPUT_FILE "${EXTRAREPO_FETCH_OUT_FILE}" )
|
|
set(CLEAN_CMND_ARGS
|
|
COMMAND "${GIT_EXE}" clean -fdx
|
|
WORKING_DIRECTORY "${EXTRAREPO_SRC_DIR}"
|
|
OUTPUT_FILE "${EXTRAREPO_CLEAN_OUT_FILE}" )
|
|
set(RESET_CMND_ARGS
|
|
COMMAND "${GIT_EXE}" reset --hard HEAD
|
|
WORKING_DIRECTORY "${EXTRAREPO_SRC_DIR}"
|
|
OUTPUT_FILE "${EXTRAREPO_RESET_OUT_FILE}" )
|
|
if (${PROJECT_NAME}_EXTRAREPOS_BRANCH)
|
|
set(SET_BRANCH_CMND_ARGS
|
|
COMMAND "${GIT_EXE}" checkout -B ${${PROJECT_NAME}_EXTRAREPOS_BRANCH}
|
|
--track ${${PROJECT_NAME}_GIT_REPOSITORY_REMOTE}/${${PROJECT_NAME}_EXTRAREPOS_BRANCH}
|
|
WORKING_DIRECTORY "${EXTRAREPO_SRC_DIR}"
|
|
OUTPUT_FILE "${EXTRAREPO_SET_BRANCH_OUT_FILE}" )
|
|
ELSE ()
|
|
set(SET_BRANCH_CMND_ARGS
|
|
COMMAND "${GIT_EXE}" reset --hard "@{u}"
|
|
WORKING_DIRECTORY "${EXTRAREPO_SRC_DIR}"
|
|
OUTPUT_FILE "${EXTRAREPO_SET_BRANCH_OUT_FILE}" )
|
|
endif()
|
|
|
|
extrarepo_execute_process_wrapper(${FETCH_CMND_ARGS})
|
|
extrarepo_execute_process_wrapper(${CLEAN_CMND_ARGS})
|
|
extrarepo_execute_process_wrapper(${RESET_CMND_ARGS})
|
|
extrarepo_execute_process_wrapper(${SET_BRANCH_CMND_ARGS})
|
|
|
|
endfunction()
|
|
|
|
|
|
# Update or clone a single extra repo
|
|
#
|
|
function(tribits_clone_or_update_extrarepo EXTRAREPO_NAME_IN EXTRAREPO_DIR_IN
|
|
EXTRAREPO_REPOTYPE_IN EXTRAREPO_REPOURL_IN
|
|
)
|
|
|
|
#message("TRIBITS_CLONE_OR_UPDATE_EXTRAREPO: ${EXTRAREPO_NAME_IN} ${EXTRAREPO_REPOURL_IN}")
|
|
|
|
set(EXTRAREPO_SRC_DIR "${${PROJECT_NAME}_SOURCE_DIRECTORY}/${EXTRAREPO_DIR_IN}")
|
|
#print_var(EXTRAREPO_SRC_DIR)
|
|
|
|
set(EXTRAREPO_CLONE_OUT_FILE
|
|
"${CTEST_BINARY_DIRECTORY}/${EXTRAREPO_NAME_IN}.clone.out")
|
|
set(EXTRAREPO_CHECKOUT_OUT_FILE
|
|
"${CTEST_BINARY_DIRECTORY}/${EXTRAREPO_NAME_IN}.checkout.out")
|
|
|
|
if (NOT EXISTS "${EXTRAREPO_SRC_DIR}")
|
|
|
|
message("\n${EXTRAREPO_NAME_IN}: Doing initial ${EXTRAREPO_REPOTYPE_IN}"
|
|
" clone/checkout from URL '${EXTRAREPO_REPOURL_IN}' to dir '${EXTRAREPO_DIR_IN}' ...")
|
|
|
|
# Set the command to clone
|
|
if (${EXTRAREPO_REPOTYPE_IN} STREQUAL GIT)
|
|
if (${PROJECT_NAME}_EXTRAREPOS_BRANCH)
|
|
set(CHECKOUT_BRANCH_ARG -b ${${PROJECT_NAME}_EXTRAREPOS_BRANCH})
|
|
else()
|
|
set(CHECKOUT_BRANCH_ARG)
|
|
endif()
|
|
set(CLONE_CMND_ARGS
|
|
COMMAND "${GIT_EXECUTABLE}" clone
|
|
${CHECKOUT_BRANCH_ARG} -o ${${PROJECT_NAME}_GIT_REPOSITORY_REMOTE}
|
|
"${EXTRAREPO_REPOURL}" ${EXTRAREPO_DIR_IN}
|
|
WORKING_DIRECTORY "${${PROJECT_NAME}_SOURCE_DIRECTORY}"
|
|
OUTPUT_FILE "${EXTRAREPO_CLONE_OUT_FILE}" )
|
|
else()
|
|
message(SEND_ERROR
|
|
"Error, Invalid EXTRAREPO_REPOTYPE_IN='${EXTRAREPO_REPOTYPE_IN}'!")
|
|
endif()
|
|
|
|
# Do the clone
|
|
extrarepo_execute_process_wrapper(${CLONE_CMND_ARGS})
|
|
|
|
else()
|
|
|
|
message("\n${EXTRAREPO_NAME_IN}: Doing ${EXTRAREPO_REPOTYPE_IN} update"
|
|
" from URL '${EXTRAREPO_REPOURL_IN}' to dir '${EXTRAREPO_SRC_DIR}' ...")
|
|
|
|
endif()
|
|
|
|
if (${EXTRAREPO_REPOTYPE_IN} STREQUAL GIT)
|
|
# Always update the git repo, even after a clone. See
|
|
# tribits_ctest_driver() documentation.
|
|
tribits_update_git_extrarepo("${GIT_EXECUTABLE}" "${EXTRAREPO_SRC_DIR}")
|
|
else()
|
|
message(SEND_ERROR
|
|
"Error, Invalid EXTRAREPO_REPOTYPE_IN='${EXTRAREPO_REPOTYPE_IN}'!")
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
|
|
# Clone or update all of the extra repos and put them on the right branch.
|
|
#
|
|
# NOTE: The base repo is cloned by ctest_start() and updated by ctest_update()
|
|
# before calling this function. This function only operates on the extra
|
|
# repos.
|
|
#
|
|
function(tribits_clone_or_update_extra_repos CTEST_UPDATE_RETURN_VAL
|
|
UPDATE_FAILED_VAR_OUT
|
|
)
|
|
|
|
set(UPDATE_FAILED FALSE)
|
|
|
|
if (${PROJECT_NAME}_EXTRAREPOS_BRANCH)
|
|
message("For extra repos, doing switch to branch ${${PROJECT_NAME}_EXTRAREPOS_BRANCH}")
|
|
endif()
|
|
|
|
set(EXTRAREPO_IDX 0)
|
|
foreach(EXTRAREPO_NAME ${${PROJECT_NAME}_ALL_EXTRA_REPOSITORIES})
|
|
list(GET ${PROJECT_NAME}_ALL_EXTRA_REPOSITORIES_DIRS ${EXTRAREPO_IDX}
|
|
EXTRAREPO_DIR )
|
|
list(GET ${PROJECT_NAME}_ALL_EXTRA_REPOSITORIES_VCTYPES ${EXTRAREPO_IDX}
|
|
EXTRAREPO_REPOTYPE )
|
|
list(GET ${PROJECT_NAME}_ALL_EXTRA_REPOSITORIES_REPOURLS ${EXTRAREPO_IDX}
|
|
EXTRAREPO_REPOURL )
|
|
tribits_clone_or_update_extrarepo( ${EXTRAREPO_NAME} ${EXTRAREPO_DIR}
|
|
${EXTRAREPO_REPOTYPE} ${EXTRAREPO_REPOURL} )
|
|
# ToDo: Detect and return failure in cloning or updating extra repos!
|
|
math(EXPR EXTRAREPO_IDX "${EXTRAREPO_IDX}+1")
|
|
endforeach()
|
|
|
|
set(${UPDATE_FAILED_VAR_OUT} ${UPDATE_FAILED} PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
|
|
# Create the Updates.txt file
|
|
#
|
|
function(tribits_create_repo_updates_file)
|
|
extrarepo_execute_process_wrapper(
|
|
COMMAND ${PYTHON_EXECUTABLE}
|
|
${GITDIST_EXE} --dist-no-color
|
|
log "--pretty=format:%h: %s%nAuthor: %an <%ae>%nDate: %ad%n"
|
|
--name-status -C ORIG_HEAD..HEAD
|
|
WORKING_DIRECTORY ${CTEST_SOURCE_DIRECTORY}
|
|
OUTPUT_FILE "${CTEST_BINARY_DIRECTORY}/Updates.txt"
|
|
)
|
|
endfunction()
|
|
|
|
|
|
# Select the set of extra repositories
|
|
#
|
|
macro(tribits_setup_extrarepos)
|
|
|
|
if (EXISTS "${${PROJECT_NAME}_EXTRAREPOS_FILE}" )
|
|
# Repos many not already exist because we have not cloned them yet!
|
|
set(${PROJECT_NAME}_CHECK_EXTRAREPOS_EXIST FALSE)
|
|
tribits_get_and_process_extra_repositories_lists()
|
|
else()
|
|
message("${${PROJECT_NAME}_EXTRAREPOS_FILE} does not exist,"
|
|
" skipping extra repositories.")
|
|
endif()
|
|
|
|
endmacro()
|
|
|
|
|
|
# Select the list of packages
|
|
#
|
|
# OUTPUT: Sets ${PROJECT_NAME}_DEFAULT_PACKAGES
|
|
#
|
|
# NOTE: This macro is used to clean up the main tribits_ctest_driver()
|
|
# macro.
|
|
#
|
|
macro(tribits_setup_packages)
|
|
|
|
include(TribitsPrintDependencyInfo)
|
|
include(TribitsWriteXmlDependenciesFiles)
|
|
|
|
# Here, we must point into the source tree just cloned (or updated)
|
|
# and not the "driver" source dir tree for two reasons. First, the
|
|
# list of core packages may be more recent in what was checked out.
|
|
# Second, the extra repos do not even exist in the "driver" source
|
|
# tree.
|
|
|
|
set(${PROJECT_NAME}_ASSERT_DEFINED_DEPENDENCIES OFF)
|
|
set(${PROJECT_NAME}_OUTPUT_DEPENDENCY_FILES FALSE)
|
|
if (CTEST_GENERATE_OUTER_DEPS_XML_OUTPUT_FILE)
|
|
set(${PROJECT_NAME}_DEPS_XML_OUTPUT_FILE
|
|
"${PROJECT_BINARY_DIR}/${${PROJECT_NAME}_PACKAGE_DEPS_XML_FILE_NAME}")
|
|
else()
|
|
set(${PROJECT_NAME}_DEPS_XML_OUTPUT_FILE)
|
|
endif()
|
|
if (CTEST_SUBMIT_CDASH_SUBPROJECTS_DEPS_FILE)
|
|
set(${PROJECT_NAME}_CDASH_DEPS_XML_OUTPUT_FILE
|
|
"${PROJECT_BINARY_DIR}/${${PROJECT_NAME}_CDASH_SUBPROJECT_DEPS_XML_FILE_NAME}" )
|
|
else()
|
|
set(${PROJECT_NAME}_CDASH_DEPS_XML_OUTPUT_FILE)
|
|
endif()
|
|
set(${PROJECT_NAME}_DEPS_HTML_OUTPUT_FILE)
|
|
|
|
# Don't ignore missing repos by default. This will allow processing to
|
|
# continue but this outer CTest script will fail (thereby sending a CDash
|
|
# email from the TDD system). However, when we configure actual packages,
|
|
# we do set this to TRUE so that the package configures will not fail due to
|
|
# missing extra repositories.
|
|
set_default_and_from_env(${PROJECT_NAME}_IGNORE_MISSING_EXTRA_REPOSITORIES FALSE)
|
|
set_default_and_from_env(${PROJECT_NAME}_PRE_REPOSITORIES "")
|
|
set_default_and_from_env(${PROJECT_NAME}_EXTRA_REPOSITORIES "")
|
|
split("${${PROJECT_NAME}_PRE_REPOSITORIES}" "," ${PROJECT_NAME}_PRE_REPOSITORIES)
|
|
split("${${PROJECT_NAME}_EXTRA_REPOSITORIES}" "," ${PROJECT_NAME}_EXTRA_REPOSITORIES)
|
|
|
|
tribits_read_in_native_repositories()
|
|
tribits_combine_native_and_extra_repos()
|
|
tribits_read_all_project_deps_files_create_deps_graph()
|
|
tribits_print_initial_dependency_info()
|
|
tribits_write_xml_dependency_files()
|
|
|
|
# When we get here, we will have the basic dependency structure set up
|
|
# with only defaults set
|
|
|
|
# Set this to "" so that it can be defined in enable_modified_packages_only()
|
|
set(${PROJECT_NAME}_ENABLE_ALL_PACKAGES "")
|
|
|
|
endmacro()
|
|
|
|
|
|
macro(enable_package_if_not_explicitly_excluded TRIBITS_PACKAGE)
|
|
if ("${${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}}" STREQUAL "")
|
|
message("Enabling explicitly set package ${TRIBITS_PACKAGE} ...")
|
|
set(${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE} ON)
|
|
elseif(NOT ${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE})
|
|
if (${TRIBITS_PACKAGE}_EXPLICITY_EXCLUDED)
|
|
message("NOT enabling explicitly set package ${TRIBITS_PACKAGE} since it was explicitly excluded!")
|
|
else()
|
|
message("Enabling explicitly set package ${TRIBITS_PACKAGE} which was default or otherwise disabed!")
|
|
set(${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE} ON)
|
|
endif()
|
|
else()
|
|
message("Explicitly set package ${TRIBITS_PACKAGE} is already enabled?")
|
|
endif()
|
|
endmacro()
|
|
|
|
|
|
# Select packages set by the input
|
|
#
|
|
macro(enable_user_selected_packages)
|
|
|
|
# 1) Set the enables for packages
|
|
|
|
if (${PROJECT_NAME}_PACKAGE_ENABLES_FILE)
|
|
message("Setting package enables specified in file"
|
|
" '${${PROJECT_NAME}_PACKAGE_ENABLES_FILE}'")
|
|
include(${${PROJECT_NAME}_PACKAGE_ENABLES_FILE})
|
|
elseif (NOT "${${PROJECT_NAME}_PACKAGES_USER_SELECTED}" STREQUAL "")
|
|
foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_PACKAGES_USER_SELECTED})
|
|
enable_package_if_not_explicitly_excluded(${TRIBITS_PACKAGE})
|
|
endforeach()
|
|
else()
|
|
message("Setting ${PROJECT_NAME}_ENABLE_ALL_PACKAGES=ON since"
|
|
" ${PROJECT_NAME}_PACKAGES_USER_SELECTED='${${PROJECT_NAME}_PACKAGES_USER_SELECTED}'")
|
|
set(${PROJECT_NAME}_ENABLE_ALL_PACKAGES ON)
|
|
endif()
|
|
|
|
# 2) Set extra package enables from ${PROJECT_NAME}_ADDITIONAL_PACKAGES
|
|
|
|
foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_ADDITIONAL_PACKAGES})
|
|
enable_package_if_not_explicitly_excluded(${TRIBITS_PACKAGE})
|
|
endforeach()
|
|
|
|
endmacro()
|
|
|
|
|
|
# Extract the list of changed files for the main repo on put into an
|
|
# modified files file.
|
|
#
|
|
macro(tribits_get_modified_files WORKING_DIR_IN MODIFIED_FILES_FILE_NAME_IN)
|
|
set(CMND_ARGS
|
|
COMMAND "${GIT_EXECUTABLE}" diff --name-only ORIG_HEAD..HEAD
|
|
WORKING_DIRECTORY "${WORKING_DIR_IN}"
|
|
OUTPUT_FILE ${MODIFIED_FILES_FILE_NAME_IN}
|
|
#OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
if (NOT CTEST_DEPENDENCY_HANDLING_UNIT_TESTING)
|
|
execute_process(${CMND_ARGS})
|
|
else()
|
|
message("execute_process(${CMND_ARGS})")
|
|
endif()
|
|
endmacro()
|
|
|
|
|
|
# Select only packages that are modified or failed in the last CI iteration
|
|
#
|
|
macro(enable_only_modified_packages)
|
|
|
|
#
|
|
# A) Get the list of changed packages
|
|
#
|
|
|
|
set(MODIFIED_FILES_FILE_NAME "${CTEST_BINARY_DIRECTORY}/modifiedFiles.txt")
|
|
|
|
# A.1) Get changes from main ${PROJECT_NAME} repo
|
|
|
|
tribits_get_modified_files("${CTEST_SOURCE_DIRECTORY}" "${MODIFIED_FILES_FILE_NAME}")
|
|
|
|
# A.2) Get changes from extra repos
|
|
|
|
set(EXTRAREPO_IDX 0)
|
|
foreach(EXTRAREPO_NAME ${${PROJECT_NAME}_ALL_EXTRA_REPOSITORIES})
|
|
|
|
list(GET ${PROJECT_NAME}_ALL_EXTRA_REPOSITORIES_DIRS
|
|
${EXTRAREPO_IDX} EXTRAREPO_DIR )
|
|
list(GET ${PROJECT_NAME}_ALL_EXTRA_REPOSITORIES_HASPKGS
|
|
${EXTRAREPO_IDX} EXTRAREPO_PACKSTAT )
|
|
|
|
# For now, only look for changes if it has packages. Later, we may need
|
|
# to generalize this for the general extra repo case with deeper directory
|
|
# and other VC systems than GIT.
|
|
if (EXTRAREPO_PACKSTAT STREQUAL HASPACKAGES)
|
|
|
|
set(EXTRAREPO_SRC_DIR "${CTEST_SOURCE_DIRECTORY}/${EXTRAREPO_DIR}")
|
|
set(EXTRAREPO_MODIFIED_FILES_FILE_NAME
|
|
"${CTEST_BINARY_DIRECTORY}/modifiedFiles.${EXTRAREPO_NAME}.txt")
|
|
|
|
tribits_get_modified_files("${EXTRAREPO_SRC_DIR}"
|
|
"${EXTRAREPO_MODIFIED_FILES_FILE_NAME}")
|
|
|
|
file(STRINGS ${EXTRAREPO_MODIFIED_FILES_FILE_NAME} EXTRAREPO_MODIFIED_FILES_STR)
|
|
set(EXTRAREPO_FILES_STR "")
|
|
foreach(STR_LINE ${EXTRAREPO_MODIFIED_FILES_STR})
|
|
string(APPEND EXTRAREPO_FILES_STR "${EXTRAREPO_DIR}/${STR_LINE}\n")
|
|
endforeach()
|
|
file(APPEND "${MODIFIED_FILES_FILE_NAME}" ${EXTRAREPO_FILES_STR})
|
|
|
|
endif()
|
|
|
|
math(EXPR EXTRAREPO_IDX "${EXTRAREPO_IDX}+1")
|
|
|
|
endforeach()
|
|
|
|
# A.3) Get the names of the modified packages
|
|
|
|
if (NOT PYTHON_EXECUTABLE)
|
|
message(FATAL_ERROR "Error, Python must be enabled to map from modified"
|
|
" files to packages!")
|
|
endif()
|
|
|
|
if (EXISTS "${MODIFIED_FILES_FILE_NAME}")
|
|
execute_process(
|
|
COMMAND ${PYTHON_EXECUTABLE}
|
|
${${PROJECT_NAME}_TRIBITS_DIR}/ci_support/get-tribits-packages-from-files-list.py
|
|
--files-list-file=${MODIFIED_FILES_FILE_NAME}
|
|
--project-dir=${TRIBITS_PROJECT_ROOT}
|
|
--deps-xml-file=${CTEST_BINARY_DIRECTORY}/${${PROJECT_NAME}_PACKAGE_DEPS_XML_FILE_NAME}
|
|
OUTPUT_VARIABLE MODIFIED_PACKAGES_LIST
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
else()
|
|
set(MODIFIED_PACKAGES_LIST)
|
|
endif()
|
|
|
|
split("${MODIFIED_PACKAGES_LIST}" "," MODIFIED_PACKAGES_LIST)
|
|
print_var(MODIFIED_PACKAGES_LIST)
|
|
|
|
#
|
|
# B) Get the list of packages that failed last CI iteration
|
|
#
|
|
|
|
# NOTE: It is critical to enable and test packages until they pass. If you
|
|
# don't do this, then the package will not show as updated in the above
|
|
# logic. In this case only downstream packages will get enabled. If the
|
|
# failing packages break the downstream packages, this will be bad (for lots
|
|
# of reasons). Therefore, we must enable failing packages from the last CI
|
|
# iteration and keep enabling and testing them until they do pass!
|
|
|
|
if (EXISTS "${FAILED_PACKAGES_FILE_NAME}")
|
|
file(READ "${FAILED_PACKAGES_FILE_NAME}" FAILING_PACKAGES_LIST)
|
|
string(STRIP "${FAILING_PACKAGES_LIST}" FAILING_PACKAGES_LIST)
|
|
print_var(FAILING_PACKAGES_LIST)
|
|
endif()
|
|
|
|
#
|
|
# C) Enable the changed and previously failing packages
|
|
#
|
|
|
|
foreach(TRIBITS_PACKAGE ${MODIFIED_PACKAGES_LIST})
|
|
#print_var(${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE})
|
|
assert_defined(${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE})
|
|
if ("${${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}}" STREQUAL "")
|
|
if (
|
|
${TRIBITS_PACKAGE} STREQUAL "ALL_PACKAGES"
|
|
OR
|
|
${TRIBITS_PACKAGE}_TESTGROUP STREQUAL "PT"
|
|
OR
|
|
(
|
|
${TRIBITS_PACKAGE}_TESTGROUP STREQUAL "ST"
|
|
AND
|
|
${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE
|
|
)
|
|
)
|
|
message("Enabling modified package: ${TRIBITS_PACKAGE}")
|
|
set(${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE} ON)
|
|
else()
|
|
message("NOT enabling modified ST package: ${TRIBITS_PACKAGE}")
|
|
endif()
|
|
else()
|
|
message("Not enabling explicitly disabled modified package: ${TRIBITS_PACKAGE}")
|
|
endif()
|
|
endforeach()
|
|
|
|
if (FAILING_PACKAGES_LIST STREQUAL "ALL_PACKAGES")
|
|
message("Enabling previously failing ALL_PACKAGES")
|
|
set(${PROJECT_NAME}_ENABLE_ALL_PACKAGES ON)
|
|
else()
|
|
foreach(TRIBITS_PACKAGE ${FAILING_PACKAGES_LIST})
|
|
if ("${${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}}" STREQUAL "")
|
|
if (
|
|
${TRIBITS_PACKAGE}_TESTGROUP STREQUAL "PT"
|
|
OR
|
|
(
|
|
${TRIBITS_PACKAGE}_TESTGROUP STREQUAL "ST"
|
|
AND
|
|
${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE
|
|
)
|
|
)
|
|
message("Enabling previously failing package: ${TRIBITS_PACKAGE}")
|
|
set(${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE} ON)
|
|
else()
|
|
message("NOT enabling previously failing ST package: ${TRIBITS_PACKAGE}")
|
|
endif()
|
|
else()
|
|
message("Not enabling explicitly disabled previously"
|
|
" failing package: ${TRIBITS_PACKAGE}")
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
|
|
#
|
|
# D) Print the final status
|
|
#
|
|
|
|
if (${PROJECT_NAME}_ENABLE_ALL_PACKAGES)
|
|
if (NOT ${PROJECT_NAME}_CTEST_DO_ALL_AT_ONCE)
|
|
message(FATAL_ERROR
|
|
"Error, failing 'ALL_PACKAGES' only allowed with all-at-once mode!")
|
|
endif()
|
|
message("\nDirectly modified or failing non-disabled packages that need"
|
|
" to be tested: ALL_PACKAGES")
|
|
else()
|
|
tribits_print_package_list_enable_status(
|
|
"\nDirectly modified or failing non-disabled packages that need to be tested"
|
|
INTERNAL ON NONEMPTY )
|
|
endif()
|
|
|
|
endmacro()
|
|
|
|
|
|
# Exclude disabled packages from ${PROJECT_NAME}_EXCLUDE_PACKAGES
|
|
#
|
|
# NOTE: These disables need to dominate over the above enables so this code is
|
|
# after all the enable code has run
|
|
#
|
|
macro(disable_excluded_packages)
|
|
foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_EXCLUDE_PACKAGES})
|
|
message("Disabling excluded package ${TRIBITS_PACKAGE} ...")
|
|
set(${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE} OFF)
|
|
set(${TRIBITS_PACKAGE}_EXPLICITY_EXCLUDED TRUE)
|
|
endforeach()
|
|
endmacro()
|
|
|
|
|
|
# Remove packages that are only implicitly enabled but don't have tests
|
|
# enabled.
|
|
#
|
|
macro(select_final_set_of_packages_to_directly_test)
|
|
|
|
set(${PROJECT_NAME}_PACKAGES_TO_DIRECTLY_TEST)
|
|
|
|
foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES})
|
|
|
|
set(PROCESS_THE_PACKAGE FALSE)
|
|
|
|
if (${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}
|
|
AND ${TRIBITS_PACKAGE}_ENABLE_TESTS
|
|
)
|
|
set(PROCESS_THE_PACKAGE TRUE)
|
|
elseif (${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}
|
|
AND CTEST_EXPLICITLY_ENABLE_IMPLICITLY_ENABLED_PACKAGES
|
|
)
|
|
set(PROCESS_THE_PACKAGE TRUE)
|
|
endif()
|
|
|
|
if(PROCESS_THE_PACKAGE)
|
|
append_set(${PROJECT_NAME}_PACKAGES_TO_DIRECTLY_TEST ${TRIBITS_PACKAGE})
|
|
endif()
|
|
|
|
endforeach()
|
|
|
|
endmacro()
|
|
|
|
|
|
# Set mapping of labels to subprojects (i.e. TriBITS packages) for CDash.
|
|
#
|
|
# NOTE: Unlike for the inner CMake configure, only subprojects that are
|
|
# explicitly tested will be marked as a CDash subproject. This limits the
|
|
# rows in CDash. This does not seem to be a problem for when running ctest
|
|
# locally. When run locally, ctest will just report aggregated times for
|
|
# subprojects that have 1 or more tests. Not true for CDash.
|
|
#
|
|
macro(tribits_ctest_driver_set_labels_to_subprojects_mapping)
|
|
set(CTEST_LABELS_FOR_SUBPROJECTS)
|
|
foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_PACKAGES_TO_DIRECTLY_TEST})
|
|
list(APPEND CTEST_LABELS_FOR_SUBPROJECTS ${TRIBITS_PACKAGE})
|
|
endforeach()
|
|
endmacro()
|
|
|
|
|
|
# Select the default generator.
|
|
#
|
|
macro(select_default_generator)
|
|
# When the build tree is known and exists, use
|
|
# its generator.
|
|
set(DEFAULT_GENERATOR "DID NOT SET!")
|
|
if(EXISTS "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt")
|
|
file(STRINGS "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt"
|
|
line REGEX "^CMAKE_GENERATOR:" LIMIT_COUNT 1)
|
|
if("${line}" MATCHES "=(.+)$")
|
|
set(DEFAULT_GENERATOR "${CMAKE_MATCH_1}")
|
|
endif()
|
|
else()
|
|
set(DEFAULT_GENERATOR "Unix Makefiles")
|
|
endif()
|
|
endmacro()
|
|
|
|
|
|
# Call INITIALIZE_ERROR_QUEUE once at the top of TRIBITS_CTEST_DRIVER
|
|
#
|
|
macro(initialize_error_queue)
|
|
set(TRIBITS_CTEST_DRIVER_ERROR_QUEUE "")
|
|
endmacro()
|
|
|
|
|
|
# QUEUE_ERROR should be called only for errors that are not already reported to
|
|
# the dashboard in some other way. For example, if calling ctest_submit fails,
|
|
# then that failure does NOT show up on the dashboard, so it is appropriate to
|
|
# call QUEUE_ERROR for that case. For a build error or test failure, it is NOT
|
|
# appropriate to call QUEUE_ERROR because those already show up on the
|
|
# dashboard (assuming a good ctest_submit...)
|
|
#
|
|
# When adding more callers of QUEUE_ERROR, just make sure that it does not
|
|
# duplicate an existing/reported dashboard failure.
|
|
#
|
|
macro(queue_error err_msg)
|
|
set(TRIBITS_CTEST_DRIVER_ERROR_QUEUE
|
|
${TRIBITS_CTEST_DRIVER_ERROR_QUEUE} "${err_msg}")
|
|
endmacro()
|
|
|
|
|
|
# Call report_queued_errors() once at the bottom of tribits_ctest_driver()
|
|
#
|
|
macro(report_queued_errors)
|
|
if ("${TRIBITS_CTEST_DRIVER_ERROR_QUEUE}" STREQUAL "")
|
|
message("TRIBITS_CTEST_DRIVER_ERROR_QUEUE is empty. All is well.")
|
|
else()
|
|
message("ERROR: TRIBITS_CTEST_DRIVER_ERROR_QUEUE reports the following error message queue:")
|
|
foreach(err_msg ${TRIBITS_CTEST_DRIVER_ERROR_QUEUE})
|
|
message("${err_msg}")
|
|
endforeach()
|
|
endif()
|
|
endmacro()
|
|
|
|
|
|
# Setup for tracking if a configure is being attempted to keep memory if it
|
|
# will pass or not.
|
|
#
|
|
# This will wrilte files in the directory ${CTEST_BINARY_DIRECTORY} to keep
|
|
# track of this across multiple ctest -S script invocations.
|
|
#
|
|
macro(tribits_remember_if_configure_attempted)
|
|
|
|
# Must always define these files names as they they are used in functions
|
|
# called later in the same ctest -S invocation!
|
|
set(CONFIGURE_ATTEMPTED_FILE
|
|
"${CTEST_BINARY_DIRECTORY}/ConfigureAttempted.txt")
|
|
set(CONFIGURE_PASSED_FILE
|
|
"${CTEST_BINARY_DIRECTORY}/ConfigurePasssed.txt")
|
|
|
|
if (CTEST_DO_CONFIGURE)
|
|
file(WRITE "${CONFIGURE_ATTEMPTED_FILE}" "Attempting configure")
|
|
if (EXISTS "${CONFIGURE_PASSED_FILE}")
|
|
file(REMOVE "${CONFIGURE_PASSED_FILE}")
|
|
endif()
|
|
elseif(CTEST_DO_NEW_START)
|
|
if (EXISTS "${CONFIGURE_ATTEMPTED_FILE}")
|
|
file(REMOVE "${CONFIGURE_ATTEMPTED_FILE}")
|
|
endif()
|
|
if (EXISTS "${CONFIGURE_PASSED_FILE}")
|
|
file(REMOVE "${CONFIGURE_PASSED_FILE}")
|
|
endif()
|
|
endif()
|
|
|
|
endmacro()
|
|
# NOTE: Above, this is made a macro because it defines the vars
|
|
# CONFIGURE_ATTEMPTED_FILE and CONFIGURE_PASSED_FILE at the top function
|
|
# scope. This is needed so the below functions will see them set.
|
|
|
|
|
|
# Determine if a past configure was attempted but did not pass
|
|
#
|
|
function(tribits_previous_configure_attempted_but_not_passsed
|
|
PREVIOUS_CONFIGURE_ATTEMPTED_BUT_NOT_PASSSED_VAR_OUT
|
|
)
|
|
|
|
#print_var(CONFIGURE_ATTEMPTED_FILE)
|
|
#print_var(CONFIGURE_PASSED_FILE)
|
|
|
|
if(
|
|
(EXISTS "${CONFIGURE_ATTEMPTED_FILE}")
|
|
AND
|
|
(NOT EXISTS "${CONFIGURE_PASSED_FILE}")
|
|
)
|
|
set(PREVIOUS_CONFIGURE_ATTEMPTED_BUT_NOT_PASSSED TRUE)
|
|
else()
|
|
set(PREVIOUS_CONFIGURE_ATTEMPTED_BUT_NOT_PASSSED FALSE)
|
|
endif()
|
|
|
|
set(${PREVIOUS_CONFIGURE_ATTEMPTED_BUT_NOT_PASSSED_VAR_OUT}
|
|
${PREVIOUS_CONFIGURE_ATTEMPTED_BUT_NOT_PASSSED} PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
|
|
# Remember that the configure passed for later ctest -S invocations
|
|
#
|
|
function(tribits_remember_configure_passed)
|
|
file(WRITE "${CONFIGURE_PASSED_FILE}" "Configure Passed!")
|
|
endfunction()
|
|
|
|
|
|
# Override CTEST_SUBMIT to drive multiple submits and to detect failed
|
|
# submissions and track them as queued errors.
|
|
#
|
|
macro(tribits_ctest_submit)
|
|
|
|
# Cache the original CTEST_DROP_SITE and CTEST_DROP_LOCATION
|
|
if ("${TRIBITS_CTEST_DROP_SITE_ORIG}" STREQUAL "")
|
|
set(TRIBITS_CTEST_DROP_SITE_ORIG ${CTEST_DROP_SITE})
|
|
if (TRIBITS_CTEST_SUBMIT_DEBUG_DUMP)
|
|
print_var(TRIBITS_CTEST_DROP_SITE_ORIG)
|
|
endif()
|
|
endif()
|
|
if ("${TRIBITS_CTEST_DROP_LOCATION_ORIG}" STREQUAL "")
|
|
set(TRIBITS_CTEST_DROP_LOCATION_ORIG ${CTEST_DROP_LOCATION})
|
|
if (TRIBITS_CTEST_SUBMIT_DEBUG_DUMP)
|
|
print_var(TRIBITS_CTEST_DROP_LOCATION_ORIG)
|
|
endif()
|
|
endif()
|
|
|
|
# Do the first submit
|
|
set(CTEST_DROP_SITE ${TRIBITS_CTEST_DROP_SITE_ORIG})
|
|
set(CTEST_DROP_LOCATION ${TRIBITS_CTEST_DROP_LOCATION_ORIG})
|
|
if (TRIBITS_CTEST_SUBMIT_DEBUG_DUMP)
|
|
print_var(CTEST_DROP_SITE)
|
|
print_var(CTEST_DROP_LOCATION)
|
|
endif()
|
|
|
|
tribits_ctest_submit_driver(${ARGN})
|
|
|
|
# Do the second submit if requested!
|
|
if (TRIBITS_2ND_CTEST_DROP_SITE OR TRIBITS_2ND_CTEST_DROP_LOCATION)
|
|
|
|
message("\nDoing submit to second CDash site ...\n")
|
|
|
|
if (NOT "${TRIBITS_2ND_CTEST_DROP_SITE}" STREQUAL "")
|
|
if (TRIBITS_CTEST_SUBMIT_DEBUG_DUMP)
|
|
print_var(TRIBITS_2ND_CTEST_DROP_SITE)
|
|
endif()
|
|
set(CTEST_DROP_SITE ${TRIBITS_2ND_CTEST_DROP_SITE})
|
|
endif()
|
|
|
|
if (NOT "${TRIBITS_2ND_CTEST_DROP_LOCATION}" STREQUAL "")
|
|
if (TRIBITS_CTEST_SUBMIT_DEBUG_DUMP)
|
|
print_var(TRIBITS_2ND_CTEST_DROP_LOCATION)
|
|
endif()
|
|
set(CTEST_DROP_LOCATION ${TRIBITS_2ND_CTEST_DROP_LOCATION})
|
|
endif()
|
|
|
|
tribits_ctest_submit_driver(${ARGN})
|
|
|
|
endif()
|
|
|
|
endmacro()
|
|
|
|
|
|
macro(tribits_ctest_submit_driver)
|
|
|
|
# If using a recent enough ctest with RETRY_COUNT, use it to overcome
|
|
# failed submits:
|
|
set(retry_args "")
|
|
set(retry_args
|
|
RETRY_COUNT ${CTEST_SUBMIT_RETRY_COUNT}
|
|
RETRY_DELAY ${CTEST_SUBMIT_RETRY_DELAY})
|
|
message("info: using retry_args='${retry_args}' for _ctest_submit call")
|
|
|
|
# Call the original CTEST_SUBMIT and pay attention to its RETURN_VALUE:
|
|
ctest_submit(${ARGN} ${retry_args} RETURN_VALUE rv)
|
|
|
|
if(NOT "${rv}" STREQUAL "0")
|
|
queue_error("error: ctest_submit failed: rv='${rv}' ARGN='${ARGN}' retry_args='${retry_args}'")
|
|
endif()
|
|
|
|
endmacro()
|
|
|
|
|
|
# Wrapper for ctest_update(...) for unit testing
|
|
#
|
|
macro(ctest_update_wrapper)
|
|
if (NOT CTEST_UPDATE_UNIT_TESTING_MODE)
|
|
ctest_update(${ARGN})
|
|
else()
|
|
message("ctest_update(${ARGN})")
|
|
set(UPDATE_RETURN_VAL ${CTEST_UPDATE_RETURN_VAL})
|
|
endif()
|
|
endmacro()
|
|
|
|
|
|
# Helper macros to pass through common CMake configure arguments used by both
|
|
# package-by-package approach and all-at-once approach
|
|
#
|
|
macro(tribits_fwd_cmake_config_args_0)
|
|
set( CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_TRIBITS_DIR=${${PROJECT_NAME}_TRIBITS_DIR}"
|
|
"-DCTEST_USE_LAUNCHERS:BOOL=${CTEST_USE_LAUNCHERS}"
|
|
"-D${PROJECT_NAME}_ENABLE_ALL_OPTIONAL_PACKAGES:BOOL=ON"
|
|
"-D${PROJECT_NAME}_WARNINGS_AS_ERRORS_FLAGS:STRING=${${PROJECT_NAME}_WARNINGS_AS_ERRORS_FLAGS}"
|
|
"-D${PROJECT_NAME}_ALLOW_NO_PACKAGES:BOOL=ON"
|
|
"-D${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=${${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES}"
|
|
)
|
|
if (NOT CTEST_GENERATE_DEPS_XML_OUTPUT_FILE)
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_DEPS_XML_OUTPUT_FILE:FILEPATH=")
|
|
endif()
|
|
if (NOT "${${PROJECT_NAME}_GENERATE_VERSION_DATE_FILES}" STREQUAL "")
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_GENERATE_VERSION_DATE_FILES:BOOL=${${PROJECT_NAME}_GENERATE_VERSION_DATE_FILES}")
|
|
endif()
|
|
if (NOT "${${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE}" STREQUAL "")
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE:BOOL=${${PROJECT_NAME}_ENABLE_SECONDARY_TESTED_CODE}")
|
|
endif()
|
|
if (NOT MPI_EXEC_MAX_NUMPROCS STREQUAL 0)
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-DMPI_EXEC_MAX_NUMPROCS:STRING=${MPI_EXEC_MAX_NUMPROCS}")
|
|
endif()
|
|
if (${PROJECT_NAME}_SKIP_CTEST_ADD_TEST)
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_SKIP_CTEST_ADD_TEST:BOOL=${${PROJECT_NAME}_SKIP_CTEST_ADD_TEST}")
|
|
endif()
|
|
if (CTEST_DO_COVERAGE_TESTING)
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_ENABLE_COVERAGE_TESTING:BOOL=ON")
|
|
endif()
|
|
if (${PROJECT_NAME}_EXTRAREPOS_FILE STREQUAL "NONE")
|
|
set(EXTRAREOS_FILE_PASSED "")
|
|
else()
|
|
set(EXTRAREOS_FILE_PASSED "${${PROJECT_NAME}_EXTRAREPOS_FILE}")
|
|
endif()
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_EXTRAREPOS_FILE:STRING=${EXTRAREOS_FILE_PASSED}")
|
|
list(APPEND CONFIGURE_OPTIONS # See TRIBITS_SETUP_PACKAGES
|
|
"-D${PROJECT_NAME}_IGNORE_MISSING_EXTRA_REPOSITORIES:BOOL=ON")
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_ENABLE_KNOWN_EXTERNAL_REPOS_TYPE:STRING=${${PROJECT_NAME}_ENABLE_KNOWN_EXTERNAL_REPOS_TYPE}")
|
|
if (CTEST_DO_INSTALL)
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-DCMAKE_SKIP_INSTALL_ALL_DEPENDENCY=ON")
|
|
endif()
|
|
endmacro()
|
|
|
|
|
|
macro(tribits_fwd_cmake_config_args_1)
|
|
set(CONFIGURE_OPTIONS ${CONFIGURE_OPTIONS}
|
|
${EXTRA_SYSTEM_CONFIGURE_OPTIONS} ${EXTRA_CONFIGURE_OPTIONS}
|
|
${${PROJECT_NAME}_EXTRA_CONFIGURE_OPTIONS} )
|
|
endmacro()
|
|
|
|
|
|
# Remove the all of the LastTestsFailed*.log files so we can determine if any
|
|
# tests have failed.
|
|
#
|
|
macro(tribits_remove_last_test_failed_log_file)
|
|
# Remove the LastTestsFailed log so we can detect if there are any
|
|
# failed tests.
|
|
set(TEST_TMP_DIR "${CTEST_BINARY_DIRECTORY}/Testing/Temporary")
|
|
set(LAST_TESTS_FILED_LOG_FILE_GLOB "${TEST_TMP_DIR}/LastTestsFailed*.log")
|
|
file(GLOB logfiles "${LAST_TESTS_FILED_LOG_FILE_GLOB}")
|
|
foreach(logfile ${logfiles})
|
|
file(REMOVE "${logfile}")
|
|
endforeach()
|
|
endmacro()
|
|
|
|
|
|
# Sets the var FAILED_TEST_LOG_FILE if the file is found
|
|
macro(tribits_find_last_test_failed_log_file)
|
|
file(GLOB FAILED_TEST_LOG_FILE "${LAST_TESTS_FILED_LOG_FILE_GLOB}")
|
|
endmacro()
|
|
|
|
|
|
# Get names of failed packages from failed tests
|
|
function(tribits_get_failed_packages_from_failed_tests
|
|
LAST_TESTS_FAILED_FILE FAILED_PACKAGES_OUT
|
|
)
|
|
execute_process(
|
|
COMMAND ${PYTHON_EXECUTABLE}
|
|
"${${PROJECT_NAME}_TRIBITS_DIR}/ci_support/get-tribits-packages-from-last-tests-failed.py"
|
|
"--deps-xml-file=${CTEST_BINARY_DIRECTORY}/${${PROJECT_NAME}_PACKAGE_DEPS_XML_FILE_NAME}"
|
|
"--last-tests-failed-file=${LAST_TESTS_FAILED_FILE}"
|
|
OUTPUT_VARIABLE FAILED_PACKAGES
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
split("${FAILED_PACKAGES}" "," FAILED_PACKAGES)
|
|
set(${FAILED_PACKAGES_OUT} "${FAILED_PACKAGES}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
|
|
# Drive the configure, build, test, and submit package-by-package
|
|
#
|
|
# Sets ${PROJECT_NAME}_FAILED_PACKAGES as an indication if there are any
|
|
# failures.
|
|
#
|
|
macro(tribits_ctest_package_by_package)
|
|
|
|
message(
|
|
"\n***"
|
|
"\n*** Loop through ${PROJECT_NAME} packages to configure, build, and test ..."
|
|
"\n***")
|
|
|
|
set(${PROJECT_NAME}_LAST_CONFIGURED_PACKAGE)
|
|
set(${PROJECT_NAME}_FAILED_LIB_BUILD_PACKAGES)
|
|
set(PACKAGE_IDX 0)
|
|
|
|
foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_PACKAGES_TO_DIRECTLY_TEST})
|
|
|
|
message("")
|
|
message("${PACKAGE_IDX}) Processing current package ${TRIBITS_PACKAGE}:"
|
|
" libs='${${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}}',"
|
|
" tests='${${TRIBITS_PACKAGE}_ENABLE_TESTS}'")
|
|
message("")
|
|
|
|
set_property(GLOBAL PROPERTY SubProject ${TRIBITS_PACKAGE})
|
|
set_property(GLOBAL PROPERTY Label ${TRIBITS_PACKAGE})
|
|
|
|
#
|
|
# A) Configure the package and its dependent packages
|
|
#
|
|
|
|
message("Configuring TRIBITS_PACKAGE='${TRIBITS_PACKAGE}'")
|
|
|
|
# Create CONFIGURE_OPTIONS for this TRIBITS_PACKAGE
|
|
tribits_fwd_cmake_config_args_0()
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_ENABLE_TESTS:BOOL=${${TRIBITS_PACKAGE}_ENABLE_TESTS}")
|
|
if (DEFINED ${PROJECT_NAME}_LAST_CONFIGURED_PACKAGE)
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_ENABLE_${${PROJECT_NAME}_LAST_CONFIGURED_PACKAGE}:BOOL=")
|
|
set(${PROJECT_NAME}_LAST_CONFIGURED_PACKAGE)
|
|
endif()
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_DEFINE_MISSING_PACKAGE_LIBS_TARGETS=ON")
|
|
foreach(FAILED_PACKAGE ${${PROJECT_NAME}_FAILED_LIB_BUILD_PACKAGES})
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_ENABLE_${FAILED_PACKAGE}:BOOL=OFF")
|
|
endforeach()
|
|
tribits_fwd_cmake_config_args_1()
|
|
list(APPEND CONFIGURE_OPTIONS # Package enable must be at the very end to override other stuff!
|
|
"-D${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}:BOOL=ON" )
|
|
message("\nCONFIGURE_OPTIONS = '${CONFIGURE_OPTIONS}'")
|
|
|
|
# Remember this package so we can set its enable to "" next time
|
|
set(${PROJECT_NAME}_LAST_CONFIGURED_PACKAGE "${TRIBITS_PACKAGE}")
|
|
|
|
#
|
|
# B) Configure the package and its dependent packages
|
|
#
|
|
|
|
set(PBP_CONFIGURE_PASSED TRUE)
|
|
|
|
if (CTEST_DEPENDENCY_HANDLING_UNIT_TESTING)
|
|
|
|
message("${TRIBITS_PACKAGE}: Skipping configure due"
|
|
" to running in unit testing mode!")
|
|
|
|
else()
|
|
|
|
#
|
|
# We always have to configure if we are going to do anything for the
|
|
# package. We just want submit configure results to CDash if we are not
|
|
# asked to configure!
|
|
#
|
|
|
|
set(PBP_CONFIGURE_PASSED FALSE)
|
|
|
|
ctest_configure(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
OPTIONS "${CONFIGURE_OPTIONS}" # New option!
|
|
RETURN_VALUE CONFIGURE_RETURN_VAL
|
|
)
|
|
|
|
message("Generating the file '${CMAKE_CACHE_CLEAN_FILE}' ...")
|
|
tribits_strip_comments_from_cmake_cache_file(
|
|
"${CTEST_BINARY_DIRECTORY}/CMakeCache.txt"
|
|
"${CMAKE_CACHE_CLEAN_FILE}"
|
|
)
|
|
|
|
# If the configure failed, add the package to the list
|
|
# of failed packages
|
|
if ("${CONFIGURE_RETURN_VAL}" EQUAL "0")
|
|
message("\n${TRIBITS_PACKAGE}: Configure passed!\n")
|
|
set(PBP_CONFIGURE_PASSED TRUE)
|
|
# load target properties and test keywords
|
|
ctest_read_custom_files(BUILD "${CTEST_BINARY_DIRECTORY}")
|
|
# Overridde from this file!
|
|
include("${TRIBITS_PROJECT_ROOT}/CTestConfig.cmake")
|
|
else()
|
|
message("\n${TRIBITS_PACKAGE} FAILED to configure!\n")
|
|
endif()
|
|
|
|
if (EXISTS ${CMAKE_CACHE_CLEAN_FILE})
|
|
set(CTEST_NOTES_FILES "${CTEST_NOTES_FILES_WO_CACHE};${CMAKE_CACHE_CLEAN_FILE}")
|
|
else()
|
|
set(CTEST_NOTES_FILES "${CTEST_NOTES_FILES_WO_CACHE}")
|
|
endif()
|
|
|
|
print_var(CTEST_NOTES_FILES)
|
|
|
|
if (NOT CTEST_DO_CONFIGURE AND CTEST_DO_SUBMIT)
|
|
message("${TRIBITS_PACKAGE}: Skipping submitting configure"
|
|
" and notes due to CTEST_DO_CONFIGURE='${CTEST_DO_CONFIGURE}'!")
|
|
elseif (CTEST_DO_SUBMIT)
|
|
message("\nSubmitting configure and notes ...")
|
|
tribits_ctest_submit( PARTS configure notes )
|
|
endif()
|
|
|
|
endif()
|
|
|
|
# Print out values read from project CTestCustom.cmake file!
|
|
print_var(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE)
|
|
print_var(CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE)
|
|
|
|
#
|
|
# C) Build the library and then ALL
|
|
#
|
|
|
|
set(PBP_BUILD_PASSED TRUE)
|
|
set(PBP_BUILD_LIBS_PASSED TRUE)
|
|
|
|
print_var(PBP_CONFIGURE_PASSED)
|
|
|
|
if ( NOT PBP_CONFIGURE_PASSED AND CTEST_DO_BUILD )
|
|
|
|
message("\n${TRIBITS_PACKAGE}: Skipping build due"
|
|
" to configure failing!")
|
|
|
|
set(PBP_BUILD_PASSED FALSE)
|
|
set(PBP_BUILD_LIBS_PASSED FALSE)
|
|
|
|
elseif (NOT CTEST_DO_BUILD)
|
|
|
|
message("\n${TRIBITS_PACKAGE}: Skipping build due"
|
|
" to CTEST_DO_BUILD='${CTEST_DO_BUILD}'!")
|
|
|
|
elseif (CTEST_DEPENDENCY_HANDLING_UNIT_TESTING OR
|
|
CTEST_CONFIGURATION_UNIT_TESTING
|
|
)
|
|
|
|
message("\n${TRIBITS_PACKAGE}: Skipping build due"
|
|
" to running in unit testing mode!")
|
|
|
|
else()
|
|
|
|
# Start by trying to build just the libraries for the current package
|
|
|
|
set( CTEST_BUILD_TARGET ${TRIBITS_PACKAGE}_libs )
|
|
message("\nBuilding target: '${CTEST_BUILD_TARGET}' ...\n")
|
|
set(PBP_BUILD_LIBS_PASSED FALSE)
|
|
ctest_build(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
RETURN_VALUE BUILD_LIBS_RETURN_VAL
|
|
NUMBER_ERRORS BUILD_LIBS_NUM_ERRORS
|
|
APPEND
|
|
)
|
|
message("Build return: RETURN_VALUE=${BUILD_LIBS_RETURN_VAL},"
|
|
" NUMBER_ERRORS=${BUILD_LIBS_NUM_ERRORS}")
|
|
|
|
# Determine if the build failed or not.
|
|
|
|
if ("${BUILD_LIBS_NUM_ERRORS}" EQUAL "0")
|
|
message("\n${TRIBITS_PACKAGE}: Libs build passed!")
|
|
set(PBP_BUILD_LIBS_PASSED TRUE)
|
|
else()
|
|
message("\nFAILED library build for package '${TRIBITS_PACKAGE}'!")
|
|
set(PBP_BUILD_PASSED FALSE)
|
|
endif()
|
|
# Above: Since make -i is used BUILD_LIBS_RETURN_VAL might be 0, but
|
|
# if there are errors the build should fail, so both
|
|
# BUILD_LIBS_RETURN_VAL and BUILD_LIBS_NUM_ERRORS should be 0 for a
|
|
# good build and for the all target to be built.
|
|
|
|
# Submit the library build results to the dashboard
|
|
if (CTEST_DO_SUBMIT)
|
|
tribits_ctest_submit( PARTS build )
|
|
endif()
|
|
|
|
# If the build of the libraries passed, then go on the build
|
|
# the tests/examples and run them.
|
|
|
|
if (PBP_BUILD_LIBS_PASSED)
|
|
|
|
# Build the ALL target, but append the results to the last build.xml
|
|
set(CTEST_BUILD_TARGET)
|
|
message("\nBuild ALL target for '${TRIBITS_PACKAGE}' ...\n")
|
|
ctest_build(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
RETURN_VALUE BUILD_ALL_RETURN_VAL
|
|
NUMBER_ERRORS BUILD_ALL_NUM_ERRORS
|
|
APPEND
|
|
)
|
|
message("Build all: BUILD_ALL_NUM_ERRORS='${BUILD_ALL_NUM_ERRORS}',"
|
|
"BUILD_ALL_RETURN_VAL='${BUILD_ALL_RETURN_VAL}'" )
|
|
|
|
if (NOT "${BUILD_ALL_NUM_ERRORS}" EQUAL "0")
|
|
message("${TRIBITS_PACKAGE}: All build FAILED!")
|
|
set(PBP_BUILD_PASSED FALSE)
|
|
else()
|
|
message("${TRIBITS_PACKAGE}: All build passed!")
|
|
endif()
|
|
|
|
# Submit the build for all target
|
|
if (CTEST_DO_SUBMIT)
|
|
tribits_ctest_submit( PARTS build )
|
|
endif()
|
|
|
|
endif()
|
|
|
|
endif()
|
|
|
|
#
|
|
# D) Run the tests
|
|
#
|
|
|
|
set(PBP_TESTS_PASSED TRUE)
|
|
|
|
if (NOT PBP_BUILD_LIBS_PASSED AND CTEST_DO_TEST)
|
|
|
|
message("\n${TRIBITS_PACKAGE}: Skipping tests since library build failed!\n")
|
|
|
|
set(PBP_TESTS_PASSED FALSE)
|
|
|
|
elseif (NOT CTEST_DO_TEST)
|
|
|
|
message("\n${TRIBITS_PACKAGE}: Skipping running tests due"
|
|
" to CTEST_DO_TEST='${CTEST_DO_TEST}'!")
|
|
|
|
else()
|
|
|
|
#
|
|
# D.1) Run the regular tests
|
|
#
|
|
|
|
set(PBP_TESTS_PASSED FALSE)
|
|
|
|
# Run the tests that match the ${TRIBITS_PACKAGE} name
|
|
message("\nRunning test for package '${TRIBITS_PACKAGE}'"
|
|
" (parallel level ${CTEST_PARALLEL_LEVEL}) ...\n")
|
|
tribits_remove_last_test_failed_log_file()
|
|
ctest_test(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
PARALLEL_LEVEL "${CTEST_PARALLEL_LEVEL}"
|
|
INCLUDE_LABEL "^${TRIBITS_PACKAGE}$"
|
|
)
|
|
# See if a 'LastTestsFailed*.log' file exists to determine if there are
|
|
# failed tests
|
|
tribits_find_last_test_failed_log_file()
|
|
if (FAILED_TEST_LOG_FILE)
|
|
message("\n${TRIBITS_PACKAGE}: File '${FAILED_TEST_LOG_FILE}'"
|
|
" exists so there were failed tests!")
|
|
else()
|
|
message("\n${TRIBITS_PACKAGE}: File '${FAILED_TEST_LOG_FILE}'"
|
|
" does NOT exist so all tests passed!")
|
|
set(PBP_TESTS_PASSED TRUE)
|
|
endif()
|
|
# 2009/12/05: ToDo: We need to add an argument to ctest_test(...)
|
|
# called something like 'NUMBER_FAILED numFailedTests' to allow us to
|
|
# detect when the tests have filed.
|
|
if (CTEST_DO_SUBMIT)
|
|
tribits_ctest_submit( PARTS Test )
|
|
endif()
|
|
|
|
#
|
|
# D.2) Collect coverage results
|
|
#
|
|
|
|
if (CTEST_DO_COVERAGE_TESTING)
|
|
|
|
message("\nRunning coverage for package '${TRIBITS_PACKAGE}' ...\n")
|
|
|
|
ctest_coverage(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
LABELS ${TRIBITS_PACKAGE} ${TRIBITS_PACKAGE}Libs ${TRIBITS_PACKAGE}Exes
|
|
)
|
|
|
|
if (CTEST_DO_SUBMIT)
|
|
tribits_ctest_submit( PARTS Coverage )
|
|
endif()
|
|
|
|
endif()
|
|
|
|
endif()
|
|
|
|
#
|
|
# E) Run memory testing
|
|
#
|
|
|
|
if (NOT PBP_BUILD_LIBS_PASSED AND CTEST_DO_MEMORY_TESTING)
|
|
|
|
message("\n${TRIBITS_PACKAGE}: Skipping running memory checking"
|
|
"tests since library build failed!\n")
|
|
|
|
elseif (NOT CTEST_DO_MEMORY_TESTING)
|
|
|
|
message("\n${TRIBITS_PACKAGE}: Skipping running memory checking tests due"
|
|
" to CTEST_DO_MEMORY_TESTING='${CTEST_DO_MEMORY_TESTING}'!")
|
|
|
|
else()
|
|
|
|
message("\nRunning memory testing for package '${TRIBITS_PACKAGE}' ...\n")
|
|
|
|
print_var(CTEST_MEMORYCHECK_COMMAND)
|
|
print_var(CTEST_MEMORYCHECK_COMMAND_OPTIONS)
|
|
print_var(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE)
|
|
|
|
ctest_memcheck(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
PARALLEL_LEVEL "${CTEST_PARALLEL_LEVEL}"
|
|
INCLUDE_LABEL "^${TRIBITS_PACKAGE}$"
|
|
)
|
|
# ToDo: Determine if memory testing passed or not and affect overall
|
|
# pass/fail!
|
|
|
|
if (CTEST_DO_SUBMIT)
|
|
tribits_ctest_submit( PARTS MemCheck )
|
|
endif()
|
|
|
|
endif()
|
|
|
|
#
|
|
# F) Record if this package failed the build or any tests
|
|
#
|
|
|
|
if (NOT PBP_CONFIGURE_PASSED OR NOT PBP_BUILD_LIBS_PASSED)
|
|
list(APPEND ${PROJECT_NAME}_FAILED_LIB_BUILD_PACKAGES ${TRIBITS_PACKAGE})
|
|
endif()
|
|
|
|
if (NOT PBP_BUILD_PASSED OR NOT PBP_TESTS_PASSED)
|
|
list(APPEND ${PROJECT_NAME}_FAILED_PACKAGES ${TRIBITS_PACKAGE})
|
|
endif()
|
|
|
|
#
|
|
# G) Do submit of update
|
|
#
|
|
|
|
if (CTEST_DO_SUBMIT)
|
|
message("\nSubmit the update file that will trigger the notification email ...\n")
|
|
tribits_ctest_submit( PARTS update )
|
|
endif()
|
|
|
|
math(EXPR PACKAGE_IDX "${PACKAGE_IDX}+1")
|
|
|
|
endforeach(TRIBITS_PACKAGE)
|
|
|
|
if (${PROJECT_NAME}_FAILED_LIB_BUILD_PACKAGES)
|
|
message(
|
|
"\nFinal set packages that failed to configure or have the libraries build:"
|
|
" '${${PROJECT_NAME}_FAILED_LIB_BUILD_PACKAGES}'")
|
|
endif()
|
|
|
|
message("\nDone with the incremental building and testing of"
|
|
" ${PROJECT_NAME} packages!\n")
|
|
|
|
endmacro()
|
|
# NOTE: Above, the option
|
|
# ${PROJECT_NAME}_DEFINE_MISSING_PACKAGE_LIBS_TARGETS=ON is passed down
|
|
# through to the inner CMake TriBITS configure to trigger the creation of
|
|
# dummy targets <PackageName>_libs for all the packages for the case where a
|
|
# package is disabled due to a disabled upstream package and
|
|
# ${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=ON but the target
|
|
# <thePackage>_libs is attempted to be built anyway and we expect it to build
|
|
# nothing and result in no error. (The outer ctest -S driver is not smart
|
|
# enough to know all the lgoic for if a package will actually be enabled or
|
|
# not. That is the job of the inner TriBITS dependency logic and
|
|
# ${PROJECT_NAME}_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=ON.) Otherwise, with
|
|
# CMake 3.19+, cmake_build() catches errors in undefined global build targets
|
|
# like this and reports them correctly. This workaround allows the
|
|
# package-by-package mode to gracefully disable downstream packages that can't
|
|
# be enabled due to the disable of a broken upstream packages. See the test
|
|
# TriBITS_CTestDriver_PBP_ST_BreakConfigureRequiredPkg that exercises this use
|
|
# case.
|
|
|
|
|
|
# Drive the configure, build, test, and submit all at once for all of the
|
|
# enabled packages.
|
|
#
|
|
# Sets ${PROJECT_NAME}_FAILED_PACKAGES as an indication if there are any
|
|
# failures.
|
|
#
|
|
macro(tribits_ctest_all_at_once)
|
|
|
|
message(
|
|
"\n***"
|
|
"\n*** Configure, build, test and submit results all-at-once for all enabled packages ..."
|
|
"\n***")
|
|
|
|
set(AAO_CONFIGURE_FAILED FALSE)
|
|
set(AAO_BUILD_FAILED FALSE)
|
|
set(AAO_INSTALL_FAILED FALSE)
|
|
|
|
#
|
|
# A) Define mapping from labels to subprojects and gather configure arguments
|
|
#
|
|
|
|
tribits_ctest_driver_set_labels_to_subprojects_mapping()
|
|
print_var(CTEST_LABELS_FOR_SUBPROJECTS)
|
|
|
|
message("")
|
|
message("Configuring ...")
|
|
message("")
|
|
|
|
# Create CONFIGURE_OPTIONS
|
|
tribits_fwd_cmake_config_args_0()
|
|
if (NOT "${${PROJECT_NAME}_PACKAGE_ENABLES_FILE}" STREQUAL "")
|
|
# NOTE: For now, the user is expected to pass through this file in the
|
|
# inner CMake cache var ${PROJECT_NAME}_CONFIGURE_OPTIONS_FILE! We should
|
|
# fix this in the future but that is what it is for now.
|
|
elseif (${PROJECT_NAME}_ENABLE_ALL_PACKAGES)
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_ENABLE_ALL_PACKAGES=ON" )
|
|
foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_EXCLUDE_PACKAGES})
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}=OFF" )
|
|
endforeach()
|
|
# NOTE: Above we have to explicitly set disables for the excluded packages
|
|
# since we are pssing in ${PROJECT_NAME}_ENABLE_ALL_PACKAGES=ON. This is
|
|
# effectively the "black-listing" approach.
|
|
else()
|
|
foreach(TRIBITS_PACKAGE ${${PROJECT_NAME}_PACKAGES_TO_DIRECTLY_TEST})
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_ENABLE_${TRIBITS_PACKAGE}=ON" )
|
|
endforeach()
|
|
# NOTE: Above we don't have to consider the packages excluded in
|
|
# ${PROJECT_NAME}_EXCLUDE_PACKAGES because they are not enabled ad this
|
|
# point and therefore no in ${PROJECT_NAME}_PACKAGES_TO_DIRECTLY_TEST.
|
|
# This is effectively the "white-listing" approach.
|
|
endif()
|
|
list(APPEND CONFIGURE_OPTIONS
|
|
"-D${PROJECT_NAME}_ENABLE_TESTS:BOOL=${${PROJECT_NAME}_INNER_ENABLE_TESTS}")
|
|
tribits_fwd_cmake_config_args_1()
|
|
message("\nCONFIGURE_OPTIONS = '${CONFIGURE_OPTIONS}'")
|
|
|
|
#
|
|
# B) Configure the package and its dependent packages
|
|
#
|
|
|
|
tribits_previous_configure_attempted_but_not_passsed(
|
|
PREVIOUS_CONFIGURE_ATTEMPTED_BUT_NOT_PASSSED)
|
|
#print_var(PREVIOUS_CONFIGURE_ATTEMPTED_BUT_NOT_PASSSED)
|
|
|
|
if ((NOT CTEST_DO_CONFIGURE) AND PREVIOUS_CONFIGURE_ATTEMPTED_BUT_NOT_PASSSED)
|
|
|
|
message(
|
|
"\nSkipping configure due to CTEST_DO_CONFIGURE='${CTEST_DO_CONFIGURE}'!\n"
|
|
"\nHOWEVER: A configure was previously attempted but did not pass so consider configure FAILED!")
|
|
set(AAO_CONFIGURE_PASSED FALSE)
|
|
set(AAO_CONFIGURE_FAILED TRUE)
|
|
|
|
elseif (NOT CTEST_DO_CONFIGURE)
|
|
|
|
message("\nSkipping configure due to CTEST_DO_CONFIGURE='${CTEST_DO_CONFIGURE}'!\n")
|
|
set(AAO_CONFIGURE_PASSED TRUE)
|
|
# Just assume configure passeed for the purpose of running the build.
|
|
|
|
elseif (CTEST_DEPENDENCY_HANDLING_UNIT_TESTING)
|
|
|
|
message("Skipping actual ctest_configure() because"
|
|
" CTEST_DEPENDENCY_HANDLING_UNIT_TESTING='${CTEST_DEPENDENCY_HANDLING_UNIT_TESTING}'!"
|
|
)
|
|
set(AAO_CONFIGURE_PASSED TRUE)
|
|
|
|
else()
|
|
|
|
ctest_configure(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
OPTIONS "${CONFIGURE_OPTIONS}" # New option!
|
|
RETURN_VALUE CONFIGURE_RETURN_VAL
|
|
)
|
|
|
|
message("Generating the file '${CMAKE_CACHE_CLEAN_FILE}' ...")
|
|
tribits_strip_comments_from_cmake_cache_file(
|
|
"${CTEST_BINARY_DIRECTORY}/CMakeCache.txt"
|
|
"${CMAKE_CACHE_CLEAN_FILE}"
|
|
)
|
|
|
|
if (NOT "${CONFIGURE_RETURN_VAL}" EQUAL "0")
|
|
message("Configure FAILED!")
|
|
set(AAO_CONFIGURE_PASSED FALSE)
|
|
set(AAO_CONFIGURE_FAILED TRUE)
|
|
else()
|
|
message("Configure PASSED!")
|
|
set(AAO_CONFIGURE_PASSED TRUE)
|
|
endif()
|
|
|
|
if (AAO_CONFIGURE_PASSED)
|
|
tribits_remember_configure_passed()
|
|
endif()
|
|
|
|
set(CTEST_NOTES_FILES "${CTEST_NOTES_FILES_WO_CACHE}")
|
|
|
|
if (EXISTS ${CMAKE_CACHE_CLEAN_FILE})
|
|
list(APPEND CTEST_NOTES_FILES "${CMAKE_CACHE_CLEAN_FILE}")
|
|
endif()
|
|
|
|
if (EXISTS "${REPO_VERSION_FILE}")
|
|
set(CTEST_NOTES_FILES "${REPO_VERSION_FILE};${CTEST_NOTES_FILES}")
|
|
endif()
|
|
|
|
print_var(CTEST_NOTES_FILES)
|
|
|
|
# Submit configure results and the notes to the dashboard
|
|
if (CTEST_DO_SUBMIT)
|
|
message("\nSubmitting update, configure and notes ...")
|
|
tribits_ctest_submit( PARTS update configure notes )
|
|
endif()
|
|
|
|
endif()
|
|
|
|
# Read in configured CTestCustom.cmake
|
|
ctest_read_custom_files(BUILD "${CTEST_BINARY_DIRECTORY}")
|
|
# NOTE: Above, it is safe to call ctest_read_custom_files() even if the
|
|
# configure failed and the file CTestCustom.cmake does exist. In this case,
|
|
# CTest will just do nothing.
|
|
|
|
# Overridde any values by loading <projectDir>/CTestConfig.cmake
|
|
include("${TRIBITS_PROJECT_ROOT}/CTestConfig.cmake")
|
|
|
|
# Print out values read from project CTestCustom.cmake file
|
|
print_var(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE)
|
|
print_var(CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE)
|
|
|
|
#
|
|
# C) Do the build
|
|
#
|
|
|
|
if (NOT CTEST_DO_BUILD)
|
|
|
|
message("\nSkipping build due to CTEST_DO_BUILD='${CTEST_DO_BUILD}'!\n")
|
|
|
|
elseif (CTEST_DEPENDENCY_HANDLING_UNIT_TESTING AND AAO_CONFIGURE_PASSED)
|
|
|
|
message("Skipping build because"
|
|
" CTEST_DEPENDENCY_HANDLING_UNIT_TESTING='${CTEST_DEPENDENCY_HANDLING_UNIT_TESTING}'!"
|
|
)
|
|
|
|
elseif (AAO_CONFIGURE_PASSED)
|
|
|
|
message("")
|
|
message("Building all targets ...")
|
|
message("")
|
|
|
|
ctest_build(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
RETURN_VALUE BUILD_ALL_RETURN_VAL
|
|
NUMBER_ERRORS BUILD_ALL_NUM_ERRORS
|
|
)
|
|
message("Build output: BUILD_ALL_NUM_ERRORS='${BUILD_ALL_NUM_ERRORS}',"
|
|
"BUILD_ALL_RETURN_VAL='${BUILD_ALL_RETURN_VAL}'" )
|
|
|
|
if (NOT "${BUILD_ALL_NUM_ERRORS}" EQUAL "0")
|
|
message("Build FAILED!")
|
|
set(AAO_BUILD_FAILED TRUE)
|
|
else()
|
|
message("Build PASSED!")
|
|
endif()
|
|
|
|
# Submit the build for all target
|
|
if (CTEST_DO_SUBMIT)
|
|
tribits_ctest_submit( PARTS build )
|
|
endif()
|
|
|
|
if (CTEST_DO_INSTALL)
|
|
|
|
message("")
|
|
message("Installing (i.e. building target 'install_package_by_package') ...")
|
|
message("")
|
|
|
|
ctest_build(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
TARGET install_package_by_package
|
|
RETURN_VALUE BUILD_INSTALL_RETURN_VAL
|
|
NUMBER_ERRORS BUILD_INSTALL_NUM_ERRORS
|
|
)
|
|
message("Build install output:"
|
|
" BUILD_INSTALL_NUM_ERRORS='${BUILD_INSTALL_NUM_ERRORS}',"
|
|
"BUILD_INSTALL_RETURN_VAL='${BUILD_INSTALL_RETURN_VAL}'" )
|
|
|
|
if (NOT "${BUILD_INSTALL_NUM_ERRORS}" EQUAL "0")
|
|
message("Install FAILED!")
|
|
set(AAO_INSTALL_FAILED TRUE)
|
|
else()
|
|
message("Install PASSED!")
|
|
endif()
|
|
|
|
# Submit the build for all target
|
|
if (CTEST_DO_SUBMIT)
|
|
tribits_ctest_submit( PARTS build )
|
|
endif()
|
|
|
|
endif()
|
|
|
|
else()
|
|
|
|
message("")
|
|
message("Skipping build because configure failed!")
|
|
message("")
|
|
|
|
endif()
|
|
|
|
#
|
|
# D) Run tests
|
|
#
|
|
|
|
if (NOT CTEST_DO_TEST)
|
|
|
|
message("")
|
|
message("Skipping tests because CTEST_DO_TEST='${CTEST_DO_TEST}'!")
|
|
message("")
|
|
|
|
elseif (NOT AAO_CONFIGURE_PASSED)
|
|
|
|
message("")
|
|
message("Skipping tests because configure failed!")
|
|
message("")
|
|
|
|
elseif (CTEST_DEPENDENCY_HANDLING_UNIT_TESTING AND AAO_CONFIGURE_PASSED)
|
|
|
|
message("Skipping testing because"
|
|
" CTEST_DEPENDENCY_HANDLING_UNIT_TESTING='${CTEST_DEPENDENCY_HANDLING_UNIT_TESTING}'!"
|
|
)
|
|
|
|
else()
|
|
|
|
# NOTE: We always run the tests if the configure passed no matter if there
|
|
# are build failures because the only way that we can detect what packages
|
|
# have build failures is to see what packages have test failures.
|
|
|
|
tribits_remove_last_test_failed_log_file()
|
|
|
|
# Run the tests
|
|
message("")
|
|
message("\nRunning tests (parallel level ${CTEST_PARALLEL_LEVEL}) ...\n")
|
|
message("")
|
|
|
|
ctest_test(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
PARALLEL_LEVEL "${CTEST_PARALLEL_LEVEL}"
|
|
)
|
|
|
|
# See if a 'LastTestsFailed*.log' file exists to determine if there are
|
|
# failed tests.
|
|
tribits_find_last_test_failed_log_file()
|
|
if (FAILED_TEST_LOG_FILE)
|
|
message("File '${FAILED_TEST_LOG_FILE}' exists so there were non-passing tests!")
|
|
else()
|
|
message("File '${FAILED_TEST_LOG_FILE}' does NOT exist so all tests passed!")
|
|
endif()
|
|
|
|
if (CTEST_DO_SUBMIT)
|
|
tribits_ctest_submit( PARTS Test )
|
|
endif()
|
|
|
|
endif()
|
|
|
|
#
|
|
# E) Gather coverage results
|
|
#
|
|
|
|
if (NOT CTEST_DO_COVERAGE_TESTING)
|
|
|
|
message("")
|
|
message("Skipping converage tests because CTEST_DO_COVERAGE_TESTING='${CTEST_DO_COVERAGE_TESTING}'!")
|
|
message("")
|
|
|
|
elseif (NOT AAO_CONFIGURE_PASSED)
|
|
|
|
message("")
|
|
message("Skipping coverage tests because configure failed!")
|
|
message("")
|
|
|
|
elseif (CTEST_DEPENDENCY_HANDLING_UNIT_TESTING AND AAO_CONFIGURE_PASSED)
|
|
|
|
message("Skipping coverage testing because"
|
|
" CTEST_DEPENDENCY_HANDLING_UNIT_TESTING='${CTEST_DEPENDENCY_HANDLING_UNIT_TESTING}'!"
|
|
)
|
|
|
|
else()
|
|
|
|
# NOTE: We always gather the coverage results if the configure passed
|
|
# independent if there was any build or test failures. The coverage stats
|
|
# may not be very valid if there are build or test failures but there is
|
|
# no harm and showing the coverage based on tests that actually run (even
|
|
# if they fail).
|
|
|
|
message("\nGathering coverage results ...\n")
|
|
ctest_coverage(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
)
|
|
if (CTEST_DO_SUBMIT)
|
|
tribits_ctest_submit( PARTS Coverage )
|
|
endif()
|
|
|
|
endif()
|
|
|
|
#
|
|
# F) Do memory testing
|
|
#
|
|
|
|
if (NOT CTEST_DO_MEMORY_TESTING)
|
|
|
|
message("")
|
|
message("Skipping memory testing because CTEST_DO_MEMORY_TESTING='${CTEST_DO_MEMORY_TESTING}'!")
|
|
message("")
|
|
|
|
elseif (NOT AAO_CONFIGURE_PASSED)
|
|
|
|
message("")
|
|
message("Skipping memory tests because configure failed!")
|
|
message("")
|
|
|
|
elseif (CTEST_DEPENDENCY_HANDLING_UNIT_TESTING AND AAO_CONFIGURE_PASSED)
|
|
|
|
message("Skipping memory testing because"
|
|
" CTEST_DEPENDENCY_HANDLING_UNIT_TESTING='${CTEST_DEPENDENCY_HANDLING_UNIT_TESTING}'!"
|
|
)
|
|
|
|
else()
|
|
|
|
# NOTE: We always gather the memory results if the configure passed
|
|
# independent if there was any build or test failures. The memory stats
|
|
# may not be very valid if there are build or test failures but there is
|
|
# no harm and showing the memory based on tests that actually run (even
|
|
# if they fail).
|
|
|
|
message("\nRunning memory tests ...\n")
|
|
print_var(CTEST_MEMORYCHECK_COMMAND)
|
|
print_var(CTEST_MEMORYCHECK_COMMAND_OPTIONS)
|
|
print_var(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE)
|
|
ctest_memcheck(
|
|
BUILD "${CTEST_BINARY_DIRECTORY}"
|
|
)
|
|
if (CTEST_DO_SUBMIT)
|
|
tribits_ctest_submit( PARTS MemCheck )
|
|
endif()
|
|
|
|
endif()
|
|
|
|
#
|
|
# G) Determine final pass/fail by gathering list of failing packages
|
|
#
|
|
|
|
if (AAO_CONFIGURE_FAILED OR AAO_BUILD_FAILED OR AAO_INSTALL_FAILED)
|
|
if (${PROJECT_NAME}_ENABLE_ALL_PACKAGES)
|
|
# Special value "ALL_PACKAGES" so that it will trigger enabling all
|
|
# packages on the next CI iteration!
|
|
set(${PROJECT_NAME}_FAILED_PACKAGES ALL_PACKAGES)
|
|
else()
|
|
# Specific packages were selected to be tested so fail all of them!
|
|
set(${PROJECT_NAME}_FAILED_PACKAGES ${${PROJECT_NAME}_PACKAGES_TO_DIRECTLY_TEST})
|
|
endif()
|
|
# NOTE: With the all-at-once approach, there is no way to determine which
|
|
# packages have build or install failures given the current ctest_build()
|
|
# command. And since some build targets don't get used in tests, we can't
|
|
# look at what packages have test failures in order to know that a build
|
|
# failure will cause a test failure. And in the case of install failures,
|
|
# those will never cause test failures. Therefore, if there are any build
|
|
# or install failures, we just have to assume that any tested package
|
|
# could have failed. Hence, we set the above just like for a (global)
|
|
# configure failures. Perhaps we could read the generated *.xml files to
|
|
# figure that out but that is not worth the work right now. The only bad
|
|
# consequence of this is that a CI build would end up building and testing
|
|
# every package even if only one downstream package had a build failure,
|
|
# for example. That is just one of the downsides of the all-at-once
|
|
# approach vs. the package-by-package approach.
|
|
elseif (FAILED_TEST_LOG_FILE)
|
|
tribits_get_failed_packages_from_failed_tests("${FAILED_TEST_LOG_FILE}"
|
|
${PROJECT_NAME}_FAILED_PACKAGES )
|
|
else()
|
|
# If no tests failed, then there are no failed packages!
|
|
set(${PROJECT_NAME}_FAILED_PACKAGES)
|
|
endif()
|
|
# ToDo: Optionally determine pass/fail based
|
|
|
|
message("\nDone with the all-at-once configure, build, test, and submit of ${PROJECT_NAME} packages!\n")
|
|
|
|
endmacro()
|
|
|