# ********************************************************** # Copyright (c) 2011-2025 Google, Inc. All rights reserved. # Copyright (c) 2009-2010 VMware, Inc. All rights reserved. # ********************************************************** # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # * 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. # # * Neither the name of VMware, Inc. nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 VMWARE, INC. OR 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. # Test suite script for DynamoRIO split into common pieces for re-use # by tools. # Usage: # 1) In tool test suite script, set the project name, src dir, # whether to run tests, and include the pre file: # set(CTEST_PROJECT_NAME "DynamoRIO") # set(cpack_project_name "DynamoRIO") # set(run_tests ON) # include("${PATH_TO_DR_EXPORTS}/cmake/runsuite_common_pre.cmake") # 2) Do any custom argument processing and setting of base_cache # or other vars. Can also do argument processing prior to # the pre include. # 3) Define function (error_string str outvar) # It should set ${outvar} in PARENT_SCOPE to the set # of specific errors found in ${str}. # 4) Define the build_package boolean and include the post script: # set(build_package ON) # include("${PATH_TO_DR_EXPORTS}/cmake/runsuite_common_post.cmake") # Also define build_source_package to build the package_source # CPack target (only for non-Visual Studio generators). # # extra_ctest_args can also be defined to pass extra args to ctest_test(), # such as INCLUDE_LABEL. # ARCH_IS_X86 is defined for running x86 specific tests. # Unfinished features in i#66 (now under i#121): # * have a list of known failures and label w/ " (known: i#XX)" cmake_minimum_required(VERSION 3.14) set(cmake_ver_string "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_RELEASE_VERSION}") # arguments are a ;-separated list (must escape as \; from ctest_run_script()) set(arg_nightly OFF) # whether to report the results set(arg_site "") # site to report results for (for nightly reported runs) set(arg_include "") # cmake file to include up front set(arg_preload "") # cmake file to include prior to each 32-bit build set(arg_preload64 "") # cmake file to include prior to each 64-bit build set(arg_ssh OFF) # running over cygwin ssh: disable pdbs set(arg_use_nmake OFF)# use nmake instead of visual studio set(arg_use_msbuild OFF) # use msbuild instead of devenv for visual studio if (UNIX) set(arg_use_make ON) # use unix make else (UNIX) set(arg_use_make OFF) # use unix make instead of visual studio endif (UNIX) set(arg_use_ninja OFF) # use ninja set(arg_generator "") # specify precise cmake generator (minus any "Win64") set(arg_long OFF) # whether to run the long suite set(arg_already_built OFF) # for testing w/ already-built suite set(arg_exclude "") # regex of tests to exclude set(arg_verbose OFF) # extra output set(arg_32_only OFF) # do not include 64-bit set(arg_64_only OFF) # do not include 64-bit set(arg_build_only OFF) # do not run tests foreach (arg ${CTEST_SCRIPT_ARG}) if (${arg} STREQUAL "nightly") set(arg_nightly ON) endif (${arg} STREQUAL "nightly") if (${arg} MATCHES "^site=") string(REGEX REPLACE "^site=" "" arg_site "${arg}") endif (${arg} MATCHES "^site=") if (${arg} MATCHES "^include=") string(REGEX REPLACE "^include=" "" arg_include "${arg}") endif (${arg} MATCHES "^include=") if (${arg} MATCHES "^preload=") string(REGEX REPLACE "^preload=" "" arg_preload "${arg}") endif (${arg} MATCHES "^preload=") if (${arg} MATCHES "^preload64=") string(REGEX REPLACE "^preload64=" "" arg_preload64 "${arg}") endif (${arg} MATCHES "^preload64=") if (${arg} STREQUAL "ssh") set(arg_ssh ON) endif (${arg} STREQUAL "ssh") if (${arg} STREQUAL "use_nmake") set(arg_use_nmake ON) endif () if (${arg} STREQUAL "use_msbuild") set(arg_use_msbuild ON) endif () if (${arg} STREQUAL "use_make") set(arg_use_make ON) endif () if (${arg} STREQUAL "use_ninja") set(arg_use_ninja ON) endif () if (${arg} STREQUAL "verbose") set(arg_verbose ON) endif () if (${arg} MATCHES "^generator=") string(REGEX REPLACE "^generator=" "" arg_generator "${arg}") endif () if (${arg} STREQUAL "long") set(arg_long ON) endif (${arg} STREQUAL "long") if (${arg} STREQUAL "already_built") set(arg_already_built ON) endif (${arg} STREQUAL "already_built") if (${arg} MATCHES "^exclude=") # not parallel to include=. this excludes individual tests. string(REGEX REPLACE "^exclude=" "" arg_exclude "${arg}") endif (${arg} MATCHES "^exclude=") if (${arg} MATCHES "^32_only") set(arg_32_only ON) endif () if (${arg} MATCHES "^64_only") set(arg_64_only ON) endif () if (${arg} MATCHES "^build_only") set(arg_build_only ON) endif () endforeach (arg) # Returns a list of environment variable names to set in ${env_names}. # For each "name" in the list, sets a variable "name_env_value" in the caller's # scope containing the value to be set. # # We'd like to export this via utils_exposed.cmake but it is difficult to # import it here from somewhere else. # Our manual INCLUDEFILE expansion would require all users to point to a # generated file somewhere, which requires updating all users including # Dr. Memory which today points directly at the embedded submodule sources. # Some of these uses have no build dir where a generated file could live. # Using include() is difficult for a file that is itself included, because # cmake won't search our same directory, and CTEST_SCRIPT_DIRECTORY is the # includer's directory, so we can't easily have side-by-side files. # For now we keep it here, and have the current only other use in # tests/CMakeLists.txt include() this file. function (_DR_set_VS_bitwidth_env_vars is64 env_names) # Convert env vars to run proper compiler. # Note that this is fragile and won't work with non-standard # directory layouts: we assume standard VS or SDK. # XXX: would be nice to have case-insensitive regex flag! # For now hardcoding VC, Bin, amd64 set(must_change_path OFF) if (is64) list(APPEND names_list "ASM") set(ASM_env_value "ml64" PARENT_SCOPE) if (NOT "$ENV{LIB}" MATCHES "[Aa][Mm][Dd]64" AND NOT "$ENV{LIB}" MATCHES "[Xx]64") set(must_change_path ON) # Note that we can't set ENV{PATH} as the output var of the replace: # it has to be its own set(). # # VS2017 has bin/HostX{86,64}/x{86,64}/ string(REGEX REPLACE "((^|;)[^;]*)HostX86([/\\\\])x86" "\\1HostX64\\3x64" newpath "$ENV{PATH}") # i#1421: VS2013 needs base VC/bin on the path (for cross-compiler # used by cmake) so we duplicate and put amd64 first. Older VS needs # Common7/IDE instead which should already be elsewhere on path. string(REGEX REPLACE "((^|;)[^;]*)VC([/\\\\])([Bb][Ii][Nn])" "\\1VC\\3\\4\\3amd64;\\1VC\\3\\4" newpath "${newpath}") # VS2008's SDKs/Windows/v{6.0A,7.0} uses "x64" instead of "amd64" string(REGEX REPLACE "([/\\\\]v[^/\\\\]*)([/\\\\])([Bb][Ii][Nn])" "\\1\\2\\3\\2x64" newpath "${newpath}") if (arg_verbose) message("Env setup: setting PATH to ${newpath}") endif () # VS2017 does not append so we replace first. string(REGEX REPLACE "([/\\\\])x86" "\\1x64" newlib "$ENV{lib}") # Now try to support pre-VS2017. string(REGEX REPLACE "([/\\\\])([Ll][Ii][Bb])([^/\\\\])" "\\1\\2\\1amd64\\3" newlib "${newlib}") # VS2008's SDKs/Windows/v{6.0A,7.0} uses "x64" instead of "amd64": grrr string(REGEX REPLACE "([/\\\\]v[^/\\\\]*[/\\\\][Ll][Ii][Bb][/\\\\])[Aa][Mm][Dd]64" "\\1x64" newlib "${newlib}") # Win8 SDK uses um/x86 and um/x64 after "Lib/win{8,v6.3}/" string(REGEX REPLACE "([Ll][Ii][Bb])[/\\\\]amd64([/\\\\][Ww][Ii][Nn][v0-9.]+[/\\\\]um[/\\\\])x86" "\\1\\2x64" newlib "${newlib}") if (arg_verbose) message("Env setup: setting LIB to ${newlib}") endif () string(REGEX REPLACE "([/\\\\])([Ll][Ii][Bb][/\\\\])[Xx]86" "\\1\\2" newlibpath "$ENV{LIBPATH}") string(REGEX REPLACE "([/\\\\])([Ll][Ii][Bb])" "\\1\\2\\1amd64" newlibpath "${newlibpath}") if (arg_verbose) message("Env setup: setting LIBPATH to ${newlibpath}") endif () endif () else (is64) list(APPEND ${env_names} "ASM") set(ASM_env_value "ml" PARENT_SCOPE) if ("$ENV{LIB}" MATCHES "[Aa][Mm][Dd]64" OR "$ENV{LIB}" MATCHES "[Xx]64") set(must_change_path ON) # VS2017 has bin/HostX{86,64}/x{86,64}/ string(REGEX REPLACE "((^|;)[^;]*)HostX64([/\\\\])x64" "\\1HostX86\\3x86" newpath "$ENV{PATH}") # Remove the duplicate we added (see i#1421 comment above). string(REGEX REPLACE "((^|;)[^;]*)VC[/\\\\][Bb][Ii][Nn][/\\\\][Aa][Mm][Dd]64" "" newpath "${newpath}") if (arg_verbose) message("Env setup: setting PATH to ${newpath}") endif () string(REGEX REPLACE "([Ll][Ii][Bb])[/\\\\][Aa][Mm][Dd]64" "\\1" newlib "$ENV{LIB}") string(REGEX REPLACE "([Ll][Ii][Bb][/\\\\])[Xx]64" "\\1x86" newlib "${newlib}") # Win8 SDK uses um/x86 and um/x64 string(REGEX REPLACE "([/\\\\]um[/\\\\])x64" "\\1x86" newlib "${newlib}") string(REGEX REPLACE "([/\\\\]ucrt[/\\\\])x64" "\\1x86" newlib "${newlib}") if (arg_verbose) message("Env setup: setting LIB to ${newlib}") endif () string(REGEX REPLACE "([Ll][Ii][Bb])[/\\\\][Aa][Mm][Dd]64" "\\1" newlibpath "$ENV{LIBPATH}") string(REGEX REPLACE "([Ll][Ii][Bb][/\\\\])[Xx]64" "\\1x86" newlibpath "${newlibpath}") if (arg_verbose) message("Env setup: setting LIBPATH to ${newlibpath}") endif () endif () endif (is64) if (must_change_path) list(APPEND names_list "PATH") set(PATH_env_value "${newpath}" PARENT_SCOPE) list(APPEND names_list "LIB") set(LIB_env_value "${newlib}" PARENT_SCOPE) list(APPEND names_list "LIBPATH") set(LIBPATH_env_value "${newlibpath}" PARENT_SCOPE) endif () set(${env_names} ${names_list} PARENT_SCOPE) endfunction () # allow setting the base cache variables via an include file set(base_cache "") if (arg_include) message("including ${arg_include}") include(${arg_include}) endif (arg_include) if (arg_ssh) # avoid problems creating pdbs as cygwin ssh user (i#310) set(base_cache "${base_cache} GENERATE_PDBS:BOOL=OFF") endif (arg_ssh) if (arg_use_make) find_program(MAKE_COMMAND make DOC "make command") if (NOT MAKE_COMMAND) message(FATAL_ERROR "make requested but make not found") endif (NOT MAKE_COMMAND) endif (arg_use_make) if (arg_use_ninja) find_program(NINJA_COMMAND ninja DOC "ninja command") if (NOT NINJA_COMMAND) message(FATAL_ERROR "ninja requested but ninja not found") endif (NOT NINJA_COMMAND) endif (arg_use_ninja) if (arg_long) set(TEST_LONG ON) else (arg_long) set(TEST_LONG OFF) endif (arg_long) if (WIN32) find_program(CYGPATH cygpath) if (CYGPATH) set(have_cygwin ON) else (CYGPATH) set(have_cygwin OFF) endif (CYGPATH) endif (WIN32) get_filename_component(BINARY_BASE "." ABSOLUTE) if (arg_nightly) # i#11: nightly run # Caller should have set CTEST_SITE via site= arg if (arg_site) set(CTEST_SITE "${arg_site}") else (arg_site) message(FATAL_ERROR "must set sitename via site= arg") endif (arg_site) set(CTEST_DASHBOARD_ROOT "${BINARY_BASE}") # We assume a manual check out was done, and that CTest can just do "update". # If we want a fresh checkout we can set CTEST_BACKUP_AND_RESTORE # and CTEST_CHECKOUT_COMMAND but the update should be fine. find_program(CTEST_UPDATE_COMMAND git DOC "source code update command") set(SUITE_TYPE Nightly) set(DO_UPDATE ON) set(DO_SUBMIT ON) set(SUBMIT_LOCAL OFF) else (arg_nightly) # a local run, not a nightly set(SUITE_TYPE Experimental) set(DO_UPDATE OFF) set(DO_SUBMIT ON) set(SUBMIT_LOCAL ON) # CTest does "scp file ${CTEST_DROP_SITE}:${CTEST_DROP_LOCATION}" so for # local copy w/o needing sshd on localhost we arrange to have : in the # absolute filepath. Note that I would prefer having the results inside # each build dir, but having : in the build dir name complicates # LD_LIBRARY_PATH. if (WIN32) # Colon not allowed in name so use drive string(REGEX MATCHALL "^[A-Za-z]" drive "${BINARY_BASE}") string(REGEX REPLACE "^[A-Za-z]:" "" nondrive "${BINARY_BASE}") set(CTEST_DROP_SITE "${drive}") set(CTEST_DROP_LOCATION "${nondrive}/xmlresults") set(RESULTS_DIR "${CTEST_DROP_SITE}:${CTEST_DROP_LOCATION}") else (WIN32) set(CTEST_DROP_SITE "${BINARY_BASE}/xml") set(CTEST_DROP_LOCATION "results") set(RESULTS_DIR "${CTEST_DROP_SITE}:${CTEST_DROP_LOCATION}") endif (WIN32) if (EXISTS "${RESULTS_DIR}") file(REMOVE_RECURSE "${RESULTS_DIR}") endif (EXISTS "${RESULTS_DIR}") file(MAKE_DIRECTORY "${CTEST_DROP_SITE}:${CTEST_DROP_LOCATION}") endif (arg_nightly) # Find the number of CPUs on the current system. # Cribbed from http://www.kitware.com/blog/home/post/63 if(NOT DEFINED PROCESSOR_COUNT) # Unknown: set(PROCESSOR_COUNT 4) # Guess # Linux: set(cpuinfo_file "/proc/cpuinfo") if(EXISTS "${cpuinfo_file}") file(STRINGS "${cpuinfo_file}" procs REGEX "^processor.: [0-9]+$") list(LENGTH procs PROCESSOR_COUNT) endif() # Mac: if(APPLE) find_program(cmd_sys_pro "system_profiler") if(cmd_sys_pro) execute_process(COMMAND ${cmd_sys_pro} SPHardwareDataType OUTPUT_VARIABLE info) string(REGEX REPLACE "^.*Total Number [Oo]f Cores: ([0-9]+).*$" "\\1" PROCESSOR_COUNT "${info}") endif() endif() # Windows: if(WIN32) if ($ENV{NUMBER_OF_PROCESSORS}) set(PROCESSOR_COUNT "$ENV{NUMBER_OF_PROCESSORS}") endif () endif() endif() math(EXPR PARALLEL_COUNT_BUILD "${PROCESSOR_COUNT} + 2") # Typically no benefit and sometimes detrimental to exceed core count here math(EXPR PARALLEL_COUNT_TEST "${PROCESSOR_COUNT}") # CTest goes and does our builds and then wants to configure # and build again and complains there's no top-level setting of # CTEST_BINARY_DIRECTORY: # "CMake Error: Some required settings in the configuration file were missing:" # but we don't want to do another build so we just ignore the error. set(CTEST_CMAKE_COMMAND "${CMAKE_EXECUTABLE_NAME}") # outer file should set CTEST_PROJECT_NAME set(CTEST_COMMAND "${CTEST_EXECUTABLE_NAME}") # Raise the default of 50 to avoid warnings blocking the detection of # build failures (i#1137): set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS 200) set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS 200) # Detect if the arch is x86 if (NOT DEFINED ARCH_IS_X86) if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm|aarch64)") set(ARCH_IS_X86 OFF) else () set(ARCH_IS_X86 ON) endif () endif () # Detect if the kernel is ia32 or x64. If the kernel is ia32, there's no sense # in trying to run any x64 code. On Windows, the x64 toolchain is built as x64 # code, so we can't even build. On Linux, it's possible to have an ia32 # toolchain that targets x64, but we don't currently support it. if (NOT DEFINED KERNEL_IS_X64) # Allow variable override. if (WIN32) # Check both PROCESSOR_ARCHITECTURE and PROCESSOR_ARCHITEW6432 in case CMake # was built x64. if ("$ENV{PROCESSOR_ARCHITECTURE}" MATCHES "AMD64" OR "$ENV{PROCESSOR_ARCHITEW6432}" MATCHES "AMD64") set(KERNEL_IS_X64 ON) else () set(KERNEL_IS_X64 OFF) endif () else () # uname -m is what the kernel supports. execute_process(COMMAND uname -m OUTPUT_VARIABLE machine RESULT_VARIABLE cmd_result) # If for some reason uname fails (not on PATH), assume the kernel is x64 # anyway. if (cmd_result OR "${machine}" MATCHES "x86_64|aarch64|arm64") set(KERNEL_IS_X64 ON) else () set(KERNEL_IS_X64 OFF) endif () endif () endif () if (NOT KERNEL_IS_X64) message("WARNING: Kernel is not x64, skipping x64 builds") endif () # Make it clear that single-bitwidth packages only contain that bitwidth # (and provide unique names for CI deployment). # Also set aarchxx names when not doing cross-compilation which sets # them ahead of time. if (NOT "${base_cache}" MATCHES "PACKAGE_PLATFORM:STRING=[A-Za-z]" AND NOT "${base_cache}" MATCHES "PACKAGE_PLATFORM=[A-Za-z]") if (arg_64_only) if ("${machine}" MATCHES "aarch64|arm64") set(base_cache "${base_cache} PACKAGE_PLATFORM:STRING=AArch64-") else () set(base_cache "${base_cache} PACKAGE_PLATFORM:STRING=x86_64-") endif () elseif (arg_32_only) if ("${machine}" MATCHES "aarch32|arm") set(base_cache "${base_cache} PACKAGE_PLATFORM:STRING=ARM- PACKAGE_SUBSYS:STRING=-EABIHF") else () set(base_cache "${base_cache} PACKAGE_PLATFORM:STRING=i386-") endif () endif () endif () if (arg_use_ninja) set(CTEST_CMAKE_GENERATOR "Ninja") elseif (arg_use_make) set(CTEST_CMAKE_GENERATOR "Unix Makefiles") find_program(MAKE_COMMAND make DOC "make command") if (have_cygwin) # seeing errors building in parallel: pdb collision? # can't repro w/ VERBOSE=1 set(CTEST_BUILD_COMMAND_BASE "${MAKE_COMMAND} -j2") else (have_cygwin) set(CTEST_BUILD_COMMAND_BASE "${MAKE_COMMAND} -j${PARALLEL_COUNT_BUILD}") endif (have_cygwin) elseif (arg_use_nmake) set(CTEST_CMAKE_GENERATOR "NMake Makefiles") else () if (arg_generator) set(vs_generator ${arg_generator}) else () set(vs_generator "NOTFOUND") get_filename_component(current_directory_path "${CMAKE_CURRENT_LIST_FILE}" PATH) include(${current_directory_path}/lookup_visualstudio.cmake) get_visualstudio_info(vs_dir vs_version vs_generator) if (NOT vs_generator) message(FATAL_ERROR "Cannot determine Visual Studio version") endif () endif () message(STATUS "Using ${vs_generator} generators") if (arg_use_msbuild) find_program(MSBUILD_PROGRAM msbuild) if (MSBUILD_PROGRAM) set(base_cache "${base_cache} CMAKE_MAKE_PROGRAM:FILEPATH=${MSBUILD_PROGRAM}") # Unfortunately we have to provide all the args (setting CMAKE_MAKE_PROGRAM # doesn't do it for ctest builds). We want ALL_BUILD.vcproj for pre-VS2010 # and ALL_BUILD.vcxproj for VS2010. if (vs_generator MATCHES "Visual Studio 1.") set(proj_file "ALL_BUILD.vcxproj") else () set(proj_file "ALL_BUILD.vcproj") endif () # Request parallel build on all available cores (sequential by default: i#800) # via "/m". # Configuration will be adjusted per build below. set(CTEST_BUILD_COMMAND "${MSBUILD_PROGRAM} ${proj_file} /p:Configuration=REPLACE_CONFIG /m") else (MSBUILD_PROGRAM) message("WARNING: cannot find msbuild; disabling") set(arg_use_msbuild OFF) endif (MSBUILD_PROGRAM) endif (arg_use_msbuild) endif () function(get_default_config config builddir) file(READ "${builddir}/CMakeCache.txt" cache) string(REGEX MATCH "CMAKE_CONFIGURATION_TYPES:STRING=([^\n]*)" cache "${cache}") string(REGEX REPLACE "CMAKE_CONFIGURATION_TYPES:STRING=([^;]*)" "\\1" cache "${cache}") set(${config} ${cache} PARENT_SCOPE) endfunction(get_default_config) # Sets two vars in PARENT_SCOPE: # + returns the build dir in "last_build_dir" # + for each build for which add_to_package is true: # - returns the build dir in "last_package_build_dir" # - adds to "cpack_projects" for project "${cpack_project_name}" # (set by outer file) function(testbuild_ex name is64 initial_cache test_only_in_long add_to_package build_args) set(CTEST_BUILD_NAME "${name}") # Skip x64 builds on a true ia32 machine. if (is64 AND NOT KERNEL_IS_X64) return() endif () if (is64 AND arg_32_only) return() endif () if (NOT is64 AND arg_64_only) return() endif () # Skip 32-bit builds on an AArch64 machine. if (NOT is64 AND CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") return() endif () if (NOT arg_use_nmake AND NOT arg_use_make AND NOT arg_use_ninja) # we need a separate generator for 64-bit as well as the PATH # env var changes below (since we run cl directly) if (is64) set(CTEST_CMAKE_GENERATOR "${vs_generator} Win64") else (is64) set(CTEST_CMAKE_GENERATOR "${vs_generator}") endif (is64) # we need to set this for the package build using the last build set(CTEST_CMAKE_GENERATOR "${CTEST_CMAKE_GENERATOR}" PARENT_SCOPE) endif () set(CTEST_BINARY_DIRECTORY "${BINARY_BASE}/build_${CTEST_BUILD_NAME}") set(last_build_dir "${CTEST_BINARY_DIRECTORY}" PARENT_SCOPE) if (NOT arg_already_built) # Support other VC installations than VS2005 via pre-build include file. # Preserve path so include file can simply prepend each time. set(pre_path "$ENV{PATH}") set(pre_lib "$ENV{LIB}") if (is64) set(preload_file "${arg_preload64}") else (is64) set(preload_file "${arg_preload}") endif (is64) if (preload_file) # Command-style CTest (i.e., using ctest_configure(), etc.) does # not support giving args to CTEST_CMAKE_COMMAND so we are forced # to do an include() instead of -C include("${preload_file}") endif (preload_file) if (WIN32) # i#111: Disabling progress and status messages can speed the Windows build # up by up to 50%. I filed CMake bug 8726 on this and this variable will be # in the 2.8 release; going ahead and setting now. # For Linux these messages make little perf difference, and can help # diagnose errors or watch progress. # The messages only apply to Makefile generators, not Visual Studio. if (NOT "${CTEST_CMAKE_GENERATOR}" MATCHES "Visual Studio") set(os_specific_defines "CMAKE_RULE_MESSAGES:BOOL=OFF") endif () else (WIN32) set(os_specific_defines "") endif (WIN32) set(CTEST_INITIAL_CACHE "${initial_cache} TEST_SUITE:BOOL=ON ${os_specific_defines} ${base_cache} ") ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" "${CTEST_INITIAL_CACHE}") if (WIN32) # If other compilers also on path ensure we pick cl set(ENV{CC} "cl") set(ENV{CXX} "cl") # Convert env vars to run proper compiler. _DR_set_VS_bitwidth_env_vars(${is64} env_names) foreach (env ${env_names}) set(ENV{${env}} "${${env}_env_value}") endforeach () else (WIN32) if (ARCH_IS_X86) if (is64) set(ENV{CFLAGS} "-m64") set(ENV{CXXFLAGS} "-m64") else (is64) set(ENV{CFLAGS} "-m32") set(ENV{CXXFLAGS} "-m32") endif (is64) endif (ARCH_IS_X86) endif (WIN32) else (NOT arg_already_built) # remove the Last* files from the prior run file(GLOB lastrun ${CTEST_BINARY_DIRECTORY}/Testing/Temporary/Last*) if (lastrun) file(REMOVE ${lastrun}) endif (lastrun) endif (NOT arg_already_built) ctest_start(${SUITE_TYPE}) if (NOT arg_already_built) if (DO_UPDATE) ctest_update(SOURCE "${CTEST_SOURCE_DIRECTORY}") endif (DO_UPDATE) ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE config_success) if (config_success EQUAL 0) # support "make install" if (DEFINED CTEST_BUILD_COMMAND_BASE) set(CTEST_BUILD_COMMAND "${CTEST_BUILD_COMMAND_BASE} ${build_args}") else () # else use default if ("${CTEST_CMAKE_GENERATOR}" MATCHES "Visual Studio") # workaround for cmake bug #11830 where assumes "Debug" is # the default config get_default_config(defconfig "${CTEST_BINARY_DIRECTORY}") set(CTEST_BUILD_CONFIGURATION "${defconfig}") message("building default config \"${defconfig}\"") if (NOT "${build_args}" STREQUAL "" OR NOT "${extra_build_args}" STREQUAL "") set(CTEST_BUILD_FLAGS "-- ${extra_build_args} ${build_args}") endif () if (arg_use_msbuild) string(REPLACE "REPLACE_CONFIG" "${defconfig}" CTEST_BUILD_COMMAND "${CTEST_BUILD_COMMAND}") endif (arg_use_msbuild) else () set(CTEST_BUILD_FLAGS "${build_args}") endif () message("building with args \"${CTEST_BUILD_FLAGS}\"") endif () ctest_build(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE build_success) else (config_success EQUAL 0) set(build_success -1) if (optional_cross_compile) # XXX: for platforms requiring special hardware such as ARM, this global indicates # an optional cross-compilation, for use on more common platforms like x86 Unix # (would use a parameter instead of a global, except for backward compatibility) file(GLOB last_config ${CTEST_BINARY_DIRECTORY}/Testing/*/*.xml) if (last_config) file(REMOVE ${last_config}) endif (last_config) set(DO_SUBMIT OFF) message("Warning: optional cross-compilation \"${name}\" is not available" "--skipping") set(add_to_package OFF) file(WRITE ${CTEST_BINARY_DIRECTORY}/Testing/missing-cross-compile "${name}") endif (optional_cross_compile) endif (config_success EQUAL 0) else (NOT arg_already_built) set(build_success 0) endif (NOT arg_already_built) if (build_success EQUAL 0 AND run_tests AND NOT arg_build_only) if (NOT test_only_in_long OR ${TEST_LONG}) # to run a subset of tests add an INCLUDE regexp to ctest_test. e.g.: # INCLUDE broadfun if (NOT "${arg_exclude}" STREQUAL "") set(ctest_test_args ${ctest_test_args} EXCLUDE ${arg_exclude}) endif (NOT "${arg_exclude}" STREQUAL "") set(ctest_test_args ${ctest_test_args} ${extra_ctest_args}) if ("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.17") # CMake 3.17 supports retrying failed tests. We avoid flaky tests on # particular platforms failing the whole suite by trying multiple times. set(ctest_test_args ${ctest_test_args} "REPEAT" "UNTIL_PASS:3") endif () if (WIN32 AND TEST_LONG) # XXX i#265: on Windows we can't run multiple instances of # the same app b/c of global reg key conflicts: should support # env vars and not require registry set(RUN_PARALLEL OFF) else () set(RUN_PARALLEL ON) endif () if (RUN_PARALLEL) # i#111: run tests in parallel, supported on CTest 2.8.0+ # Note that adding -j to CMAKE_COMMAND does not work, though invoking # this script with -j does work, but we want parallel by default. ctest_test(BUILD "${CTEST_BINARY_DIRECTORY}" PARALLEL_LEVEL ${PARALLEL_COUNT_TEST} ${ctest_test_args}) else (RUN_PARALLEL) ctest_test(BUILD "${CTEST_BINARY_DIRECTORY}" ${ctest_test_args}) endif (RUN_PARALLEL) endif (NOT test_only_in_long OR ${TEST_LONG}) endif (build_success EQUAL 0 AND run_tests AND NOT arg_build_only) if (DO_SUBMIT) if (CTEST_DROP_METHOD MATCHES "http") # include any notes via set(CTEST_NOTES_FILES )? ctest_submit() else () # We used to use the "scp" (could also have used "cp") drop method # to copy these xml files out for us, but cmake 3.14 dropped that. # Thus we copy them ourselves. file(GLOB xml_files "${CTEST_BINARY_DIRECTORY}/Testing/*/*.xml") set(prefix "___${CTEST_BUILD_NAME}___${SUITE_TYPE}___XML___") foreach (xml ${xml_files}) get_filename_component(base "${xml}" NAME) # Avoid confusion with a later package build in the same dir by # renaming instead of copying. file(RENAME "${xml}" "${CTEST_DROP_SITE}:${CTEST_DROP_LOCATION}/${prefix}${base}") message("Moving ${xml} to " "${CTEST_DROP_SITE}:${CTEST_DROP_LOCATION}/${prefix}${base}") endforeach () endif () endif (DO_SUBMIT) if (NOT arg_already_built) set(ENV{PATH} "${pre_path}") set(ENV{LIB} "${pre_lib}") endif (NOT arg_already_built) if (add_to_package) # support having the suite test building the full package # XXX: perhaps should replace package.cmake w/ invocation of runsuite.cmake # w/ certain params, since they're pretty similar at this point? # communicate w/ caller set(last_package_build_dir "${CTEST_BINARY_DIRECTORY}" PARENT_SCOPE) if (CTEST_BINARY_DIRECTORY MATCHES "debug") # prepend rather than append to get debug first, so we take release # files preferentially in case of overlap set(cpack_projects "\"${CTEST_BINARY_DIRECTORY};${cpack_project_name};ALL;/\"\n ${cpack_projects}" PARENT_SCOPE) else () set(cpack_projects "${cpack_projects}\n \"${CTEST_BINARY_DIRECTORY};${cpack_project_name};ALL;/\"" PARENT_SCOPE) endif () if ("${CTEST_CMAKE_GENERATOR}" MATCHES "Visual Studio") # i#390: workaround for cpack limitation where cpack is run w/ # one config and each build's install rules check only for their # own config. we change each config check to "TRUE OR ". file(READ "${CTEST_BINARY_DIRECTORY}/cmake_install.cmake" str) # grab first-level includes string(REGEX MATCHALL "INCLUDE\\\(\"[^\"]+\"" includes "${str}") string(REGEX REPLACE "INCLUDE\\\(\"([^\"]+)\"" "\\1" includes "${includes}") # grab second-level includes set(includes2nd ) foreach (config ${includes}) file(READ "${config}" str) string(REGEX MATCHALL "INCLUDE\\\(\"[^\"]+\"" newincs "${str}") string(REGEX REPLACE "INCLUDE\\\(\"([^\"]+)\"" "\\1" newincs "${newincs}") set(includes2nd ${includes2nd} ${newincs}) endforeach (config) # now process each foreach (config "${CTEST_BINARY_DIRECTORY}/cmake_install.cmake" ${includes} ${includes2nd}) file(READ "${config}" str) string(REGEX REPLACE "IF\\\((\"\\\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES)" "IF(TRUE OR \\1" str "${str}") # set CMP0012 policy to treat TRUE as literal file(WRITE "${config}" "cmake_policy(VERSION 2.8)\n${str}") endforeach (config) endif () endif (add_to_package) endfunction(testbuild_ex) function(testbuild name is64 initial_cache) # by default run all tests and do not include in package testbuild_ex(${name} ${is64} ${initial_cache} OFF OFF "") # propagate set(last_build_dir "${last_build_dir}" PARENT_SCOPE) set(last_package_build_dir "${last_package_build_dir}" PARENT_SCOPE) set(cpack_projects "${cpack_projects}" PARENT_SCOPE) endfunction(testbuild)