Repository: conan-io/conan

Issue:
Cannot set CMAKE_SYSTEM_VERSION without setting CMAKE_SYSTEM_NAME
To help us debug your issue please explain:

- [ 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.

Using conan 1.5.2, on Windows, with CMake and Visual Studio 2015.

Conan's CMake support seems to assume that `CMAKE_SYSTEM_VERSION` is only useful for cross-compiling, so it ignores the `CONAN_CMAKE_SYSTEM_VERSION` environment variable unless you also set `CMAKE_SYSTEM_NAME` somehow. However, with Visual Studio, it can be used to select the Windows Kit to use (eg: 8.1 to target Windows versions back to Vista). This works like the `MACOSX_DEPLOYMENT_TARGET` environment variable on macOS.

I'm using profiles to manage these. So in our macos profiles, I've set

    [env]
    MACOSX_DEPLOYMENT_TARGET=10.10

and in the Windows ones, I want to set

    [env]
    CONAN_CMAKE_SYSTEM_VERSION=8.1

However, I also need to set `CONAN_CMAKE_SYSTEM_NAME=Windows` for this to work. This isn't a bit problem, but it is somewhat redundant. The bigger issue is that the documentation does not make this clear at all - I only found this out by digging through the conan source code.

In summary, I would like to see `CONAN_CMAKE_SYSTEM_VERSION` respected even if `CONAN_CMAKE_SYSTEM_NAME` is not set, or - if that's not acceptable for whatever reason - the dependency should at least be documented at https://docs.conan.io/en/latest/reference/env_vars.html#cmake-related-variables.

Discussion:

Patch:
diff --git a/.ci/jenkins/Jenkinsfile b/.ci/jenkins/Jenkinsfile
index 2b4408fad..7d4d96044 100644
--- a/.ci/jenkins/Jenkinsfile
+++ b/.ci/jenkins/Jenkinsfile
@@ -4,10 +4,10 @@ def slaves = ['Linux', 'Windows', 'Macos']
 
 def pyvers 
 if (env.BRANCH_NAME =~ /(^release.*)|(^master)/) {
-    pyvers = ['py36', 'py34', 'py27']
+    pyvers = ['py37', 'py36', 'py34', 'py27']
 }
 else{
-	pyvers = ['py36', 'py27']
+	pyvers = ['py37', 'py36', 'py27']
 }
 
 def module = "\"conans.test\""
@@ -28,6 +28,10 @@ try{
         def slave = x
         for (y in pyvers) {
             def pyver = y
+            if(slave != "Linux" && pyver=="py37"){
+                continue;
+            }
+
             builders["${slave} - ${pyver}"] = {
                 node(slave) {
                     stage("${slave} - ${pyver}"){
diff --git a/.ci/jenkins/conf.py b/.ci/jenkins/conf.py
index 02c9bc118..9d907a4b8 100644
--- a/.ci/jenkins/conf.py
+++ b/.ci/jenkins/conf.py
@@ -13,7 +13,8 @@ macpylocation = {"py27": "/usr/bin/python",  # /Users/jenkins_ci/.pyenv/versions
 
 linuxpylocation = {"py27": "/usr/bin/python2.7",
                    "py34": "/usr/bin/python3.4",
-                   "py36": "/usr/bin/python3.6"}
+                   "py36": "/usr/bin/python3.6",
+                   "py37": "/usr/bin/python3.7"}
 
 
 def get_environ(tmp_path):
diff --git a/conans/client/build/cmake.py b/conans/client/build/cmake.py
index f70eba2ea..dad1425df 100644
--- a/conans/client/build/cmake.py
+++ b/conans/client/build/cmake.py
@@ -17,7 +17,7 @@ from conans.tools import cpu_count, args_to_string
 from conans import tools
 from conans.util.log import logger
 from conans.util.config_parser import get_bool_from_text
-from conans.client.build.compiler_flags import architecture_flag
+from conans.client.build.compiler_flags import architecture_flag, parallel_compiler_cl_flag
 
 
 def _get_env_cmake_system_name():
@@ -178,17 +178,16 @@ class CMake(object):
         # System name and system version
         if self._cmake_system_name is not True:  # String not empty
             ret["CMAKE_SYSTEM_NAME"] = self._cmake_system_name
-            ret["CMAKE_SYSTEM_VERSION"] = os_ver
         else:  # detect if we are cross building and the system name and version
             if cross_building(self._conanfile.settings):  # We are cross building
                 if self._os != self._os_build:
                     if self._os:  # the_os is the host (regular setting)
                         ret["CMAKE_SYSTEM_NAME"] = "Darwin" if self._os in ["iOS", "tvOS",
                                                                             "watchOS"] else self._os
-                        if os_ver:
-                            ret["CMAKE_SYSTEM_VERSION"] = os_ver
                     else:
                         ret["CMAKE_SYSTEM_NAME"] = "Generic"
+        if os_ver:
+            ret["CMAKE_SYSTEM_VERSION"] = os_ver
 
         # system processor
         cmake_system_processor = os.getenv("CONAN_CMAKE_SYSTEM_PROCESSOR", None)
@@ -325,9 +324,9 @@ class CMake(object):
 
         if str(self._os) in ["Windows", "WindowsStore"] and self._compiler == "Visual Studio":
             if self.parallel:
-                cpus = tools.cpu_count()
-                ret["CONAN_CXX_FLAGS"] = "/MP%s" % cpus
-                ret["CONAN_C_FLAGS"] = "/MP%s" % cpus
+                flag = parallel_compiler_cl_flag()
+                ret["CONAN_CXX_FLAGS"] = flag
+                ret["CONAN_C_FLAGS"] = flag
 
         # fpic
         if str(self._os) not in ["Windows", "WindowsStore"]:
@@ -431,6 +430,7 @@ class CMake(object):
                     self._compiler_version and Version(self._compiler_version) >= "10":
                 if "--" not in args:
                     args.append("--")
+                # Parallel for building projects in the solution
                 args.append("/m:%i" % cpu_count())
 
         arg_list = join_arguments([
diff --git a/conans/client/build/compiler_flags.py b/conans/client/build/compiler_flags.py
index 9ec94021f..a8f857dfc 100644
--- a/conans/client/build/compiler_flags.py
+++ b/conans/client/build/compiler_flags.py
@@ -9,7 +9,7 @@
     #   -LIBPATH, -D, -I, -ZI and so on.
 
 """
-
+from conans import tools
 from conans.tools import unix_path
 
 
@@ -192,3 +192,8 @@ def format_library_paths(library_paths, win_bash=False, subsystem=None, compiler
 def format_libraries(libraries, compiler=None):
     pattern = "%s.lib" if str(compiler) == 'Visual Studio' else "-l%s"
     return [pattern % library for library in libraries if library]
+
+
+def parallel_compiler_cl_flag():
+    cpu_count = tools.cpu_count()
+    return "/MP%s" % cpu_count
diff --git a/conans/client/build/msbuild.py b/conans/client/build/msbuild.py
index 864729dfb..3ffb40051 100644
--- a/conans/client/build/msbuild.py
+++ b/conans/client/build/msbuild.py
@@ -26,7 +26,10 @@ class MSBuild(object):
 
     def build(self, project_file, targets=None, upgrade_project=True, build_type=None, arch=None,
               parallel=True, force_vcvars=False, toolset=None, platforms=None, use_env=True,
-              vcvars_ver=None, winsdk_version=None):
+              vcvars_ver=None, winsdk_version=None, properties=None):
+
+        self.build_env.parallel = parallel
+
         with tools.environment_append(self.build_env.vars):
             # Path for custom properties file
             props_file_contents = self._get_props_file_contents()
@@ -37,15 +40,16 @@ class MSBuild(object):
                                            targets=targets, upgrade_project=upgrade_project,
                                            build_type=build_type, arch=arch, parallel=parallel,
                                            toolset=toolset, platforms=platforms,
-                                           use_env=use_env)
+                                           use_env=use_env, properties=properties)
                 command = "%s && %s" % (vcvars, command)
                 return self._conanfile.run(command)
 
     def get_command(self, project_file, props_file_path=None, targets=None, upgrade_project=True,
                     build_type=None, arch=None, parallel=True, toolset=None, platforms=None,
-                    use_env=False):
+                    use_env=False, properties=None):
 
         targets = targets or []
+        properties = properties or {}
         command = []
 
         if upgrade_project and not get_env("CONAN_SKIP_VS_PROJECTS_UPGRADE", False):
@@ -101,6 +105,9 @@ class MSBuild(object):
         if props_file_path:
             command.append('/p:ForceImportBeforeCppTargets="%s"' % props_file_path)
 
+        for name, value in properties.items():
+            command.append('/p:%s="%s"' % (name, value))
+
         return " ".join(command)
 
     def _get_props_file_contents(self):
diff --git a/conans/client/build/visual_environment.py b/conans/client/build/visual_environment.py
index 86b8554f9..c3f530d22 100644
--- a/conans/client/build/visual_environment.py
+++ b/conans/client/build/visual_environment.py
@@ -2,7 +2,7 @@ import copy
 import os
 
 from conans.client.build.compiler_flags import build_type_define, build_type_flags, visual_runtime, format_defines, \
-    include_path_option
+    include_path_option, parallel_compiler_cl_flag
 from conans.client.build.cppstd_flags import cppstd_flag
 
 
@@ -33,6 +33,7 @@ class VisualStudioBuildEnvironment(object):
         self.cxx_flags = copy.copy(self._deps_cpp_info.cppflags)
         self.link_flags = self._configure_link_flags()
         self.std = self._std_cpp()
+        self.parallel = False
 
     def _configure_link_flags(self):
         ret = copy.copy(self._deps_cpp_info.exelinkflags)
@@ -61,6 +62,9 @@ class VisualStudioBuildEnvironment(object):
         ret.extend(self.cxx_flags)
         ret.extend(self.link_flags)
 
+        if self.parallel:  # Build source in parallel
+            ret.append(parallel_compiler_cl_flag())
+
         if self.std:
             ret.append(self.std)
 
diff --git a/conans/client/cmd/uploader.py b/conans/client/cmd/uploader.py
index 386bd4c82..fd8fab32f 100644
--- a/conans/client/cmd/uploader.py
+++ b/conans/client/cmd/uploader.py
@@ -6,7 +6,7 @@ from conans.util.log import logger
 from conans.client.loader_parse import load_conanfile_class
 from conans.paths import EXPORT_SOURCES_TGZ_NAME
 from conans.client.source import complete_recipe_sources
-from conans.search.search import search_recipes
+from conans.search.search import search_recipes, search_packages
 
 
 def _is_a_reference(ref):
@@ -28,7 +28,8 @@ class CmdUpload(object):
 
     def upload(self, recorder, reference_or_pattern, package_id=None, all_packages=None,
                force=False, confirm=False, retry=0, retry_wait=0, skip_upload=False,
-               integrity_check=False, no_overwrite=None, remote_name=None):
+               integrity_check=False, no_overwrite=None, remote_name=None,
+               query=None):
         """If package_id is provided, conan_reference_or_pattern is a ConanFileReference"""
 
         if package_id and not _is_a_reference(reference_or_pattern):
@@ -59,6 +60,9 @@ class CmdUpload(object):
                                              str(conan_ref)))
                 if all_packages:
                     packages_ids = self._client_cache.conan_packages(conan_ref)
+                elif query:
+                    packages = search_packages(self._client_cache, conan_ref, query)
+                    packages_ids = list(packages.keys())
                 elif package_id:
                     packages_ids = [package_id, ]
                 else:
diff --git a/conans/client/command.py b/conans/client/command.py
index 1df046338..f69abcd30 100644
--- a/conans/client/command.py
+++ b/conans/client/command.py
@@ -55,6 +55,9 @@ class OnceArgument(argparse.Action):
             raise argparse.ArgumentError(None, msg)
         setattr(namespace, self.dest, values)
 
+_QUERY_EXAMPLE = ("os=Windows AND (arch=x86 OR compiler=gcc)")
+_PATTERN_EXAMPLE = ("boost/*")
+_REFERENCE_EXAMPLE =  ("MyPackage/1.2@user/channel")
 
 _BUILD_FOLDER_HELP = ("Directory for the build process. Defaulted to the current directory. A "
                       "relative path to current directory can also be specified")
@@ -62,12 +65,12 @@ _INSTALL_FOLDER_HELP = ("Directory containing the conaninfo.txt and conanbuildin
                         "(from previous 'conan install'). Defaulted to --build-folder")
 _KEEP_SOURCE_HELP = ("Do not remove the source folder in local cache, even if the recipe changed. "
                      "Use this for testing purposes only")
-_PATTERN_OR_REFERENCE_HELP = ("Pattern or package recipe reference, e.g., 'boost/*', "
-                              "'MyPackage/1.2@user/channel'")
+_PATTERN_OR_REFERENCE_HELP = ("Pattern or package recipe reference, e.g., '%s', "
+                              "'%s'" % (_REFERENCE_EXAMPLE, _PATTERN_EXAMPLE))
 _PATH_HELP = ("Path to a folder containing a conanfile.py or to a recipe file "
               "e.g., my_folder/conanfile.py")
-_QUERY_HELP = ("Packages query: 'os=Windows AND (arch=x86 OR compiler=gcc)'. The "
-               "'pattern_or_reference' parameter has to be a reference: MyPackage/1.2@user/channel")
+_QUERY_HELP = ("Packages query: '%s'. The 'pattern_or_reference' parameter has "
+               "to be a reference: %s" % (_QUERY_EXAMPLE, _REFERENCE_EXAMPLE))
 _SOURCE_FOLDER_HELP = ("Directory containing the sources. Defaulted to the conanfile's directory. A"
                        " relative path to current directory can also be specified")
 
@@ -733,6 +736,9 @@ class Command(object):
         parser.add_argument("-l", "--locks", default=False, action="store_true",
                             help="Remove locks")
         args = parser.parse_args(*args)
+
+        # NOTE: returns the expanded pattern (if a pattern was given), and checks
+        # that the query parameter wasn't abused
         reference = self._check_query_parameter_and_get_reference(args.pattern_or_reference,
                                                                   args.query)
 
@@ -934,6 +940,8 @@ class Command(object):
         parser.add_argument('pattern_or_reference', help=_PATTERN_OR_REFERENCE_HELP)
         parser.add_argument("-p", "--package", default=None, action=OnceArgument,
                             help='package ID to upload')
+        parser.add_argument('-q', '--query', default=None, action=OnceArgument,
+                            help="Only upload packages matching a specific query. " + _QUERY_HELP)
         parser.add_argument("-r", "--remote", action=OnceArgument,
                             help='upload to this specific remote')
         parser.add_argument("--all", action='store_true', default=False,
@@ -959,11 +967,15 @@ class Command(object):
 
         args = parser.parse_args(*args)
 
+        if args.query and args.package:
+            raise ConanException("'-q' and '-p' parameters can't be used at the same time")
+
         cwd = os.getcwd()
         info = None
 
         try:
             info = self._conan.upload(pattern=args.pattern_or_reference, package=args.package,
+                                      query=args.query,
                                       remote_name=args.remote, all_packages=args.all,
                                       force=args.force,
                                       confirm=args.confirm, retry=args.retry,
diff --git a/conans/client/conan_api.py b/conans/client/conan_api.py
index 8bd920c35..d96295482 100644
--- a/conans/client/conan_api.py
+++ b/conans/client/conan_api.py
@@ -727,9 +727,10 @@ class ConanAPIV1(object):
         return recorder.get_info()
 
     @api_method
-    def upload(self, pattern, package=None, remote_name=None, all_packages=False, force=False,
-               confirm=False, retry=2, retry_wait=5, skip_upload=False, integrity_check=False,
-               no_overwrite=None):
+    def upload(self, pattern, package=None, remote_name=None,
+               all_packages=False, force=False, confirm=False, retry=2,
+               retry_wait=5, skip_upload=False, integrity_check=False,
+               no_overwrite=None, query=None):
         """ Uploads a package recipe and the generated binary packages to a specified remote
         """
 
@@ -745,7 +746,8 @@ class ConanAPIV1(object):
                              self._registry)
         try:
             uploader.upload(recorder, pattern, package, all_packages, force, confirm, retry,
-                            retry_wait, skip_upload, integrity_check, no_overwrite, remote_name)
+                            retry_wait, skip_upload, integrity_check, no_overwrite, remote_name,
+                            query=query)
             return recorder.get_info()
         except ConanException as exc:
             recorder.error = True
diff --git a/conans/client/loader.py b/conans/client/loader.py
index 717a5990d..6a0b17c92 100644
--- a/conans/client/loader.py
+++ b/conans/client/loader.py
@@ -54,6 +54,7 @@ class ConanFileLoader(object):
             result._env_values.update(self._env_values)
 
             if consumer:
+                self._user_options[result.name].update(self._user_options["*"])
                 self._user_options.descope_options(result.name)
                 result.options.initialize_upstream(self._user_options, local=local)
                 self._user_options.clear_unscoped_options()
diff --git a/conans/client/tools/win.py b/conans/client/tools/win.py
index 2995a20be..8f963e837 100644
--- a/conans/client/tools/win.py
+++ b/conans/client/tools/win.py
@@ -241,12 +241,13 @@ def vcvars_command(settings, arch=None, compiler_version=None, force=False, vcva
 
     # https://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx
     arch_setting = arch_setting or 'x86_64'
-    if detected_architecture() == 'x86_64':
-        vcvars_arch = {'x86': 'x86',
+    arch_build = settings.get_safe("arch_build") or detected_architecture()
+    if arch_build == 'x86_64':
+        vcvars_arch = {'x86': 'amd64_x86' if int(compiler_version) >= 12 else 'x86',
                        'x86_64': 'amd64',
                        'armv7': 'amd64_arm',
                        'armv8': 'amd64_arm64'}.get(arch_setting)
-    elif detected_architecture() == 'x86':
+    elif arch_build == 'x86':
         vcvars_arch = {'x86': 'x86',
                        'x86_64': 'x86_amd64',
                        'armv7': 'x86_arm',
diff --git a/conans/model/options.py b/conans/model/options.py
index ab2cc367f..da7cde5b0 100644
--- a/conans/model/options.py
+++ b/conans/model/options.py
@@ -483,9 +483,8 @@ class PackageOptions(object):
 
 
 class Options(object):
-    """ all options of a package, both its own options and the upstream
-    ones.
-    Owned by conanfile
+    """ All options of a package, both its own options and the upstream ones.
+    Owned by ConanFile.
     """
     def __init__(self, options):
         assert isinstance(options, PackageOptions)
diff --git a/conans/pylint_plugin.py b/conans/pylint_plugin.py
index 8af7867e0..99bc9c7f2 100644
--- a/conans/pylint_plugin.py
+++ b/conans/pylint_plugin.py
@@ -1,7 +1,6 @@
 """Pylint plugin for ConanFile"""
-
 import astroid
-from astroid import MANAGER, scoped_nodes
+from astroid import MANAGER
 
 
 def register(linter):
@@ -16,7 +15,7 @@ def register(linter):
 def transform_conanfile(node):
     """Transform definition of ConanFile class so dynamic fields are visible to pylint"""
 
-    str_class = scoped_nodes.builtin_lookup("str")
+    str_class = astroid.builtin_lookup("str")
     info_class = MANAGER.ast_from_module_name("conans.model.info").lookup(
         "ConanInfo")
     build_requires_class = MANAGER.ast_from_module_name(
@@ -42,5 +41,5 @@ def transform_conanfile(node):
 
 
 MANAGER.register_transform(
-    scoped_nodes.Class, transform_conanfile,
+    astroid.ClassDef, transform_conanfile,
     lambda node: node.qname() == "conans.model.conan_file.ConanFile")
diff --git a/conans/requirements.txt b/conans/requirements.txt
index ccaf199d7..a7e8b1779 100644
--- a/conans/requirements.txt
+++ b/conans/requirements.txt
@@ -7,8 +7,8 @@ fasteners>=0.14.1
 six>=1.10.0
 node-semver==0.2.0
 distro>=1.0.2, <1.2.0
-pylint>=1.8.1, <1.9.0
+pylint>=1.9.3
 future==0.16.0
 pygments>=2.0, <3.0
-astroid>=1.6, <1.7
+astroid>=1.6.5
 deprecation>=2.0, <2.1
diff --git a/conans/requirements_osx.txt b/conans/requirements_osx.txt
index 0774179b5..b9de59ac6 100644
--- a/conans/requirements_osx.txt
+++ b/conans/requirements_osx.txt
@@ -1,5 +1,5 @@
 idna==2.6 # Solving conflict, somehow is installing 2.7 when requests require 2.6
-cryptography>=1.3.4, <2.2.0
+cryptography>=1.3.4, <2.4.0
 pyOpenSSL>=16.0.0, <18.0.0
 ndg-httpsclient>=0.4.1, <0.5.0
 pyasn>=1.5.0b7, <1.6.0


Test patch:
diff --git a/conans/test/build_helpers/msbuild_test.py b/conans/test/build_helpers/msbuild_test.py
index 10b45eee3..c91726fce 100644
--- a/conans/test/build_helpers/msbuild_test.py
+++ b/conans/test/build_helpers/msbuild_test.py
@@ -110,6 +110,15 @@ class HelloConan(ConanFile):
         self.assertIn("Debug|x86", client.user_io.out)
         self.assertIn("Copied 1 '.exe' file: MyProject.exe", client.user_io.out)
 
+    def custom_properties_test(self):
+        settings = MockSettings({"build_type": "Debug",
+                                 "compiler": "Visual Studio",
+                                 "arch": "x86_64"})
+        conanfile = MockConanfile(settings)
+        msbuild = MSBuild(conanfile)
+        command = msbuild.get_command("project_file.sln", properties={"MyProp1": "MyValue1", "MyProp2": "MyValue2"})
+        self.assertIn(' /p:MyProp1="MyValue1" /p:MyProp2="MyValue2"', command)
+
     @unittest.skipUnless(platform.system() == "Windows", "Requires MSBuild")
     def reuse_msbuild_object_test(self):
         # https://github.com/conan-io/conan/issues/2865
diff --git a/conans/test/build_helpers/visual_environment_test.py b/conans/test/build_helpers/visual_environment_test.py
index a5c7caa14..89033f31d 100644
--- a/conans/test/build_helpers/visual_environment_test.py
+++ b/conans/test/build_helpers/visual_environment_test.py
@@ -39,6 +39,23 @@ class VisualStudioBuildEnvironmentTest(unittest.TestCase):
                    '-mysharedlinkflag'],
             "LIB": ["/one/lib/path", "/two/lib/path"],
         })
+        tool.parallel = True
+        self.assertEquals(tool.vars_dict, {
+            "CL": ["-I/one/include/path", "-I/two/include/path",
+                   '-MDd',
+                   '-mycflag',
+                   '-mycflag2',
+                   '-Zi',
+                   '-Ob0',
+                   '-Od',
+                   '-mycppflag',
+                   '-mycppflag2',
+                   '-myexelinkflag',
+                   '-mysharedlinkflag',
+                   '/MP%s' % tools.cpu_count()],
+            "LIB": ["/one/lib/path", "/two/lib/path"],
+        })
+        tool.parallel = False
 
         # Now alter the paths before the vars_dict call
         tool.include_paths.append("/three/include/path")
diff --git a/conans/test/command/upload_test.py b/conans/test/command/upload_test.py
index 193024241..d53a05efe 100644
--- a/conans/test/command/upload_test.py
+++ b/conans/test/command/upload_test.py
@@ -5,6 +5,7 @@ from conans.test.utils.cpp_test_files import cpp_hello_conan_files
 from conans.model.ref import ConanFileReference, PackageReference
 from conans.util.files import save, is_dirty, gzopen_without_timestamps
 import os
+import itertools
 from mock import mock
 from conans.errors import ConanException
 from conans.paths import EXPORT_SOURCES_TGZ_NAME, PACKAGE_TGZ_NAME
@@ -20,6 +21,16 @@ class MyPkg(ConanFile):
         self.copy("*")
 """
 
+conanfile_upload_query = """from conans import ConanFile
+class MyPkg(ConanFile):
+    name = "Hello1"
+    version = "1.2.1"
+    exports_sources = "*"
+    settings = "os", "arch"
+
+    def package(self):
+        self.copy("*")
+"""
 
 class UploadTest(unittest.TestCase):
 
@@ -78,6 +89,38 @@ class UploadTest(unittest.TestCase):
         self.assertIn("Uploading conan_package.tgz", client.user_io.out)
         self.assertIn("Uploading conanfile.py", client.user_io.out)
 
+    def query_upload_test(self):
+        client = self._client()
+        client.save({"conanfile.py": conanfile_upload_query})
+
+        for os, arch in itertools.product(["Macos", "Linux", "Windows"],
+                                          ["armv8", "x86_64"]):
+            client.run("create . user/testing -s os=%s -s arch=%s" % (os, arch))
+
+        # Check that the right number of packages are picked up by the queries
+        client.run("upload Hello1/*@user/testing --confirm -q 'os=Windows or os=Macos'")
+        for i in range(1, 5):
+            self.assertIn("Uploading package %d/4" % i, client.user_io.out)
+        self.assertNotIn("Package is up to date, upload skipped", client.user_io.out)
+
+        client.run("upload Hello1/*@user/testing --confirm -q 'os=Linux and arch=x86_64'")
+        self.assertIn("Uploading package 1/1", client.user_io.out)
+
+        client.run("upload Hello1/*@user/testing --confirm -q 'arch=armv8'")
+        for i in range(1, 4):
+            self.assertIn("Uploading package %d/3" % i, client.user_io.out)
+        self.assertIn("Package is up to date, upload skipped", client.user_io.out)
+
+        # Check that a query not matching any packages doesn't upload any packages
+        client.run("upload Hello1/*@user/testing --confirm -q 'arch=sparc'")
+        self.assertNotIn("Uploading package", client.user_io.out)
+
+        # Check that an invalid query fails
+        try:
+            client.run("upload Hello1/*@user/testing --confirm -q 'blah blah blah'")
+        except:
+            self.assertIn("Invalid package query", client.user_io.out)
+
     def broken_sources_tgz_test(self):
         # https://github.com/conan-io/conan/issues/2854
         client = self._client()
@@ -110,8 +153,9 @@ class UploadTest(unittest.TestCase):
         client.save({"conanfile.py": conanfile,
                      "source.h": "my source"})
         client.run("create . user/testing")
-        package_ref = PackageReference.loads("Hello0/1.2.1@user/testing:"
-                                             "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9")
+        CONAN_PACKAGE_ID = "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9"
+        package_ref = PackageReference.loads("Hello0/1.2.1@user/testing:" +
+                                             CONAN_PACKAGE_ID)
 
         def gzopen_patched(name, mode="r", fileobj=None, compresslevel=None, **kwargs):
             if name == PACKAGE_TGZ_NAME:
@@ -128,8 +172,8 @@ class UploadTest(unittest.TestCase):
             self.assertTrue(is_dirty(tgz))
 
         client.run("upload * --confirm --all")
-        self.assertIn("WARN: Hello0/1.2.1@user/testing:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9: "
-                      "Removing conan_package.tgz, marked as dirty",
+        self.assertIn("WARN: Hello0/1.2.1@user/testing:%s: "
+                      "Removing conan_package.tgz, marked as dirty" % CONAN_PACKAGE_ID,
                       client.out)
         self.assertTrue(os.path.exists(tgz))
         self.assertFalse(is_dirty(tgz))
diff --git a/conans/test/generators/xcode_gcc_vs_test.py b/conans/test/generators/xcode_gcc_vs_test.py
index 8d350a6a5..eca7ded42 100644
--- a/conans/test/generators/xcode_gcc_vs_test.py
+++ b/conans/test/generators/xcode_gcc_vs_test.py
@@ -6,6 +6,7 @@ from conans.paths import (CONANFILE_TXT, BUILD_INFO_CMAKE, BUILD_INFO_GCC, CONAN
 from conans.util.files import load
 import os
 from conans.test.utils.tools import TestClient
+import re
 
 
 class VSXCodeGeneratorsTest(unittest.TestCase):
@@ -77,8 +78,10 @@ xcode
         package_ref = PackageReference(conan_ref, package_id)
         package_path = client.paths.package(package_ref).replace("\\", "/")
 
-        expected_lib_dirs = os.path.join(package_path, "lib").replace("\\", "/")
-        expected_include_dirs = os.path.join(package_path, "include").replace("\\", "/")
+        replaced_path = re.sub(os.getenv("USERPROFILE", "not user profile").replace("\\", "/"),
+                               "$(USERPROFILE)", package_path, flags=re.I)
+        expected_lib_dirs = os.path.join(replaced_path, "lib").replace("\\", "/")
+        expected_include_dirs = os.path.join(replaced_path, "include").replace("\\", "/")
 
         self.assertIn(expected_lib_dirs, lib_dirs)
         self.assertEquals("hello.lib;%(AdditionalDependencies)", libs)
@@ -90,6 +93,8 @@ xcode
 
         expected_c_flags = '-some_c_compiler_flag'
         expected_cpp_flags = '-some_cpp_compiler_flag'
+        expected_lib_dirs = os.path.join(package_path, "lib").replace("\\", "/")
+        expected_include_dirs = os.path.join(package_path, "include").replace("\\", "/")
 
         self.assertIn('LIBRARY_SEARCH_PATHS = $(inherited) "%s"' % expected_lib_dirs, xcode)
         self.assertIn('HEADER_SEARCH_PATHS = $(inherited) "%s"' % expected_include_dirs, xcode)
diff --git a/conans/test/integration/options_test.py b/conans/test/integration/options_test.py
index 11851862f..5ea8211a6 100644
--- a/conans/test/integration/options_test.py
+++ b/conans/test/integration/options_test.py
@@ -64,3 +64,59 @@ zlib/0.1@lasote/testing
                       client.user_io.out)
         conaninfo = load(os.path.join(client.current_folder, CONANINFO))
         self.assertNotIn("zlib:shared=True", conaninfo)
+
+    def general_scope_options_test(self):
+        # https://github.com/conan-io/conan/issues/2538
+        client = TestClient()
+        conanfile_libA = """
+from conans import ConanFile
+
+class LibA(ConanFile):
+    name = "libA"
+    version = "0.1"
+    options = {"shared": [True, False]}
+    default_options= "shared=False"
+
+    def configure(self):
+        self.output.info("shared=%s" % self.options.shared)
+    """
+        conanfile_libB = """
+from conans import ConanFile
+
+class LibB(ConanFile):
+    name = "libB"
+    version = "0.1"
+    options = {"shared": [True, False]}
+    default_options= "shared=False"
+    requires = "libA/0.1@danimtb/testing"
+
+    def configure(self):
+        self.options["*"].shared = self.options.shared
+        self.output.info("shared=%s" % self.options.shared)
+    """
+        client.save({"conanfile_liba.py": conanfile_libA,
+                     "conanfile_libb.py": conanfile_libB})
+
+        for without_configure_line in [True, False]:
+            client.save({"conanfile_liba.py": conanfile_libA})
+
+            if without_configure_line:
+                client.save({"conanfile_libb.py": conanfile_libB.replace(
+                    "        self.options[\"*\"].shared = self.options.shared", "")})
+            else:
+                client.save({"conanfile_libb.py": conanfile_libB})
+
+            # Test info
+            client.run("export conanfile_liba.py danimtb/testing")
+            client.run("info conanfile_libb.py -o *:shared=True")
+            self.assertIn("PROJECT: shared=True", client.out)
+            self.assertIn("libA/0.1@danimtb/testing: shared=True", client.out)
+            # Test create
+            client.run("create conanfile_liba.py danimtb/testing -o *:shared=True")
+            client.run("create conanfile_libb.py danimtb/testing -o *:shared=True")
+            self.assertIn("libB/0.1@danimtb/testing: shared=True", client.out)
+            self.assertIn("libA/0.1@danimtb/testing: shared=True", client.out)
+            # Test install
+            client.run("install conanfile_libb.py -o *:shared=True")
+            self.assertIn("PROJECT: shared=True", client.out)
+            self.assertIn("libA/0.1@danimtb/testing: shared=True", client.out)
diff --git a/conans/test/util/tools_test.py b/conans/test/util/tools_test.py
index 1637200da..13ba6eb5f 100644
--- a/conans/test/util/tools_test.py
+++ b/conans/test/util/tools_test.py
@@ -656,6 +656,23 @@ class HelloConan(ConanFile):
             self.assertIn("Conan:vcvars already set", str(output))
             self.assertIn("VS140COMNTOOLS=", str(output))
 
+    @unittest.skipUnless(platform.system() == "Windows", "Requires Windows")
+    def vcvars_amd64_32_cross_building_support_test(self):
+        # amd64_x86 crossbuilder
+        settings = Settings.loads(default_settings_yml)
+        settings.os = "Windows"
+        settings.compiler = "Visual Studio"
+        settings.compiler.version = "15"
+        settings.arch = "x86"
+        settings.arch_build = "x86_64"
+        cmd = tools.vcvars_command(settings)
+        self.assertIn('vcvarsall.bat" amd64_x86', cmd)
+
+        # It follows arch_build first
+        settings.arch_build = "x86"
+        cmd = tools.vcvars_command(settings)
+        self.assertIn('vcvarsall.bat" x86', cmd)
+
     def vcvars_raises_when_not_found_test(self):
         text = """
 os: [Windows]