Repository: conan-io/conan
Pull request #18600 (2025-07-07 12:51:06)

Improve version detection for cc compilers
Changelog: Fix: Improve version detection for cc compilers
Docs: Omit

Tests should be self explanatory


Patch:
diff --git a/conan/internal/api/detect/detect_api.py b/conan/internal/api/detect/detect_api.py
index 71d8e6e8a..aefa2967a 100644
--- a/conan/internal/api/detect/detect_api.py
+++ b/conan/internal/api/detect/detect_api.py
@@ -488,11 +488,10 @@ def _cc_compiler(compiler_exe="cc"):
         compiler = "clang" if "clang" in out else "gcc"
         # clang and gcc have version after a space, first try to find that to skip extra numbers
         # that might appear in the first line of the output before the version
-        installed_version = re.search(r" ([0-9]+(\.[0-9]+)+)", out)
-        # Try only major but with spaces next
-        installed_version = installed_version or re.search(r" ([0-9]+(\.[0-9]+)?)", out)
+        # There might also be a leading parenthesis that contains build information, so we try to skip it
+        installed_version = re.search(r"(?:\(.*\))? ([0-9]+(\.[0-9]+)*)", out)
         # Fallback to the first number we find optionally followed by other version fields
-        installed_version = installed_version or re.search(r"([0-9]+(\.[0-9]+)?)", out)
+        installed_version = installed_version or re.search(r"([0-9]+(\.[0-9]+)*)", out)
         if installed_version and installed_version.group(1):
             installed_version = installed_version.group(1)
             ConanOutput(scope="detect_api").info("Found cc=%s-%s" % (compiler, installed_version))
@@ -510,7 +509,6 @@ def detect_gcc_compiler(compiler_exe="gcc"):
             if "clang" in out:
                 return None, None, None
 
-        # TODO: Add -dumpfullversion to always return major.minor
         ret, out = detect_runner(f'"{compiler_exe}" -dumpversion')
         if ret != 0:
             return None, None, None


Test patch:
diff --git a/test/unittests/util/detect_test.py b/test/unittests/util/detect_test.py
index 476b89b16..be71c00de 100644
--- a/test/unittests/util/detect_test.py
+++ b/test/unittests/util/detect_test.py
@@ -64,14 +64,18 @@ class TestDetect:
     ["g++ (Conan-Build-gcc--binutils-2.42) 14.1.0", "14.1.0"],
     ["gcc.exe (x86_64-posix-seh-rev0, Built by MinGW-Builds project) 15.1.0", "15.1.0"],
     ["gcc.exe (x86_64-posix-seh-rev0, Built by MinGW-Builds project) 15.15.0", "15.15.0"],
+    ["gcc (crosstool-NG 1.27.0) 13.3.0", "13.3.0"],
+    ["gcc (crosstool-NG 1.27.0) 13.3", "13.3"],
     ["gcc (GCC) 4.8.1", "4.8.1"],
     ["clang version 18.1.0rc (https://github.com/llvm/llvm-project.git 461274b81d8641eab64d494accddc81d7db8a09e)", "18.1.0"],
     ["cc.exe (Rev3, Built by MSYS2 project) 14.0", "14.0"],
     ["clang version 18 (https://github.com/llvm/llvm-project.git 461274b81d8641eab64d494accddc81d7db8a09e)", "18"],
     ["cc.exe (Rev3, Built by MSYS2 project) 14", "14"],
+    ["cc.exe 14.2", "14.2"],
+    ["cc1 14.2", "14.2"],
 ])
 @patch("conan.internal.api.detect.detect_api.detect_runner")
-def test_detect_cc_versionings(detect_runner_mock, version_return, expected_version):
+def test_detect_cc_versioning(detect_runner_mock, version_return, expected_version):
     detect_runner_mock.return_value = 0, version_return
     compiler, installed_version, compiler_exe = _cc_compiler()
     # Using private _value attribute to compare the str that reaches it, so no space issues arise