Repository: conan-io/conan

Issue:
CMake helper requires compiler during package
To help us debug your issue please explain:

Hi everyone!

I'm trying give some support to taocpp/PEGTL and I would like to use CMake helper to install the project. The project is header-only, thus it installs the license, headers and pegtl-config.cmake.

However, when the package method runs over Windows, I receive the follow message:

    conans.errors.ConanExceptionInUserConanfileMethod: pegtl/2.5.2@taocpp/testing: Error in package() method, line 22
	cmake = CMake(self)
	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.

When I run the same recipe on Linux (Travis CI), I have no problems.

Appveyor error log: https://ci.appveyor.com/project/uilianries/pegtl/build/feature/conan-9/job/tnwvkd69gvkgsb6x#L250

The current PR uses just self.copy, but my intention is revert to follow state, using CMake:

https://github.com/uilianries/PEGTL/blob/dc4011991624faedf67fd390e8f53737f562a897/conanfile.py

Current PR for PEGTL: https://github.com/taocpp/PEGTL/pull/112

I'm curious if CONAN_CMAKE_GENERATOR is required by Conan or is just a CMake limitation.

Conan Version: 1.4.3

- [X] I've read the [CONTRIBUTING guide](https://raw.githubusercontent.com/conan-io/conan/develop/.github/CONTRIBUTING.md).
- [X] I've specified the Conan version, operating system version and any tool that can be relevant.
- [X] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.




Discussion:
Yes, CMake helper is looking for the generator and first checks `CONAN_CMAKE_GENERATOR` env var. So this is probably why you find the difference in CI.

We already reviewed this in issue #2758 but seems this could be a missing piece.

However, there is no default cmake generator in Windows so this should be the reason why you have to specify it even for a cmake install command.
Why does conan require that a generator be specified for a package that doesn't depend on a compiler? Why can't you let cmake figure out what to use since it doesn't matter to the package?

On Linux it defaults to "Unix Makefile" and on Windows it tries to detect installed Visual Studio version (Unless otherwise set ). I tested it on a virtual machine with VS2017 Community and it worked as expected. On both linux and windows the following was run:

```bash
cmake ..
cmake --build .
```
Yes, it seems that cmake works that way: https://stackoverflow.com/questions/6430251/what-is-the-default-generator-for-cmake-in-windows
looking into this to see if we can avoid the generator check.

BTW @uilianries, you know that you can still include `settings` in a header only recipe as long as you use `self.info.header_only()` por package ID, right? (I see you are already doing it, just a reminder)

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
@@ -117,9 +117,8 @@ def _generator(self):
 
         if not self._compiler or not self._compiler_version or not self._arch:
             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.")
+                # Not enough settings to set a generator in Windows
+                return None
             return "Unix Makefiles"
 
         if self._compiler == "Visual Studio":
@@ -243,11 +242,10 @@ def is_multi_configuration(self):
 
     @property
     def command_line(self):
-        args = [
-            '-G "%s"' % self.generator,
-            self.flags,
-            '-Wno-dev'
-        ]
+        args = ['-G "%s"' % self.generator] if self.generator else []
+        args.append(self.flags)
+        args.append('-Wno-dev')
+
         if self.toolset:
             args.append('-T "%s"' % self.toolset)
         return join_arguments(args)
@@ -422,7 +420,7 @@ def build(self, args=None, build_dir=None, target=None):
         if target is not None:
             args = ["--target", target] + args
 
-        if self.parallel:
+        if self.generator and self.parallel:
             if "Makefiles" in self.generator and "NMake" not in self.generator:
                 if "--" not in args:
                     args.append("--")


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
@@ -820,9 +820,8 @@ def instance_with_os_build(os_build):
         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")
+        cmake = instance_with_os_build("Windows")
+        self.assertEquals(cmake.generator, None)
 
         with tools.environment_append({"CONAN_CMAKE_GENERATOR": "MyCoolGenerator"}):
             cmake = instance_with_os_build("Windows")
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,13 +254,7 @@ def build(self):
             client = TestClient()
             client.save({"conanfile.py": conanfile % settings_line})
             client.run("install .")
-            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)
+            client.run("build .")
 
     def cmake_shared_flag_test(self):
         conanfile = """
diff --git a/conans/test/integration/cmake_install_package_test.py b/conans/test/integration/cmake_install_package_test.py
--- a/conans/test/integration/cmake_install_package_test.py
+++ b/conans/test/integration/cmake_install_package_test.py
@@ -72,3 +72,14 @@ def test(self):
         client.run("create . user/channel")
         self.assertIn("Test/0.1@user/channel (test package): Content: my header h!!",
                       client.user_io.out)
+
+        # Test also recipe without settings
+        new_conanfile =\
+            conanfile.replace("settings = \"os\", \"compiler\", \"build_type\", \"arch\"", "")
+        self.assertNotIn("settings = \"os\", \"compiler\", \"build_type\", \"arch\"", new_conanfile)
+        client.save({"conanfile.py": new_conanfile})
+
+        client.run("remove * --force")
+        client.run("create . user/channel")
+        self.assertIn("Test/0.1@user/channel (test package): Content: my header h!!",
+                      client.user_io.out)