function(run_make_program dir) execute_process( COMMAND "${RunCMake_MAKE_PROGRAM}" ${ARGN} WORKING_DIRECTORY "${dir}" OUTPUT_VARIABLE make_program_stdout ERROR_VARIABLE make_program_stderr RESULT_VARIABLE make_program_result ) if (NOT DEFINED RunMakeProgram_expected_result) set(RunMakeProgram_expected_result 0) endif() if(NOT "${make_program_result}" MATCHES "${RunMakeProgram_expected_result}") message(STATUS " ============ beginning of ${RunCMake_MAKE_PROGRAM}'s stdout ============ ${make_program_stdout} =============== end of ${RunCMake_MAKE_PROGRAM}'s stdout =============== ") message(STATUS " ============ beginning of ${RunCMake_MAKE_PROGRAM}'s stderr ============ ${make_program_stderr} =============== end of ${RunCMake_MAKE_PROGRAM}'s stderr =============== ") message(FATAL_ERROR "top ${RunCMake_MAKE_PROGRAM} build failed exited with status ${make_program_result}") endif() set(make_program_stdout "${make_program_stdout}" PARENT_SCOPE) endfunction(run_make_program) function(count_substring STRING SUBSTRING COUNT_VAR) string(LENGTH "${STRING}" STRING_LENGTH) string(LENGTH "${SUBSTRING}" SUBSTRING_LENGTH) if (SUBSTRING_LENGTH EQUAL 0) message(FATAL_ERROR "SUBSTRING_LENGTH is 0") endif() if (STRING_LENGTH EQUAL 0) message(FATAL_ERROR "STRING_LENGTH is 0") endif() if (STRING_LENGTH LESS SUBSTRING_LENGTH) message(FATAL_ERROR "STRING_LENGTH is less than SUBSTRING_LENGTH") endif() set(COUNT 0) string(FIND "${STRING}" "${SUBSTRING}" SUBSTRING_START) while(SUBSTRING_START GREATER_EQUAL 0) math(EXPR COUNT "${COUNT} + 1") math(EXPR SUBSTRING_START "${SUBSTRING_START} + ${SUBSTRING_LENGTH}") string(SUBSTRING "${STRING}" ${SUBSTRING_START} -1 STRING) string(FIND "${STRING}" "${SUBSTRING}" SUBSTRING_START) endwhile() set(${COUNT_VAR} ${COUNT} PARENT_SCOPE) endfunction() function(not_expect make_program_stdout unexpected_output test_name) count_substring("${make_program_stdout}" "${unexpected_output}" count) if(NOT count EQUAL 0) message(STATUS "${test_name}-not_expect - FAILED") message(FATAL_ERROR "Expected to find ${unexpected_output} exactly 0 times in ${make_program_stdout} but found ${count} occurrences of ${unexpected_output}") else() message(STATUS "${test_name}-not_expect - PASSED") endif() endfunction() function(expect_only_once make_program_stdout expected_output test_name) count_substring("${make_program_stdout}" "${expected_output}" count) if(NOT count EQUAL 1) message(STATUS "${test_name}-expect_only_once - FAILED") message(FATAL_ERROR "Expected to find ${expected_output} exactly once in ${make_program_stdout} but found ${count} occurrences of ${expected_output}") else() message(STATUS "${test_name}-expect_only_once - PASSED") endif() endfunction() function(expect_n_times string_to_check expected_output expected_count test_name) count_substring("${string_to_check}" "${expected_output}" count) if(NOT count EQUAL ${expected_count}) message(STATUS "${test_name}-expect_${expected_count}_times - FAILED") message(FATAL_ERROR "Expected to find ${expected_output} exactly ${expected_count} times in ${string_to_check} but found ${count} occurrences of ${expected_output}") else() message(STATUS "${test_name}-expect_${expected_count}_times - PASSED") endif() endfunction() function(autogen_executable_test exe) if (QtCore_VERSION VERSION_GREATER_EQUAL 5.15.0) if(RunCMake_GENERATOR MATCHES "Ninja Multi-Config") block() set(RunCMake_TEST_VARIANT_DESCRIPTION "-CMake-configure") set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig-multi-config-build) run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON -DCMAKE_AUTOGEN_BETTER_GRAPH_MULTI_CONFIG=ON) unset(RunCMake_TEST_VARIANT_DESCRIPTION) set(RunCMake_TEST_NO_CLEAN 1) foreach(config IN ITEMS Debug Release RelWithDebInfo) block() set(RunCMake_TEST_EXPECT_stdout ".*running_exe_${config}*") set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}-expect_running_exe_${config}") run_cmake_command(Auto${exe}ExecutableConfig-multi-config-build ${CMAKE_COMMAND} --build . --config ${config}) endblock() endforeach() set(RunCMake_TEST_EXPECT_stdout "ninja: no work to do") foreach(config IN ITEMS Debug Release RelWithDebInfo) block() set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}-expect_no_work_to_do") run_cmake_command(Auto${exe}ExecutableConfig-multi-config-build ${CMAKE_COMMAND} --build . --config ${config}) endblock() endforeach() endblock() block() set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig-build) run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON -DCMAKE_AUTOGEN_BETTER_GRAPH_MULTI_CONFIG=ON) foreach(config IN ITEMS Debug Release RelWithDebInfo) block() run_make_program(${RunCMake_TEST_BINARY_DIR} --verbose -f build-${config}.ninja) set(expected_output "running_exe_${config}") expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig-${config}-${expected_output}") foreach(sub_config IN ITEMS Debug Release RelWithDebInfo) if(NOT sub_config STREQUAL config) set(unexpected_output "running_exe_${sub_config}") not_expect("${make_program_stdout}" "${unexpected_output}" "Auto${exe}ExecutableConfig-${config}-${unexpected_output}") endif() endforeach() if (exe STREQUAL "Moc" OR exe STREQUAL "Uic") set(expected_output "cmake_autogen") else() set(expected_output "cmake_autorcc") endif() expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig-${config}-${expected_output}") endblock() endforeach() endblock() block() foreach(ninja_config IN ITEMS Debug Release RelWithDebInfo) foreach(target_config IN ITEMS Debug Release RelWithDebInfo) block() set(TEST_SUFFIX "-CrossConfig-${ninja_config}-${target_config}") set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig${TEST_SUFFIX}-build) set(RunCMake_TEST_VARIANT_DESCRIPTION ${TEST_SUFFIX}) run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=${ninja_config} -DCMAKE_AUTOGEN_BETTER_GRAPH_MULTI_CONFIG=ON) unset(RunCMake_TEST_VARIANT_DESCRIPTION) run_make_program(${RunCMake_TEST_BINARY_DIR} --verbose -f build-${ninja_config}.ninja dummy:${target_config}) set(expected_output "running_exe_${ninja_config}") expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig${TEST_SUFFIX}-${expected_output}") foreach(sub_config IN ITEMS Debug Release RelWithDebInfo) if(NOT sub_config STREQUAL ninja_config) set(unexpected_output "running_exe_${sub_config}") not_expect("${make_program_stdout}" "${unexpected_output}" "Auto${exe}ExecutableConfig${TEST_SUFFIX}-${unexpected_output}") endif() endforeach() if (exe STREQUAL "Moc" OR exe STREQUAL "Uic") set(expected_output "cmake_autogen") else() set(expected_output "cmake_autorcc") endif() expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig${TEST_SUFFIX}-${expected_output}") endblock() endforeach() endforeach() endblock() block() foreach(ninja_config IN ITEMS Debug Release RelWithDebInfo) set(TEST_SUFFIX "-CrossConfig-${ninja_config}-all-all") set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig${TEST_SUFFIX}-build) set(RunCMake_TEST_VARIANT_DESCRIPTION ${TEST_SUFFIX}) run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_CROSS_CONFIGS=all -DCMAKE_AUTOGEN_BETTER_GRAPH_MULTI_CONFIG=ON) unset(RunCMake_TEST_VARIANT_DESCRIPTION) run_make_program(${RunCMake_TEST_BINARY_DIR} --verbose -f build-${ninja_config}.ninja all:all) endforeach() endblock() elseif (RunCMake_GENERATOR MATCHES "Ninja|Make") block() set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig-build) foreach(config IN ITEMS Debug Release RelWithDebInfo) block() set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}") run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_BUILD_TYPE=${config} -DCMAKE_AUTOGEN_VERBOSE=ON) unset(RunCMake_TEST_VARIANT_DESCRIPTION) set(RunCMake_TEST_NO_CLEAN 1) set(RunCMake_TEST_EXPECT_stdout ".*running_exe_${config}*") run_cmake_command(Auto${exe}ExecutableConfig-${config}-build ${CMAKE_COMMAND} --build .) endblock() endforeach() endblock() endif() endif() # Visual Studio specific dependency tests if (RunCMake_GENERATOR MATCHES "Visual Studio") block() set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${exe}Example-build) set(RunCMake_TEST_VARIANT_DESCRIPTION "-CMake-configure") run_cmake_with_options(${exe}Example ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON) unset(RunCMake_TEST_VARIANT_DESCRIPTION) set(RunCMake_TEST_NO_CLEAN 1) foreach(config IN ITEMS Debug Release RelWithDebInfo) block() set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}-first-build") run_cmake_command(${exe}Example-build ${CMAKE_COMMAND} --build . --config ${config}) endblock() endforeach() foreach(config IN ITEMS Debug Release RelWithDebInfo) block() if (exe STREQUAL "Moc" OR exe STREQUAL "Uic") set(RunCMake_TEST_NOT_EXPECT_stdout "Auto${exe}") set(not_expect_descripton "Auto${exe}") else () set(RunCMake_TEST_NOT_EXPECT_stdout "Auto${exe}") set(not_expect_descripton "Auto${exe}") endif() set(RunCMake_TEST_VARIANT_DESCRIPTION "-second-build-${config}_expect_no_${not_expect_descripton}") run_cmake_command(${exe}Example-build ${CMAKE_COMMAND} --build . --config ${config}) endblock() endforeach() endblock() endif() if (RunCMake_GENERATOR MATCHES "Xcode") block() set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${exe}Example-build) set(RunCMake_TEST_VARIANT_DESCRIPTION "-CMake-configure") set(RunCMake_TEST_EXPECT_stderr ".*") run_cmake_with_options(${exe}Example ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON) set(RunCMake_TEST_NO_CLEAN 1) set(RunCMake_MAKE_PROGRAM ${CMAKE_COMMAND}) run_make_program(${RunCMake_TEST_BINARY_DIR} --build . --config Debug) if (exe STREQUAL "Moc") set(expected_count 4) elseif (exe STREQUAL "Uic") set(expected_count 1) else() set(expected_count 12) endif() expect_n_times("${make_program_stdout}" "Auto${exe}:" ${expected_count} "${exe}Example-build-Auto${exe}") if (exe STREQUAL "Moc" OR exe STREQUAL "Uic") expect_n_times("${make_program_stdout}" "AutoGen:" 5 "${exe}Example-build-AutoGen:") endif() foreach(config IN ITEMS Release RelWithDebInfo) block() # Note: We expect to see Auto${exe} or AutoGen in the output for # moc and uic because they should be triggered per configuration. # For rcc, we don't expect to see Auto${exe} or AutoGen in the output # because all configurations trigger with the first configuration. run_make_program(${RunCMake_TEST_BINARY_DIR} --build . --config ${config}) if (exe STREQUAL "Moc" OR exe STREQUAL "Uic") expect_n_times("${make_program_stdout}" "Auto${exe}:" ${expected_count} "${exe}Example-build-${config}-Auto${exe}") expect_n_times("${make_program_stdout}" "AutoGen" 5 "${exe}Example-build-${config}-AutoGen:") else() not_expect("${make_program_stdout}" "Auto${exe}" "${exe}Example-build-${config}_Auto${exe}") not_expect("${make_program_stdout}" "AutoGen" "${exe}Example-build-${config}_AutoGen") endif() endblock() endforeach() endblock() endif() endfunction()