Repository: conan-io/conan

Issue:
Settings friction review
I've been experimenting with non-common settings for embedded devices and I've found a couple of issues:

1. We have to review why the CMake() build helper is raising in case it doesn't have compiler or architecture. It is very very uncomfortable to specify the settings and deleting them later for the package_id just to avoid the error. And it makes no sense. 
2. If I install a `conanfile.txt` but without specifying `os` setting, it is crashing in the settings.py validate() method. Because somehow it has the os in the fields but not in the data. 




Discussion:
Thank you for looking into this! I already ran into the CMake helper issue multiple times, for example, [when installing a header only library with the CMake generated install target](https://github.com/vthiery/conan-jsonformoderncpp/pull/17).
This is interesting, but not sure how we will manage to do this. Even for a ``cmake install`` of a header-only library, the cmake generator is needed, and it can be something like ``Visual Studio 15 Win64``, so the compiler, version, architecture, is still needed.

But I agree we need to have a look at this.
There is not a default in Windows? In Linux/OSX there is no problem unless you want to use other than the "Unix Makefiles". And yes, it looks like it is only for the generator, we could include something like "or specify CONAN_CMAKE_GENERATOR environment variable instead" (probably only in windows) in the error message. Better to specify an env var in the profile than messing with unneeded settings.
Nop, that is the issue. In Linux it is fine, because Unix Makefiles is ubiquotous. But they won't work in Windows unless you have that tool installed, which is pretty annoying.
I see. Could we raise only in case of Windows and not CONAN_CMAKE_GENERATOR, giving the hint of providing a generator in the error message? Maybe a warning in the rest of system's is enough.
Yes, if CONAN_CMAKE_GENERATOR is defined, it will never raise.

But the problem with that is that it will create broken recipes. A normal package creation of this package will fail, because CONAN_CMAKE_GENERATOR is not defined by the user. I think that ``conan create`` from a package recipe repo should always work.
I meant only if CONAN_CMAKE_GENERATOR not defined and `compiler` or `arch` not defined and Windows.

Resolving patch:
diff --git a/conans/client/build/cmake.py b/conans/client/build/cmake.py
--- a/conans/client/build/cmake.py
+++ b/conans/client/build/cmake.py
@@ -115,8 +115,11 @@ def _generator(self):
             return os.environ["CONAN_CMAKE_GENERATOR"]
 
         if not self._compiler or not self._compiler_version or not self._arch:
-            raise ConanException("You must specify compiler, compiler.version and arch in "
-                                 "your settings to use a CMake generator")
+            if self._os_build == "Windows":
+                raise ConanException("You must specify compiler, compiler.version and arch in "
+                                     "your settings to use a CMake generator. You can also declare "
+                                     "the env variable CONAN_CMAKE_GENERATOR.")
+            return "Unix Makefiles"
 
         if self._compiler == "Visual Studio":
             _visuals = {'8': '8 2005',


Test patch:
diff --git a/conans/test/build_helpers/cmake_test.py b/conans/test/build_helpers/cmake_test.py
--- a/conans/test/build_helpers/cmake_test.py
+++ b/conans/test/build_helpers/cmake_test.py
@@ -773,6 +773,29 @@ def set_toolset_test(self):
         cmake = CMake(conan_file)
         self.assertIn('-T "v140"', cmake.command_line)
 
+
+    def test_missing_settings(self):
+        def instance_with_os_build(os_build):
+            settings = Settings.loads(default_settings_yml)
+            settings.os_build = os_build
+            conan_file = ConanFileMock()
+            conan_file.settings = settings
+            return CMake(conan_file)
+
+        cmake = instance_with_os_build("Linux")
+        self.assertEquals(cmake.generator, "Unix Makefiles")
+
+        cmake = instance_with_os_build("Macos")
+        self.assertEquals(cmake.generator, "Unix Makefiles")
+
+        with self.assertRaisesRegexp(ConanException, "You must specify compiler, "
+                                                     "compiler.version and arch"):
+            instance_with_os_build("Windows")
+
+        with tools.environment_append({"CONAN_CMAKE_GENERATOR": "MyCoolGenerator"}):
+            cmake = instance_with_os_build("Windows")
+            self.assertEquals(cmake.generator, "MyCoolGenerator")
+
     def test_cmake_system_version_android(self):
         with tools.environment_append({"CONAN_CMAKE_SYSTEM_NAME": "SomeSystem",
                                        "CONAN_CMAKE_GENERATOR": "SomeGenerator"}):
diff --git a/conans/test/integration/cmake_flags_test.py b/conans/test/integration/cmake_flags_test.py
--- a/conans/test/integration/cmake_flags_test.py
+++ b/conans/test/integration/cmake_flags_test.py
@@ -254,10 +254,13 @@ def build(self):
             client = TestClient()
             client.save({"conanfile.py": conanfile % settings_line})
             client.run("install .")
-            client.run("build .", ignore_error=True)
-
-            self.assertIn("You must specify compiler, compiler.version and arch in "
-                          "your settings to use a CMake generator", client.user_io.out,)
+            error = client.run("build .", ignore_error=True)
+            if platform.system() == "Windows":
+                self.assertTrue(error)
+                self.assertIn("You must specify compiler, compiler.version and arch in "
+                              "your settings to use a CMake generator", client.user_io.out,)
+            else:
+                self.assertFalse(error)
 
     def cmake_shared_flag_test(self):
         conanfile = """