Repository: conan-io/conan

Issue:
[bug] "conan profile detect" detects compiler versions with 3 digits but ships settings.yml only with 2 digits
### Describe the bug

Environment:
Windows 11 
Conan Versions >= 2.4 up to at least 2.16.1.
MinGw Compiler version x.y.z

Conan detects the MinGw compiler version and puts it to the default profile with all 3 digits x.y.z.
Subsequent conan commands fail with an error message like:
`
ERROR: Invalid setting 'x.y.z' is not a valid 'settings.compiler.version' value.
`
This is because in the settings.yml all compiler versions are only given with either one or two digits only.

Possible root cause:
With this change: https://github.com/conan-io/conan/pull/16362/commits/c7cd0dfb23d11979a08dd5d72d82934ee6aa4954
There was a "+" sign added in the regex-group:
`installed_version = re.search(r" ([0-9]+(\.[0-9])+)", out).group()`
When this "+" is changed to a "?" it seems to work as expected again to have only 2 digits in the default profile.
Maybe the intention of the developer was to have the "+" inside the group to allow minor versions >9?

### How to reproduce it

1. Install a MinGw Compiler with a 3 digit version x.y.z.
2. run: `conan profile detect`
3. run then e.g. a proper"conan install" command.


Discussion:
Additional question: I just wonder, why conan "validates" the compiler version setting even this setting is not used in the recipe (conanfile)?
Hi @SzBosch thanks for taking the time to report this.

The issue is actually two reports in one:
- Detect multi-digit minors, fixed in https://github.com/conan-io/conan/pull/18410

The mingw missdetection:

When the `conan profile detect` is called, you're right that the linked function is called as part of `detect_default_compiler`, but then the actual detect command additionally calls [`default_compiler_version`](https://github.com/conan-io/conan/blob/develop2/conan/internal/api/detect/detect_api.py#L617), which should be truncating the version to just the major one.

In fact, if I test locally, I get:

```
detect_api: CC and CXX: C:/Users/abril/.conan2/p/b/mingw0b4cdcf57fe89/p/bin/gcc.exe, C:/Users/abril/.conan2/p/b/mingw0b4cdcf57fe89/p/bin/g++.exe
detect_api: Found gcc 15.1
detect_api: gcc>=5, using the major as version
detect_api: gcc C++ standard library: libstdc++11

Detected profile:
[settings]
arch=armv8
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=15
os=Windows
```

For a `gcc --version` output of `gcc.exe (x86_64-posix-seh-rev0, Built by MinGW-Builds project) 15.1.0`

Could you please post the logs of your `profile detect` call, and the result of your compiler's `--version` call? Thanks!
Hi @AbrilRBS, thank you very much for your quick reply.

Here is the requested output:

```
(venv_conan_test) C:\Users\stefan>gcc --version
gcc (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


(venv_conan_test) C:\Users\stefan>conan --version
Conan version 2.17.0

(venv_conan_test) C:\Users\stefan>conan profile detect --force
detect_api: Found cc=gcc- 4.8.1
detect_api: gcc C++ standard library: libstdc++

Detected profile:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu98
compiler.libcxx=libstdc++
compiler.version= 4.8.1
os=Windows

WARN: This profile is a guess of your environment, please check it.
WARN: The output of this command is not guaranteed to be stable and can change in future Conan versions.
WARN: Use your own profile files for stability.
Saving detected profile to C:\Users\stefan\.conan2\profiles\default
```

Only now I have noticed there is also a space in front of the major digit. Maybe this can also be fixed.
> Only now I have noticed there is also a space in front of the major digit. Maybe this can also be fixed.

This would actually be the issue here, thanks for the logs :)
@SzBosch could you try running your detection with the changes in this PR? https://github.com/conan-io/conan/pull/18410 Thanks



Patch:
diff --git a/conan/internal/api/detect/detect_api.py b/conan/internal/api/detect/detect_api.py
index 0f96ebcb24c..fb29cd615a1 100644
--- a/conan/internal/api/detect/detect_api.py
+++ b/conan/internal/api/detect/detect_api.py
@@ -488,13 +488,13 @@ 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)
+        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)
+        installed_version = installed_version or 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)
-        if installed_version and installed_version.group():
-            installed_version = installed_version.group()
+        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))
             return compiler, Version(installed_version), compiler_exe
     except (Exception,):  # to disable broad-except
@@ -515,7 +515,7 @@ def detect_gcc_compiler(compiler_exe="gcc"):
         if ret != 0:
             return None, None, None
         compiler = "gcc"
-        installed_version = re.search(r"([0-9]+(\.[0-9])?)", out).group()
+        installed_version = re.search(r"([0-9]+(\.[0-9]+)?)", out).group()
         if installed_version:
             ConanOutput(scope="detect_api").info("Found %s %s" % (compiler, installed_version))
             return compiler, Version(installed_version), compiler_exe


Test patch:
diff --git a/test/unittests/client/conf/detect/test_gcc_compiler.py b/test/unittests/client/conf/detect/test_gcc_compiler.py
index b7059c600b9..ae961c6c0b4 100644
--- a/test/unittests/client/conf/detect/test_gcc_compiler.py
+++ b/test/unittests/client/conf/detect/test_gcc_compiler.py
@@ -1,19 +1,14 @@
-import unittest
 
 import mock
-from parameterized import parameterized
-
+import pytest
 
 from conan.internal.api.detect.detect_api import detect_gcc_compiler
 
-
-class GCCCompilerTestCase(unittest.TestCase):
-
-    @parameterized.expand([("10",), ("4.2",), ('7', )])
-    def test_detect_gcc_10(self, version):
-        with mock.patch("platform.system", return_value="Linux"):
-            with mock.patch("conan.internal.api.detect.detect_api.detect_runner", return_value=(0, version)):
-                compiler, installed_version, compiler_exe = detect_gcc_compiler()
-        self.assertEqual(compiler, 'gcc')
-        self.assertEqual(installed_version, version)
-        self.assertEqual(compiler_exe, 'gcc')
+@pytest.mark.parametrize("version", ["10", "4.2", '7', "8.12"])
+def test_detect_gcc_10(version):
+    with mock.patch("platform.system", return_value="Linux"):
+        with mock.patch("conan.internal.api.detect.detect_api.detect_runner", return_value=(0, version)):
+            compiler, installed_version, compiler_exe = detect_gcc_compiler()
+    assert compiler == 'gcc'
+    assert installed_version == version
+    assert compiler_exe == 'gcc'
diff --git a/test/unittests/util/detect_test.py b/test/unittests/util/detect_test.py
index 51df4cfe9ed..84f7cf3e23f 100644
--- a/test/unittests/util/detect_test.py
+++ b/test/unittests/util/detect_test.py
@@ -65,6 +65,9 @@ def test_detect_clang_gcc_toolchain(self, _):
 @pytest.mark.parametrize("version_return,expected_version", [
     ["cc.exe (Rev3, Built by MSYS2 project) 14.1.0", "14.1.0"],
     ["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 (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"],
@@ -74,6 +77,8 @@ def test_detect_clang_gcc_toolchain(self, _):
 def test_detect_cc_versionings(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
+    assert installed_version._value == Version(expected_version)._value
     assert installed_version == Version(expected_version)
 
 @pytest.mark.parametrize("function,version_return,expected_version", [