Repository: conan-io/conan

Issue:
Cross-compiling warning even when consuming package
Conan 1.12.3

I'm trying to package a compiler (gcc) as a tool to be used as a build requirement.

Since it's a compiler for native code it must have both `os_build` (where it runs on, in my case it can be Linux, Windows or MacOS) and `os` (which is a target os for compilation output, only Linux in my case).
Something like
```python
class GccConan(ConanFile):
    name = "gcc_installer"
    settings = "os", "arch", "os_build"
```
When I build it I get warning:
```
gcc_installer/6.3.1@external/master: ************************************************************
gcc_installer/6.3.1@external/master:   This package defines both 'os' and 'os_build' 
gcc_installer/6.3.1@external/master:   Please use 'os' for libraries and 'os_build'
gcc_installer/6.3.1@external/master:   only for build-requires used for cross-building
gcc_installer/6.3.1@external/master: ************************************************************
```
Which may be fine for general case and I can even put into README a note to ignore it.

However same warning appears even when I try to consume it, basically for every package I build and this is not fine (from usability perspective).

I would suggest moving this warning from initialization of `ConanFile` class to somewhere where we actually build package. Or maybe make it a part of linter / hook.

To help us debug your issue please explain:

- [x] I've read the [CONTRIBUTING guide](https://github.com/conan-io/conan/blob/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. I agree it is a bit annoying. I will talk with the team to see what can we do.
Why not use `os_buil` and `arch_build` only? Since the package is an installer, it could be built on the native platform and be distributed as well.
@uilianries 
How do I define a compiler which produces binary for Windows or Mac but runs on Linux then?
No my idea just building on native platform. But thinking again, you approach is better for this case, since you can build gcc for Windows, by Linux platform.
It could be moved to a pre_export hook, isn't it?

Resolving patch:
diff --git a/conans/client/cmd/export.py b/conans/client/cmd/export.py
--- a/conans/client/cmd/export.py
+++ b/conans/client/cmd/export.py
@@ -6,7 +6,7 @@
 
 from conans.client.cmd.export_linter import conan_linter
 from conans.client.file_copier import FileCopier
-from conans.client.output import ScopedOutput
+from conans.client.output import Color, ScopedOutput
 from conans.client.remover import DiskRemover
 from conans.errors import ConanException
 from conans.model.manifest import FileTreeManifest
@@ -54,7 +54,6 @@ def check_casing_conflict(cache, ref):
 
 def cmd_export(app, conanfile_path, name, version, user, channel, keep_source,
                export=True, graph_lock=None, ignore_dirty=False):
-
     """ Export the recipe
     param conanfile_path: the original source directory of the user containing a
                        conanfile.py
@@ -96,6 +95,8 @@ def cmd_export(app, conanfile_path, name, version, user, channel, keep_source,
             graph_lock.update_exported_ref(node_id, ref)
         return ref
 
+    _check_settings_for_warnings(conanfile, output)
+
     hook_manager.execute("pre_export", conanfile=conanfile, conanfile_path=conanfile_path,
                          reference=package_layout.ref)
     logger.debug("EXPORT: %s" % conanfile_path)
@@ -193,6 +194,27 @@ def cmd_export(app, conanfile_path, name, version, user, channel, keep_source,
     return ref
 
 
+def _check_settings_for_warnings(conanfile, output):
+    if not conanfile.settings:
+        return
+    try:
+        if not 'os_build' in conanfile.settings:
+            return
+        if not 'os' in conanfile.settings:
+            return
+
+        output.writeln("*"*60, front=Color.BRIGHT_RED)
+        output.writeln("  This package defines both 'os' and 'os_build' ",
+                       front=Color.BRIGHT_RED)
+        output.writeln("  Please use 'os' for libraries and 'os_build'",
+                       front=Color.BRIGHT_RED)
+        output.writeln("  only for build-requires used for cross-building",
+                       front=Color.BRIGHT_RED)
+        output.writeln("*"*60, front=Color.BRIGHT_RED)
+    except ConanException:
+        pass
+
+
 def _capture_scm_auto_fields(conanfile, conanfile_dir, destination_folder, output, ignore_dirty):
     """Deduce the values for the scm auto fields or functions assigned to 'url' or 'revision'
        and replace the conanfile.py contents.
diff --git a/conans/model/conan_file.py b/conans/model/conan_file.py
--- a/conans/model/conan_file.py
+++ b/conans/model/conan_file.py
@@ -2,7 +2,7 @@
 from contextlib import contextmanager
 
 from conans.client import tools
-from conans.client.output import Color, ScopedOutput
+from conans.client.output import ScopedOutput
 from conans.client.tools.env import environment_append, no_op, pythonpath
 from conans.client.tools.oss import OSInfo
 from conans.errors import ConanException, ConanInvalidConfiguration
@@ -135,19 +135,6 @@ def initialize(self, settings, env):
         self.requires = create_requirements(self)
         self.settings = create_settings(self, settings)
 
-        try:
-            if self.settings.os_build and self.settings.os:
-                self.output.writeln("*"*60, front=Color.BRIGHT_RED)
-                self.output.writeln("  This package defines both 'os' and 'os_build' ",
-                                    front=Color.BRIGHT_RED)
-                self.output.writeln("  Please use 'os' for libraries and 'os_build'",
-                                    front=Color.BRIGHT_RED)
-                self.output.writeln("  only for build-requires used for cross-building",
-                                    front=Color.BRIGHT_RED)
-                self.output.writeln("*"*60, front=Color.BRIGHT_RED)
-        except ConanException:
-            pass
-
         if 'cppstd' in self.settings.fields:
             self.output.warn("Setting 'cppstd' is deprecated in favor of 'compiler.cppstd',"
                              " please update your recipe.")


Test patch:
diff --git a/conans/test/unittests/client/cmd/export_test.py b/conans/test/unittests/client/cmd/export_test.py
--- a/conans/test/unittests/client/cmd/export_test.py
+++ b/conans/test/unittests/client/cmd/export_test.py
@@ -13,6 +13,43 @@
 from conans.util.files import load, save
 
 
+class ExportTest(unittest.TestCase):
+
+    def export_warning_test(self):
+        mixed_conanfile = """
+from conans import ConanFile
+
+class HelloConan(ConanFile):
+    name = "Hello"
+    version = "0.1"
+    exports = "*.h", "*.cpp"
+    settings = "os", "os_build"
+    def package(self):
+        self.copy("*.h", "include")
+"""
+        client = TestClient()
+        client.save({"conanfile.py": mixed_conanfile})
+        client.run("export . Hello/0.1")
+        self.assertIn("This package defines both 'os' and 'os_build'", client.out)
+
+    def export_no_warning_test(self):
+        conanfile = """
+from conans import ConanFile
+
+class HelloConan(ConanFile):
+    name = "Hello"
+    version = "0.1"
+    exports = "*.h", "*.cpp"
+    settings = "os"
+    def package(self):
+        self.copy("*.h", "include")
+"""
+        client = TestClient()
+        client.save({"conanfile.py": conanfile})
+        client.run("export . Hello/0.1")
+        self.assertNotIn("This package defines both 'os' and 'os_build'", client.out)
+
+
 class ReplaceSCMDataInConanfileTest(unittest.TestCase):
     conanfile = """
 from conans import ConanFile
@@ -48,7 +85,8 @@ def _do_actual_test(self, scm_data, after_scm, after_recipe):
         scm_data = SCMData(conanfile=namedtuple('_', 'scm')(scm=scm_data))
         _replace_scm_data_in_conanfile(self.conanfile_path, scm_data)
         self.assertEqual(load(self.conanfile_path), target_conanfile)
-        _parse_conanfile(conan_file_path=self.conanfile_path)  # Check that the resulting file is valid python code.
+        # Check that the resulting file is valid python code.
+        _parse_conanfile(conan_file_path=self.conanfile_path)
 
     def test_conanfile_after_scm(self):
         scm_data = {'type': 'git',
@@ -87,14 +125,14 @@ def scm_from_superclass_test(self):
         conanfile = '''from conans import ConanFile
 
 def get_conanfile():
-    
+
     class BaseConanFile(ConanFile):
         scm = {
-            "type": "git", 
+            "type": "git",
             "url": "auto",
             "revision": "auto"
         }
-    
+
     return BaseConanFile
 
 class Baseline(ConanFile):