diff --git a/.github/workflows/arm.yml b/.github/workflows/arm.yml index 4e71c907ebd..c683b3c52de 100644 --- a/.github/workflows/arm.yml +++ b/.github/workflows/arm.yml @@ -174,9 +174,14 @@ jobs: c++ --version cmake --version - ctest -S ${{ github.workspace }}/ITK-dashboard/dashboard.cmake -VV -j ${{ matrix.parallel-level }} ${{ matrix.ctest-options }} + ctest -S ${{ github.workspace }}/ITK-dashboard/dashboard.cmake -V -j ${{ matrix.parallel-level }} ${{ matrix.ctest-options }} env: CTEST_OUTPUT_ON_FAILURE: 1 + + - name: Report build warnings and errors + if: always() + run: python3 ${{ github.workspace }}/Testing/ContinuousIntegration/report_build_diagnostics.py ${{ github.workspace }}/build + - name: Save compiler cache if: ${{ !cancelled() }} uses: actions/cache/save@v5 diff --git a/Modules/Core/Common/src/itkObject.cxx b/Modules/Core/Common/src/itkObject.cxx index 01c01d61c88..41807b7919e 100644 --- a/Modules/Core/Common/src/itkObject.cxx +++ b/Modules/Core/Common/src/itkObject.cxx @@ -33,6 +33,10 @@ namespace itk { +// WIP: Deliberate unused variable to generate a compiler warning. +// This is a test artifact for PR #5971 and must NOT be merged. +static int deliberately_unused_variable_for_ci_test = 42; + /** * Initialize static member that controls warning display. */ diff --git a/Modules/Core/Common/test/itkPointGeometryTest.cxx b/Modules/Core/Common/test/itkPointGeometryTest.cxx index e5bb6b24c02..2fefe5fc0b2 100644 --- a/Modules/Core/Common/test/itkPointGeometryTest.cxx +++ b/Modules/Core/Common/test/itkPointGeometryTest.cxx @@ -297,5 +297,12 @@ itkPointGeometryTest(int, char *[]) std::cout << "Test for Barycentric combination of a VectorContainer of Points PASSED" << std::endl; } - return EXIT_SUCCESS; + // WIP: Deliberate test failure to verify CTEST_OUTPUT_ON_FAILURE + // works with -V instead of -VV. This is a test artifact for PR #5971 + // and must NOT be merged. + std::cerr << "DELIBERATE FAILURE: This output should appear in CI logs" << std::endl; + std::cerr << "because CTEST_OUTPUT_ON_FAILURE=1 is set and -V (not -VV)" << std::endl; + std::cerr << "is used. If you can read this in the CI log, the new" << std::endl; + std::cerr << "verbosity scheme is working correctly." << std::endl; + return EXIT_FAILURE; } diff --git a/Testing/ContinuousIntegration/AzurePipelinesBatch.yml b/Testing/ContinuousIntegration/AzurePipelinesBatch.yml index 87338fcd4b3..76d0b723803 100644 --- a/Testing/ContinuousIntegration/AzurePipelinesBatch.yml +++ b/Testing/ContinuousIntegration/AzurePipelinesBatch.yml @@ -103,12 +103,16 @@ jobs: - script: | cmake --version call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -VV -j 2 + ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -V -j 2 displayName: 'Build and test' env: CTEST_OUTPUT_ON_FAILURE: 1 CCACHE_MAXSIZE: 2.4G + - script: python $(Build.SourcesDirectory)/Testing/ContinuousIntegration/report_build_diagnostics.py $(Build.SourcesDirectory)-build + condition: succeededOrFailed() + displayName: 'Report build warnings and errors' + - script: | ci_addons ctest_junit_formatter $(Build.SourcesDirectory)-build > $(Agent.BuildDirectory)/JUnitTestResults.xml condition: succeededOrFailed() diff --git a/Testing/ContinuousIntegration/AzurePipelinesLinux.yml b/Testing/ContinuousIntegration/AzurePipelinesLinux.yml index 387f65284b1..7d56c2727cd 100644 --- a/Testing/ContinuousIntegration/AzurePipelinesLinux.yml +++ b/Testing/ContinuousIntegration/AzurePipelinesLinux.yml @@ -111,12 +111,16 @@ jobs: c++ --version cmake --version - ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -VV -j 2 + ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -V -j 2 displayName: 'Build and test' env: CTEST_OUTPUT_ON_FAILURE: 1 CCACHE_MAXSIZE: 2.4G + - bash: python3 $(Build.SourcesDirectory)/Testing/ContinuousIntegration/report_build_diagnostics.py $(Build.SourcesDirectory)-build + condition: succeededOrFailed() + displayName: 'Report build warnings and errors' + - script: | ci_addons ctest_junit_formatter $(Build.SourcesDirectory)-build > $(Agent.BuildDirectory)/JUnitTestResults.xml condition: succeededOrFailed() @@ -202,12 +206,16 @@ jobs: c++ --version cmake --version - ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -VV -j 2 + ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -V -j 2 displayName: 'Build and test' env: CTEST_OUTPUT_ON_FAILURE: 1 CCACHE_MAXSIZE: 2.4G + - bash: python3 $(Build.SourcesDirectory)/Testing/ContinuousIntegration/report_build_diagnostics.py $(Build.SourcesDirectory)-build + condition: succeededOrFailed() + displayName: 'Report build warnings and errors' + - script: | ci_addons ctest_junit_formatter $(Build.SourcesDirectory)-build > $(Agent.BuildDirectory)/JUnitTestResults.xml condition: succeededOrFailed() @@ -291,11 +299,16 @@ jobs: set -x c++ --version cmake --version - ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -VV -j 2 + ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -V -j 2 displayName: "Build and test" env: CTEST_OUTPUT_ON_FAILURE: 1 CCACHE_MAXSIZE: 2.4G + + - bash: python3 $(Build.SourcesDirectory)/Testing/ContinuousIntegration/report_build_diagnostics.py $(Build.SourcesDirectory)-build + condition: succeededOrFailed() + displayName: 'Report build warnings and errors' + - script: | ci_addons ctest_junit_formatter $(Build.SourcesDirectory)-build > $(Agent.BuildDirectory)/JUnitTestResults.xml condition: succeededOrFailed() diff --git a/Testing/ContinuousIntegration/AzurePipelinesLinuxPython.yml b/Testing/ContinuousIntegration/AzurePipelinesLinuxPython.yml index f28d4eb5901..d6543c756fc 100644 --- a/Testing/ContinuousIntegration/AzurePipelinesLinuxPython.yml +++ b/Testing/ContinuousIntegration/AzurePipelinesLinuxPython.yml @@ -118,12 +118,16 @@ jobs: c++ --version cmake --version - ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -VV -j 2 -L Python -E "(PythonExtrasTest)|(PythonFastMarching)|(PythonLazyLoadingImage)|(PythonThresholdSegmentationLevelSetWhiteMatterTest)|(PythonVerifyTTypeAPIConsistency)|(PythonWatershedSegmentation1Test)" + ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -V -j 2 -L Python -E "(PythonExtrasTest)|(PythonFastMarching)|(PythonLazyLoadingImage)|(PythonThresholdSegmentationLevelSetWhiteMatterTest)|(PythonVerifyTTypeAPIConsistency)|(PythonWatershedSegmentation1Test)" displayName: 'Build and test' env: CTEST_OUTPUT_ON_FAILURE: 1 CCACHE_MAXSIZE: 2.4G + - bash: python3 $(Build.SourcesDirectory)/Testing/ContinuousIntegration/report_build_diagnostics.py $(Build.SourcesDirectory)-build + condition: succeededOrFailed() + displayName: 'Report build warnings and errors' + - script: | ci_addons ctest_junit_formatter $(Build.SourcesDirectory)-build > $(Agent.BuildDirectory)/JUnitTestResults.xml condition: succeededOrFailed() diff --git a/Testing/ContinuousIntegration/AzurePipelinesMacOS.yml b/Testing/ContinuousIntegration/AzurePipelinesMacOS.yml index cb3e9c8c86b..b45fd75cd2d 100644 --- a/Testing/ContinuousIntegration/AzurePipelinesMacOS.yml +++ b/Testing/ContinuousIntegration/AzurePipelinesMacOS.yml @@ -110,12 +110,16 @@ jobs: c++ --version cmake --version - ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -VV -j 3 + ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -V -j 3 displayName: 'Build and test' env: CTEST_OUTPUT_ON_FAILURE: 1 CCACHE_MAXSIZE: 2.4G + - bash: python3 $(Build.SourcesDirectory)/Testing/ContinuousIntegration/report_build_diagnostics.py $(Build.SourcesDirectory)-build + condition: succeededOrFailed() + displayName: 'Report build warnings and errors' + - script: | ci_addons ctest_junit_formatter $(Build.SourcesDirectory)-build > $(Agent.BuildDirectory)/JUnitTestResults.xml condition: succeededOrFailed() diff --git a/Testing/ContinuousIntegration/AzurePipelinesMacOSPython.yml b/Testing/ContinuousIntegration/AzurePipelinesMacOSPython.yml index b236d8f87f9..1835530274e 100644 --- a/Testing/ContinuousIntegration/AzurePipelinesMacOSPython.yml +++ b/Testing/ContinuousIntegration/AzurePipelinesMacOSPython.yml @@ -119,12 +119,16 @@ jobs: c++ --version cmake --version - ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -VV -j 3 + ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -V -j 3 displayName: 'Build and test' env: CTEST_OUTPUT_ON_FAILURE: 1 CCACHE_MAXSIZE: 2.4G + - bash: python3 $(Build.SourcesDirectory)/Testing/ContinuousIntegration/report_build_diagnostics.py $(Build.SourcesDirectory)-build + condition: succeededOrFailed() + displayName: 'Report build warnings and errors' + - script: | ci_addons ctest_junit_formatter $(Build.SourcesDirectory)-build > $(Agent.BuildDirectory)/JUnitTestResults.xml condition: succeededOrFailed() diff --git a/Testing/ContinuousIntegration/AzurePipelinesWindows.yml b/Testing/ContinuousIntegration/AzurePipelinesWindows.yml index 6928a259b2e..0667e116a10 100644 --- a/Testing/ContinuousIntegration/AzurePipelinesWindows.yml +++ b/Testing/ContinuousIntegration/AzurePipelinesWindows.yml @@ -104,12 +104,16 @@ jobs: - script: | cmake --version call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -VV -j 2 + ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -V -j 2 displayName: 'Build and test' env: CTEST_OUTPUT_ON_FAILURE: 1 CCACHE_MAXSIZE: 2.4G + - script: python $(Build.SourcesDirectory)/Testing/ContinuousIntegration/report_build_diagnostics.py $(Build.SourcesDirectory)-build + condition: succeededOrFailed() + displayName: 'Report build warnings and errors' + - script: | ci_addons ctest_junit_formatter $(Build.SourcesDirectory)-build > $(Agent.BuildDirectory)/JUnitTestResults.xml condition: succeededOrFailed() diff --git a/Testing/ContinuousIntegration/AzurePipelinesWindowsPython.yml b/Testing/ContinuousIntegration/AzurePipelinesWindowsPython.yml index a471420b04b..fc5784941c9 100644 --- a/Testing/ContinuousIntegration/AzurePipelinesWindowsPython.yml +++ b/Testing/ContinuousIntegration/AzurePipelinesWindowsPython.yml @@ -114,12 +114,16 @@ jobs: - script: | cmake --version call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -VV -j 2 -L Python + ctest -S $(Agent.BuildDirectory)/ITK-dashboard/dashboard.cmake -V -j 2 -L Python displayName: 'Build and test' env: CTEST_OUTPUT_ON_FAILURE: 1 CCACHE_MAXSIZE: 2.4G + - script: python $(Build.SourcesDirectory)/Testing/ContinuousIntegration/report_build_diagnostics.py $(Build.SourcesDirectory)-build + condition: succeededOrFailed() + displayName: 'Report build warnings and errors' + - script: | ci_addons ctest_junit_formatter $(Build.SourcesDirectory)-build > $(Agent.BuildDirectory)/JUnitTestResults.xml condition: succeededOrFailed() diff --git a/Testing/ContinuousIntegration/report_build_diagnostics.py b/Testing/ContinuousIntegration/report_build_diagnostics.py new file mode 100755 index 00000000000..107bb1c1b45 --- /dev/null +++ b/Testing/ContinuousIntegration/report_build_diagnostics.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +"""Extract and print build warnings/errors from CTest Build.xml. + +ctest_build() writes compiler diagnostics to Build.xml for CDash but +does not print them to stdout. This script reads Build.xml from the +most recent test run and prints the content of every +and element so diagnostics appear directly in CI logs. + +Usage: + python report_build_diagnostics.py +""" + +import os +import sys +import xml.etree.ElementTree as ET + + +def main(): + if len(sys.argv) != 2: + print(f"Usage: {sys.argv[0]} ", file=sys.stderr) + sys.exit(1) + + build_dir = sys.argv[1] + + # CTest writes a TAG file whose first line is the timestamp directory. + tag_file = os.path.join(build_dir, "Testing", "TAG") + if not os.path.isfile(tag_file): + print(f"No TAG file found at {tag_file} — skipping.", file=sys.stderr) + return + + with open(tag_file) as f: + tag_dir = f.readline().strip() + + build_xml = os.path.join(build_dir, "Testing", tag_dir, "Build.xml") + if not os.path.isfile(build_xml): + print(f"No Build.xml found at {build_xml} — skipping.", file=sys.stderr) + return + + tree = ET.parse(build_xml) + root = tree.getroot() + + # Find all and elements under . + warnings = [] + errors = [] + for build_elem in root.iter("Build"): + for warning in build_elem.findall("Warning"): + text = warning.findtext("Text", "").strip() + src = warning.findtext("SourceFile", "").strip() + line = warning.findtext("SourceLineNumber", "").strip() + if text: + warnings.append((src, line, text)) + for error in build_elem.findall("Error"): + text = error.findtext("Text", "").strip() + src = error.findtext("SourceFile", "").strip() + line = error.findtext("SourceLineNumber", "").strip() + if text: + errors.append((src, line, text)) + + if not warnings and not errors: + print("No build warnings or errors found.") + return + + if errors: + print(f"========== BUILD ERRORS ({len(errors)}) ==========") + for src, line, text in errors: + print(f" {text}") + print() + + if warnings: + print(f"========== BUILD WARNINGS ({len(warnings)}) ==========") + for src, line, text in warnings: + print(f" {text}") + print() + + print("====================================================") + + # Exit with non-zero status only if there are errors (warnings are + # informational). This lets CI pipelines treat the step as a + # soft-fail for warnings but hard-fail for errors if desired. + + +if __name__ == "__main__": + main()