if(NOT DEFINED CMake_SOURCE_DIR) message(FATAL_ERROR "CMake_SOURCE_DIR not defined") endif() if(NOT DEFINED dir) message(FATAL_ERROR "dir not defined") endif() if(NOT DEFINED gen) message(FATAL_ERROR "gen not defined") endif() # Call cmake once to get a baseline/reference output build tree: "Build". # Then call cmake N more times, each time making a copy of the entire # build tree after cmake is done configuring/generating. At the end, # analyze the diffs in the generated build trees. Expect no diffs. # message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)") set(N 7) # First setup source and binary trees: # execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf ${dir}/Source ) execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf ${dir}/Build ) execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMake_SOURCE_DIR}/Tests/CTestTest/SmallAndFast ${dir}/Source ) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${dir}/Build ) # Patch SmallAndFast to build a .cxx executable too: # execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${dir}/Source/echoargs.c ${dir}/Source/echoargs.cxx ) file(APPEND "${dir}/Source/CMakeLists.txt" "\nadd_executable(echoargsCXX echoargs.cxx)\n") # Loop N times, saving a copy of the configured/generated build tree each time: # foreach(i RANGE 1 ${N}) # Equivalent sequence of shell commands: # message(STATUS "${i}: cd Build && cmake -G \"${gen}\" ../Source && cd .. && cp -r Build b${i}") # Run cmake: # execute_process(COMMAND ${CMAKE_COMMAND} -G ${gen} ../Source RESULT_VARIABLE result OUTPUT_VARIABLE stdout ERROR_VARIABLE stderr WORKING_DIRECTORY ${dir}/Build ) message(STATUS "result='${result}'") message(STATUS "stdout='${stdout}'") message(STATUS "stderr='${stderr}'") message(STATUS "") # Save this iteration of the Build directory: # execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf ${dir}/b${i} ) execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${dir}/Build ${dir}/b${i} RESULT_VARIABLE result OUTPUT_VARIABLE stdout ERROR_VARIABLE stderr ) message(STATUS "result='${result}'") message(STATUS "stdout='${stdout}'") message(STATUS "stderr='${stderr}'") message(STATUS "") endforeach() # Function to analyze diffs between two directories. # Set DIFF_EXECUTABLE before calling if 'diff' is available. # function(analyze_directory_diffs d1 d2 diff_count_var) set(diffs 0) message(STATUS "Analyzing directory diffs between:") message(STATUS " d1='${d1}'") message(STATUS " d2='${d2}'") if(NOT "${d1}" STREQUAL "" AND NOT "${d2}" STREQUAL "") message(STATUS "info: analyzing directories") file(GLOB_RECURSE files1 RELATIVE "${d1}" "${d1}/*") file(GLOB_RECURSE files2 RELATIVE "${d2}" "${d2}/*") if("${files1}" STREQUAL "${files2}") message(STATUS "info: file lists the same") #message(STATUS " files='${files1}'") foreach(f ${files1}) execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files ${d1}/${f} ${d2}/${f} RESULT_VARIABLE result OUTPUT_VARIABLE stdout ERROR_VARIABLE stderr ) if(result STREQUAL 0) #message(STATUS "info: file '${f}' the same") else() math(EXPR diffs "${diffs} + 1") message(STATUS "warning: file '${f}' differs from d1 to d2") file(READ "${d1}/${f}" f1contents) message(STATUS "contents of file '${d1}/${f}' [===[${f1contents}]===]") file(READ "${d2}/${f}" f2contents) message(STATUS "contents of file '${d2}/${f}' [===[${f2contents}]===]") if(DIFF_EXECUTABLE) message(STATUS "diff of files '${d1}/${f}' '${d2}/${f}'") message(STATUS "[====[") execute_process(COMMAND ${DIFF_EXECUTABLE} "${d1}/${f}" "${d2}/${f}") message(STATUS "]====]") endif() endif() endforeach() else() math(EXPR diffs "${diffs} + 1") message(STATUS "warning: file *lists* differ - some files exist in d1/not-d2 or not-d1/d2...") message(STATUS " files1='${files1}'") message(STATUS " files2='${files2}'") endif() endif() set(${diff_count_var} ${diffs} PARENT_SCOPE) endfunction() # Analyze diffs between b1:b2, b2:b3, b3:b4, b4:b5 ... bN-1:bN. # Expect no diffs. # find_program(DIFF_EXECUTABLE diff) set(total_diffs 0) foreach(i RANGE 2 ${N}) math(EXPR prev "${i} - 1") set(count 0) analyze_directory_diffs(${dir}/b${prev} ${dir}/b${i} count) message(STATUS "diff count='${count}'") message(STATUS "") math(EXPR total_diffs "${total_diffs} + ${count}") endforeach() message(STATUS "CMAKE_COMMAND='${CMAKE_COMMAND}'") message(STATUS "total_diffs='${total_diffs}'")