Repository: conan-io/conan

Issue:
output errors for invalid platforms
- [x] Refer to the issue that supports this Pull Request.
Close #2546



Discussion:

Resolving patch:
diff --git a/conans/client/build/msbuild.py b/conans/client/build/msbuild.py
--- a/conans/client/build/msbuild.py
+++ b/conans/client/build/msbuild.py
@@ -10,11 +10,12 @@ def __init__(self, conanfile):
         self.build_env = VisualStudioBuildEnvironment(self._conanfile)
 
     def build(self, project_file, targets=None, upgrade_project=True, build_type=None, arch=None,
-              parallel=True, force_vcvars=False, toolset=None):
+              parallel=True, force_vcvars=False, toolset=None, platforms=None):
         with tools.environment_append(self.build_env.vars):
             command = msvc_build_command(self._conanfile.settings,
                                          project_file, targets=targets,
                                          upgrade_project=upgrade_project,
                                          build_type=build_type, arch=arch, parallel=parallel,
-                                         force_vcvars=force_vcvars, toolset=toolset)
+                                         force_vcvars=force_vcvars, toolset=toolset,
+                                         platforms=platforms)
             return self._conanfile.run(command)
diff --git a/conans/client/tools/win.py b/conans/client/tools/win.py
--- a/conans/client/tools/win.py
+++ b/conans/client/tools/win.py
@@ -11,24 +11,24 @@
 from conans.client.tools.oss import cpu_count, detected_architecture, os_info
 from conans.errors import ConanException
 from conans.util.env_reader import get_env
-from conans.util.files import decode_text
+from conans.util.files import decode_text, load
 
 _global_output = None
 
 
 def msvc_build_command(settings, sln_path, targets=None, upgrade_project=True, build_type=None,
-                       arch=None, parallel=True, force_vcvars=False, toolset=None):
+                       arch=None, parallel=True, force_vcvars=False, toolset=None, platforms=None):
     """ Do both: set the environment variables and call the .sln build
     """
     vcvars = vcvars_command(settings, force=force_vcvars)
     build = build_sln_command(settings, sln_path, targets, upgrade_project, build_type, arch,
-                              parallel, toolset=toolset)
+                              parallel, toolset=toolset, platforms=platforms)
     command = "%s && %s" % (vcvars, build)
     return command
 
 
 def build_sln_command(settings, sln_path, targets=None, upgrade_project=True, build_type=None,
-                      arch=None, parallel=True, toolset=None):
+                      arch=None, parallel=True, toolset=None, platforms=None):
     """
     Use example:
         build_command = build_sln_command(self.settings, "myfile.sln", targets=["SDL2_image"])
@@ -50,11 +50,27 @@ def build_sln_command(settings, sln_path, targets=None, upgrade_project=True, bu
     if not arch:
         raise ConanException("Cannot build_sln_command, arch not defined")
     command += "msbuild %s /p:Configuration=%s" % (sln_path, build_type)
-    arch = str(arch)
     msvc_arch = {'x86': 'x86',
                  'x86_64': 'x64',
                  'armv7': 'ARM',
-                 'armv8': 'ARM64'}.get(arch)
+                 'armv8': 'ARM64'}
+    if platforms:
+        msvc_arch.update(platforms)
+    msvc_arch = msvc_arch.get(str(arch))
+    try:
+        sln = load(sln_path)
+        pattern = re.compile(r"GlobalSection\(SolutionConfigurationPlatforms\)(.*?)EndGlobalSection", re.DOTALL)
+        solution_global = pattern.search(sln).group(1)
+        lines = solution_global.splitlines()
+        lines = [s.split("=")[0].strip() for s in lines]
+    except Exception:
+        pass
+    else:
+        config = "%s|%s" % (build_type, msvc_arch)
+        if config not in "".join(lines):
+            _global_output.warn("***** The configuration %s does not exist in this solution *****" % config)
+            _global_output.warn("Use 'platforms' argument to define your architectures")
+
     if msvc_arch:
         command += ' /p:Platform="%s"' % msvc_arch
 


Test patch:
diff --git a/conans/test/util/build_sln_command_test.py b/conans/test/util/build_sln_command_test.py
--- a/conans/test/util/build_sln_command_test.py
+++ b/conans/test/util/build_sln_command_test.py
@@ -8,10 +8,44 @@
 from conans.errors import ConanException
 from conans.model.settings import Settings
 from nose.plugins.attrib import attr
+from conans.util.files import save
+from six import StringIO
+from conans.client.output import ConanOutput
+from conans.test.utils.test_files import temp_folder
+import os
 
 
 @attr('visual_studio')
 class BuildSLNCommandTest(unittest.TestCase):
+    def no_configuration_test(self):
+        dummy = """GlobalSection
+            EndGlobalSection
+     GlobalSection(SolutionConfigurationPlatforms) = preSolution
+        Debug|Win32 = Debug|Win32
+        Debug|x64 = Debug|x64
+        Release|Win32 = Release|Win32
+        Release|x64 = Release|x64
+    EndGlobalSection
+"""
+        folder = temp_folder()
+        path = os.path.join(folder, "dummy.sln")
+        save(path, dummy)
+        new_out = StringIO()
+        tools.set_global_instances(ConanOutput(new_out), None)
+        command = build_sln_command(Settings({}), sln_path=path, targets=None, upgrade_project=False,
+                                    build_type='Debug', arch="x86", parallel=False)
+        self.assertIn('/p:Configuration=Debug /p:Platform="x86"', command)
+        self.assertIn("WARN: ***** The configuration Debug|x86 does not exist in this solution *****",
+                      new_out.getvalue())
+        # use platforms
+        new_out = StringIO()
+        tools.set_global_instances(ConanOutput(new_out), None)
+        command = build_sln_command(Settings({}), sln_path=path, targets=None, upgrade_project=False,
+                                    build_type='Debug', arch="x86", parallel=False, platforms={"x86": "Win32"})
+        self.assertIn('/p:Configuration=Debug /p:Platform="Win32"', command)
+        self.assertNotIn("WARN", new_out.getvalue())
+        self.assertNotIn("ERROR", new_out.getvalue())
+
     def no_arch_test(self):
         with self.assertRaises(ConanException):
             build_sln_command(Settings({}), sln_path='dummy.sln', targets=None, upgrade_project=False,