Repository: conan-io/conan

Issue:
Take a look into normalizing the log levels of conan
Currently, it's not clear whether verbose or notice/status is the default one, and if their order is correct. We should take a look into normalizing all the log levels to be consistent across

Discussion:

Patch:
diff --git a/conan/api/subapi/new.py b/conan/api/subapi/new.py
index 06b646e1e..246682420 100644
--- a/conan/api/subapi/new.py
+++ b/conan/api/subapi/new.py
@@ -84,9 +84,14 @@ class NewAPI:
         result = {}
         name = definitions.get("name", "Pkg")
         definitions["conan_version"] = __version__
-        requires = definitions.get("requires")  # Convert to list, and forget about it
-        if requires:
-            definitions["requires"] = [requires] if isinstance(requires, str) else requires
+
+        def ensure_list(key):
+            value = definitions.get(key)  # Convert to list, and forget about it
+            if value:
+                definitions[key] = [value] if isinstance(value, str) else value
+
+        ensure_list("requires")
+        ensure_list("tool_requires")
 
         def as_package_name(n):
             return n.replace("-", "_").replace("+", "_").replace(".", "_")
diff --git a/conan/cli/command.py b/conan/cli/command.py
index 505a18dac..0af629ce8 100644
--- a/conan/cli/command.py
+++ b/conan/cli/command.py
@@ -117,8 +117,8 @@ class ConanArgumentParser(argparse.ArgumentParser):
                   "warning": LEVEL_WARNING,  # -vwaring 60
                   "notice": LEVEL_NOTICE,  # -vnotice 50
                   "status": LEVEL_STATUS,  # -vstatus 40
+                  None: LEVEL_STATUS,  # -v 40
                   "verbose": LEVEL_VERBOSE,  # -vverbose 30
-                  None: LEVEL_VERBOSE,  # -v 30
                   "debug": LEVEL_DEBUG,  # -vdebug 20
                   "v": LEVEL_DEBUG,  # -vv 20
                   "trace": LEVEL_TRACE,  # -vtrace 10
diff --git a/conan/cli/commands/new.py b/conan/cli/commands/new.py
index 50cd2f2bb..f4274d1cc 100644
--- a/conan/cli/commands/new.py
+++ b/conan/cli/commands/new.py
@@ -68,7 +68,7 @@ def new(conan_api, parser, *args):
                 template_vars.extend(meta.find_undeclared_variables(ast))
 
             injected_vars = {"conan_version", "package_name", "as_name"}
-            optional_vars = {"requires"}
+            optional_vars = {"requires", "tool_requires"}
             template_vars = list(set(template_vars) - injected_vars - optional_vars)
             template_vars.sort()
             return template_vars
diff --git a/conan/cli/commands/remove.py b/conan/cli/commands/remove.py
index da4a7411b..0fb4289eb 100644
--- a/conan/cli/commands/remove.py
+++ b/conan/cli/commands/remove.py
@@ -2,6 +2,7 @@ from conan.api.conan_api import ConanAPI
 from conan.api.model import ListPattern
 from conan.cli.command import conan_command, OnceArgument
 from conans.client.userio import UserInput
+from conans.errors import ConanException
 
 
 @conan_command(group="Consumer")
@@ -36,6 +37,8 @@ def remove(conan_api: ConanAPI, parser, *args):
     select_bundle = conan_api.list.select(ref_pattern, args.package_query, remote)
 
     if ref_pattern.package_id is None:
+        if args.package_query is not None:
+            raise ConanException('--package-query supplied but the pattern does not match packages')
         for ref, _ in select_bundle.refs():
             if confirmation("Remove the recipe and all the packages of '{}'?"
                             "".format(ref.repr_notime())):
diff --git a/conan/internal/api/new/basic.py b/conan/internal/api/new/basic.py
index 837913430..66188ee40 100644
--- a/conan/internal/api/new/basic.py
+++ b/conan/internal/api/new/basic.py
@@ -29,6 +29,21 @@ class BasicConanfile(ConanFile):
         pass
         {%- endif %}
 
+    # The build_requirements() method is functionally equivalent to the requirements() one,
+    # being executed just after it. It's a good place to define tool requirements,
+    # dependencies necessary at build time, not at application runtime
+    def build_requirements(self):
+        # Each call to self.tool_requires() will add the corresponding build requirement
+        {% if tool_requires is defined -%}
+        {% for require in tool_requires -%}
+        self.tool_requires("{{ require }}")
+        {% endfor %}
+        {% else -%}
+        # Uncommenting this line will add the cmake >=3.15 build dependency to your project
+        # self.requires("cmake/[>=3.15]")
+        pass
+        {%- endif %}
+
     # The purpose of generate() is to prepare the build, generating the necessary files, such as
     # Files containing information to locate the dependencies, environment activation scripts,
     # and specific build system files among others
diff --git a/conan/internal/api/new/cmake_exe.py b/conan/internal/api/new/cmake_exe.py
index d58f36702..288a4d2d2 100644
--- a/conan/internal/api/new/cmake_exe.py
+++ b/conan/internal/api/new/cmake_exe.py
@@ -46,6 +46,13 @@ class {{package_name}}Recipe(ConanFile):
         self.requires("{{ require }}")
         {% endfor %}
     {%- endif %}
+
+    {% if tool_requires is defined -%}
+    def build_requirements(self):
+        {% for require in tool_requires -%}
+        self.tool_requires("{{ require }}")
+        {% endfor %}
+    {%- endif %}
 '''
 
 cmake_exe_v2 = """cmake_minimum_required(VERSION 3.15)
diff --git a/conan/internal/api/new/cmake_lib.py b/conan/internal/api/new/cmake_lib.py
index 25c3d731d..eed436075 100644
--- a/conan/internal/api/new/cmake_lib.py
+++ b/conan/internal/api/new/cmake_lib.py
@@ -56,6 +56,14 @@ class {{package_name}}Recipe(ConanFile):
         self.requires("{{ require }}")
         {% endfor %}
     {%- endif %}
+
+    {% if tool_requires is defined -%}
+    def build_requirements(self):
+        {% for require in tool_requires -%}
+        self.tool_requires("{{ require }}")
+        {% endfor %}
+    {%- endif %}
+
 '''
 
 cmake_v2 = """cmake_minimum_required(VERSION 3.15)
diff --git a/conan/internal/deploy.py b/conan/internal/deploy.py
index f48d28cf9..69ce0690c 100644
--- a/conan/internal/deploy.py
+++ b/conan/internal/deploy.py
@@ -58,7 +58,7 @@ def full_deploy(graph, output_folder):
     for dep in conanfile.dependencies.values():
         if dep.package_folder is None:
             continue
-        folder_name = os.path.join(dep.context, dep.ref.name, str(dep.ref.version))
+        folder_name = os.path.join("full_deploy", dep.context, dep.ref.name, str(dep.ref.version))
         build_type = dep.info.settings.get_safe("build_type")
         arch = dep.info.settings.get_safe("arch")
         if build_type:
@@ -80,6 +80,7 @@ def direct_deploy(graph, output_folder):
     import os
     import shutil
 
+    output_folder = os.path.join(output_folder, "direct_deploy")
     conanfile = graph.root.conanfile
     conanfile.output.info(f"Conan built-in pkg deployer to {output_folder}")
     # If the argument is --requires, the current conanfile is a virtual one with 1 single
diff --git a/conan/tools/cmake/cmakedeps/cmakedeps.py b/conan/tools/cmake/cmakedeps/cmakedeps.py
index a4f65ed46..e36f1fd57 100644
--- a/conan/tools/cmake/cmakedeps/cmakedeps.py
+++ b/conan/tools/cmake/cmakedeps/cmakedeps.py
@@ -9,6 +9,7 @@ from conan.tools.cmake.cmakedeps.templates.macros import MacrosTemplate
 from conan.tools.cmake.cmakedeps.templates.target_configuration import TargetConfigurationTemplate
 from conan.tools.cmake.cmakedeps.templates.target_data import ConfigDataTemplate
 from conan.tools.cmake.cmakedeps.templates.targets import TargetsTemplate
+from conans.client.generators import relativize_generated_file
 from conans.errors import ConanException
 from conans.util.files import save
 
@@ -94,7 +95,9 @@ class CMakeDeps(object):
             ret[config_version.filename] = config_version.render()
 
         data_target = ConfigDataTemplate(self, require, dep, find_module_mode)
-        ret[data_target.filename] = data_target.render()
+        data_content = relativize_generated_file(data_target.render(), self._conanfile,
+                                                 "${CMAKE_CURRENT_LIST_DIR}")
+        ret[data_target.filename] = data_content
 
         target_configuration = TargetConfigurationTemplate(self, require, dep, find_module_mode)
         ret[target_configuration.filename] = target_configuration.render()
diff --git a/conan/tools/cmake/cmakedeps/templates/target_data.py b/conan/tools/cmake/cmakedeps/templates/target_data.py
index 2b04d2337..bd452109e 100644
--- a/conan/tools/cmake/cmakedeps/templates/target_data.py
+++ b/conan/tools/cmake/cmakedeps/templates/target_data.py
@@ -50,13 +50,7 @@ class ConfigDataTemplate(CMakeDepsFileTemplate):
 
         # Make the root_folder relative to the generated xxx-data.cmake file
         root_folder = self._root_folder
-        generators_folder = self.cmakedeps._conanfile.generators_folder
-        if os.path.commonpath([root_folder, generators_folder]) == generators_folder:
-            rel_path = os.path.relpath(root_folder, generators_folder)
-            rel_path = rel_path.replace('\\', '/').replace('$', '\\$').replace('"', '\\"')
-            root_folder = f"${{CMAKE_CURRENT_LIST_DIR}}/{rel_path}"
-        else:
-            root_folder = root_folder.replace('\\', '/').replace('$', '\\$').replace('"', '\\"')
+        root_folder = root_folder.replace('\\', '/').replace('$', '\\$').replace('"', '\\"')
 
         return {"global_cpp": global_cpp,
                 "has_components": self.conanfile.cpp_info.has_components,
diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py
index 9c0c216e2..e24398245 100644
--- a/conan/tools/cmake/toolchain/blocks.py
+++ b/conan/tools/cmake/toolchain/blocks.py
@@ -520,12 +520,9 @@ class PkgConfigBlock(Block):
         pkg_config = self._conanfile.conf.get("tools.gnu:pkg_config", check_type=str)
         if pkg_config:
             pkg_config = pkg_config.replace("\\", "/")
-        pkg_config_path = self._conanfile.generators_folder
-        if pkg_config_path:
-            # hardcoding scope as "build"
-            subsystem = deduce_subsystem(self._conanfile, "build")
-            pathsep = ":" if subsystem != WINDOWS else ";"
-            pkg_config_path = pkg_config_path.replace("\\", "/") + pathsep
+        subsystem = deduce_subsystem(self._conanfile, "build")
+        pathsep = ":" if subsystem != WINDOWS else ";"
+        pkg_config_path = "${CMAKE_CURRENT_LIST_DIR}" + pathsep
         return {"pkg_config": pkg_config,
                 "pkg_config_path": pkg_config_path}
 
diff --git a/conan/tools/cmake/toolchain/toolchain.py b/conan/tools/cmake/toolchain/toolchain.py
index 1a6e83f96..e6da2315f 100644
--- a/conan/tools/cmake/toolchain/toolchain.py
+++ b/conan/tools/cmake/toolchain/toolchain.py
@@ -16,6 +16,7 @@ from conan.tools.cmake.toolchain.blocks import ToolchainBlocks, UserToolchain, G
 from conan.tools.intel import IntelCC
 from conan.tools.microsoft import VCVars
 from conan.tools.microsoft.visual import vs_ide_version
+from conans.client.generators import relativize_generated_file
 from conans.errors import ConanException
 from conans.model.options import _PackageOption
 from conans.util.files import save
@@ -171,6 +172,7 @@ class CMakeToolchain(object):
     def content(self):
         context = self._context()
         content = Template(self._template, trim_blocks=True, lstrip_blocks=True).render(**context)
+        content = relativize_generated_file(content, self._conanfile, "${CMAKE_CURRENT_LIST_DIR}")
         return content
 
     def generate(self):
diff --git a/conan/tools/env/environment.py b/conan/tools/env/environment.py
index f80d83ecf..1dd99b4be 100644
--- a/conan/tools/env/environment.py
+++ b/conan/tools/env/environment.py
@@ -3,6 +3,7 @@ import textwrap
 from collections import OrderedDict
 from contextlib import contextmanager
 
+from conans.client.generators import relativize_generated_file
 from conans.client.subsystems import deduce_subsystem, WINDOWS, subsystem_path
 from conans.errors import ConanException
 from conans.model.recipe_ref import ref_matches
@@ -414,14 +415,13 @@ class EnvVars:
             {deactivate}
             """).format(deactivate=deactivate if generate_deactivate else "")
         result = [capture]
-        location = os.path.abspath(os.path.dirname(file_location))
         for varname, varvalues in self._values.items():
             value = varvalues.get_str("%{name}%", subsystem=self._subsystem, pathsep=self._pathsep)
             # To make the script relocatable
-            value = value.replace(location, "%~dp0")
             result.append('set "{}={}"'.format(varname, value))
 
         content = "\n".join(result)
+        content = relativize_generated_file(content, self._conanfile, "%~dp0")
         # It is very important to save it correctly with utf-8, the Conan util save() is broken
         os.makedirs(os.path.dirname(os.path.abspath(file_location)), exist_ok=True)
         open(file_location, "w", encoding="utf-8").write(content)
diff --git a/conans/client/generators/__init__.py b/conans/client/generators/__init__.py
index 79f978e45..a4287c774 100644
--- a/conans/client/generators/__init__.py
+++ b/conans/client/generators/__init__.py
@@ -171,3 +171,15 @@ def _generate_aggregated_env(conanfile):
     if generated:
         conanfile.output.highlight("Generating aggregated env files")
         conanfile.output.info(f"Generated aggregated env files: {generated}")
+
+
+def relativize_generated_file(content, conanfile, placeholder):
+    abs_base_path = conanfile.folders._base_generators
+    if not abs_base_path or not os.path.isabs(abs_base_path):
+        return content
+    generators_folder = conanfile.generators_folder
+    rel_path = os.path.relpath(abs_base_path, generators_folder)
+    new_path = placeholder if rel_path == "." else os.path.join(placeholder, rel_path)
+    content = content.replace(abs_base_path, new_path)
+    content = content.replace(abs_base_path.replace("\\", "/"), new_path.replace("\\", "/"))
+    return content
diff --git a/conans/search/search.py b/conans/search/search.py
index 6af6217dc..01e09bbe1 100644
--- a/conans/search/search.py
+++ b/conans/search/search.py
@@ -61,6 +61,7 @@ def _evaluate(prop_name, prop_value, binary_info):
     if not prop_name.startswith("options."):
         return compatible_prop(info_settings.get(prop_name, None), prop_value)
     else:
+        prop_name = prop_name[len("options."):]
         return compatible_prop(info_options.get(prop_name, None), prop_value)
 
 


Test patch:
diff --git a/conans/test/functional/command/test_install_deploy.py b/conans/test/functional/command/test_install_deploy.py
index 2c36b2596..46915fdb5 100644
--- a/conans/test/functional/command/test_install_deploy.py
+++ b/conans/test/functional/command/test_install_deploy.py
@@ -13,31 +13,47 @@ from conans.test.utils.tools import TestClient
 from conans.util.files import save
 
 
-@pytest.mark.tool("cmake")
-def test_install_deploy():
+@pytest.fixture(scope="module")
+def _client():
     c = TestClient()
     c.run("new cmake_lib -d name=hello -d version=0.1")
     c.run("create . -o *:shared=True -tf=")
     conanfile = textwrap.dedent("""
-        import os
-        from conan import ConanFile
-        from conan.tools.files import save
-        class Tool(ConanFile):
-            name = "tool"
-            version = "1.0"
-            def package(self):
-                save(self, os.path.join(self.package_folder, "build", "my_tools.cmake"),
-                     'set(MY_TOOL_VARIABLE "Hello world!")')
-
-            def package_info(self):
-                self.cpp_info.includedirs = []
-                self.cpp_info.libdirs = []
-                self.cpp_info.bindirs = []
-                path_build_modules = os.path.join("build", "my_tools.cmake")
-                self.cpp_info.set_property("cmake_build_modules", [path_build_modules])
-            """)
+           import os
+           from conan import ConanFile
+           from conan.tools.files import save
+           class Tool(ConanFile):
+               name = "tool"
+               version = "1.0"
+               def package(self):
+                   save(self, os.path.join(self.package_folder, "build", "my_tools.cmake"),
+                        'set(MY_TOOL_VARIABLE "Hello world!")')
+
+               def package_info(self):
+                   self.cpp_info.includedirs = []
+                   self.cpp_info.libdirs = []
+                   self.cpp_info.bindirs = []
+                   path_build_modules = os.path.join("build", "my_tools.cmake")
+                   self.cpp_info.set_property("cmake_build_modules", [path_build_modules])
+               """)
     c.save({"conanfile.py": conanfile}, clean_first=True)
     c.run("create .")
+    return c
+
+
+@pytest.fixture()
+def client(_client):
+    """ this is much faster than creating and uploading everythin
+    """
+    client = TestClient(default_server_user=True)
+    shutil.rmtree(client.cache_folder)
+    shutil.copytree(_client.cache_folder, client.cache_folder)
+    return client
+
+
+@pytest.mark.tool("cmake")
+def test_install_deploy(client):
+    c = client
     custom_content = 'message(STATUS "MY_TOOL_VARIABLE=${MY_TOOL_VARIABLE}!")'
     cmake = gen_cmakelists(appname="my_app", appsources=["main.cpp"], find_package=["hello", "tool"],
                            custom_content=custom_content)
@@ -59,7 +75,6 @@ def test_install_deploy():
            clean_first=True)
     c.run("install . -o *:shared=True "
           "--deploy=deploy.py -of=mydeploy -g CMakeToolchain -g CMakeDeps")
-    print(c.out)
     c.run("remove * -c")  # Make sure the cache is clean, no deps there
     arch = c.get_default_host_profile().settings['arch']
     deps = c.load(f"mydeploy/hello-release-{arch}-data.cmake")
@@ -84,6 +99,56 @@ def test_install_deploy():
         assert "hello/0.1: Hello World Release!" in c2.out
 
 
+@pytest.mark.tool("cmake")
+def test_install_full_deploy_layout(client):
+    c = client
+    custom_content = 'message(STATUS "MY_TOOL_VARIABLE=${MY_TOOL_VARIABLE}!")'
+    cmake = gen_cmakelists(appname="my_app", appsources=["main.cpp"], find_package=["hello", "tool"],
+                           custom_content=custom_content)
+    conanfile = textwrap.dedent("""
+        [requires]
+        hello/0.1
+        tool/1.0
+        [generators]
+        CMakeDeps
+        CMakeToolchain
+        [layout]
+        cmake_layout
+        """)
+    c.save({"conanfile.txt": conanfile,
+            "CMakeLists.txt": cmake,
+            "main.cpp": gen_function_cpp(name="main", includes=["hello"], calls=["hello"])},
+           clean_first=True)
+    c.run("install . -o *:shared=True --deploy=full_deploy.py")
+    c.run("remove * -c")  # Make sure the cache is clean, no deps there
+    arch = c.get_default_host_profile().settings['arch']
+    folder = "/Release" if platform.system() != "Windows" else ""
+    rel_path = "../../" if platform.system() == "Windows" else "../../../"
+    deps = c.load(f"build{folder}/generators/hello-release-{arch}-data.cmake")
+    assert 'set(hello_PACKAGE_FOLDER_RELEASE "${CMAKE_CURRENT_LIST_DIR}/' \
+           f'{rel_path}full_deploy/host/hello/0.1/Release/{arch}")' in deps
+    assert 'set(hello_INCLUDE_DIRS_RELEASE "${hello_PACKAGE_FOLDER_RELEASE}/include")' in deps
+    assert 'set(hello_LIB_DIRS_RELEASE "${hello_PACKAGE_FOLDER_RELEASE}/lib")' in deps
+
+    # We can fully move it to another folder, and still works
+    tmp = os.path.join(temp_folder(), "relocated")
+    shutil.copytree(c.current_folder, tmp)
+    shutil.rmtree(c.current_folder)
+    c2 = TestClient(current_folder=tmp)
+    with c2.chdir(f"build{folder}"):
+        # I can totally build without errors with deployed
+        cmakelist = "../.." if platform.system() != "Windows" else ".."
+        c2.run_command(f"cmake {cmakelist} -DCMAKE_TOOLCHAIN_FILE=generators/conan_toolchain.cmake "
+                       "-DCMAKE_BUILD_TYPE=Release")
+        assert "MY_TOOL_VARIABLE=Hello world!!" in c2.out
+        c2.run_command("cmake --build . --config Release")
+        if platform.system() == "Windows":  # Only the .bat env-generators are relocatable atm
+            cmd = r"generators\conanrun.bat && Release\my_app.exe"
+            # For Lunux: cmd = ". mydeploy/conanrun.sh && ./my_app"
+            c2.run_command(cmd)
+            assert "hello/0.1: Hello World Release!" in c2.out
+
+
 def test_copy_files_deploy():
     c = TestClient()
     deploy = textwrap.dedent("""
@@ -173,18 +238,18 @@ def test_builtin_full_deploy():
           "-s build_type=Debug -s arch=x86")
 
     host_arch = c.get_default_host_profile().settings['arch']
-    release = c.load(f"output/host/dep/0.1/Release/{host_arch}/include/hello.h")
+    release = c.load(f"output/full_deploy/host/dep/0.1/Release/{host_arch}/include/hello.h")
     assert f"Release-{host_arch}" in release
-    debug = c.load("output/host/dep/0.1/Debug/x86/include/hello.h")
+    debug = c.load("output/full_deploy/host/dep/0.1/Debug/x86/include/hello.h")
     assert "Debug-x86" in debug
     cmake_release = c.load(f"output/dep-release-{host_arch}-data.cmake")
     assert 'set(dep_INCLUDE_DIRS_RELEASE "${dep_PACKAGE_FOLDER_RELEASE}/include")' in cmake_release
-    assert f"${{CMAKE_CURRENT_LIST_DIR}}/host/dep/0.1/Release/{host_arch}" in cmake_release
+    assert f"${{CMAKE_CURRENT_LIST_DIR}}/full_deploy/host/dep/0.1/Release/{host_arch}" in cmake_release
     assert 'set(dep_BUILD_MODULES_PATHS_RELEASE ' \
            '"${dep_PACKAGE_FOLDER_RELEASE}/build/my_tools_host.cmake")' in cmake_release
     cmake_debug = c.load("output/dep-debug-x86-data.cmake")
     assert 'set(dep_INCLUDE_DIRS_DEBUG "${dep_PACKAGE_FOLDER_DEBUG}/include")' in cmake_debug
-    assert "${CMAKE_CURRENT_LIST_DIR}/host/dep/0.1/Debug/x86" in cmake_debug
+    assert "${CMAKE_CURRENT_LIST_DIR}/full_deploy/host/dep/0.1/Debug/x86" in cmake_debug
     assert 'set(dep_BUILD_MODULES_PATHS_DEBUG ' \
            '"${dep_PACKAGE_FOLDER_DEBUG}/build/my_tools_host.cmake")' in cmake_debug
 
@@ -198,14 +263,14 @@ def test_deploy_reference():
 
     c.run("install  --requires=pkg/1.0 --deploy=full_deploy --output-folder=output")
     # NOTE: Full deployer always use build_type/arch, even if None/None in the path, same structure
-    header = c.load("output/host/pkg/1.0/include/hi.h")
+    header = c.load("output/full_deploy/host/pkg/1.0/include/hi.h")
     assert "hi" in header
 
     # Testing that we can deploy to the current folder too
     c.save({}, clean_first=True)
     c.run("install  --requires=pkg/1.0 --deploy=full_deploy")
     # NOTE: Full deployer always use build_type/arch, even if None/None in the path, same structure
-    header = c.load("host/pkg/1.0/include/hi.h")
+    header = c.load("full_deploy/host/pkg/1.0/include/hi.h")
     assert "hi" in header
 
 
@@ -217,14 +282,14 @@ def test_deploy_overwrite():
     c.run("create .")
 
     c.run("install  --requires=pkg/1.0 --deploy=full_deploy --output-folder=output")
-    header = c.load("output/host/pkg/1.0/include/hi.h")
+    header = c.load("output/full_deploy/host/pkg/1.0/include/hi.h")
     assert "hi" in header
 
     # modify the package
     c.save({"conanfile.py": GenConanfile("pkg", "1.0").with_package_file("include/hi.h", "bye")})
     c.run("create .")
     c.run("install  --requires=pkg/1.0 --deploy=full_deploy --output-folder=output")
-    header = c.load("output/host/pkg/1.0/include/hi.h")
+    header = c.load("output/full_deploy/host/pkg/1.0/include/hi.h")
     assert "bye" in header
 
 
@@ -241,12 +306,12 @@ def test_deploy_editable():
     # If we don't change to another folder, the full_deploy will be recursive and fail
     with c.chdir(temp_folder()):
         c.run("install  --requires=pkg/1.0 --deploy=full_deploy --output-folder=output")
-        header = c.load("output/host/pkg/1.0/src/include/hi.h")
+        header = c.load("output/full_deploy/host/pkg/1.0/src/include/hi.h")
         assert "hi" in header
 
 
 def test_deploy_single_package():
-    """ Lets try a deploy that executes on a single package reference
+    """ Let's try a deploy that executes on a single package reference
     """
     c = TestClient()
     c.save({"conanfile.py": GenConanfile("pkg", "1.0").with_package_file("include/hi.h", "hi"),
@@ -255,10 +320,10 @@ def test_deploy_single_package():
 
     # if we deploy one --requires, we get that package
     c.run("install  --requires=pkg/1.0 --deploy=direct_deploy --output-folder=output")
-    header = c.load("output/pkg/include/hi.h")
+    header = c.load("output/direct_deploy/pkg/include/hi.h")
     assert "hi" in header
 
     # If we deploy a local conanfile.txt, we get deployed its direct dependencies
     c.run("install consumer/conanfile.txt --deploy=direct_deploy --output-folder=output2")
-    header = c.load("output2/pkg/include/hi.h")
+    header = c.load("output2/direct_deploy/pkg/include/hi.h")
     assert "hi" in header
diff --git a/conans/test/functional/toolchains/cmake/test_ninja.py b/conans/test/functional/toolchains/cmake/test_ninja.py
index 2548b9951..5e40b498c 100644
--- a/conans/test/functional/toolchains/cmake/test_ninja.py
+++ b/conans/test/functional/toolchains/cmake/test_ninja.py
@@ -5,7 +5,6 @@ import pytest
 
 from conan.tools.cmake import CMakeToolchain
 from conan.tools.cmake.presets import load_cmake_presets
-from conan.tools.build import load_toolchain_args
 from conans.test.assets.cmake import gen_cmakelists
 from conans.test.assets.genconanfile import GenConanfile
 from conans.test.assets.sources import gen_function_h, gen_function_cpp
@@ -79,7 +78,7 @@ def test_locally_build_linux(build_type, shared, client):
     assert 'cmake -G "Ninja"' in client.out
     assert "main: {}!".format(build_type) in client.out
     client.run(f"install --requires=hello/1.0@ --deploy=full_deploy -of=mydeploy {settings}")
-    deploy_path = os.path.join(client.current_folder, "mydeploy", "host", "hello", "1.0",
+    deploy_path = os.path.join(client.current_folder, "mydeploy", "full_deploy", "host", "hello", "1.0",
                                build_type, "x86_64")
     client.run_command(f"LD_LIBRARY_PATH='{deploy_path}/lib' {deploy_path}/bin/myapp")
     check_exe_run(client.out, ["main", "hello"], "gcc", None, build_type, "x86_64", cppstd=None)
@@ -113,7 +112,7 @@ def test_locally_build_msvc(build_type, shared, client):
     assert 'cmake -G "Ninja"' in client.out
     assert "main: {}!".format(build_type) in client.out
     client.run(f"install --requires=hello/1.0@ --deploy=full_deploy -of=mydeploy {settings}")
-    client.run_command(fr"mydeploy\host\hello\1.0\{build_type}\x86_64\bin\myapp.exe")
+    client.run_command(fr"mydeploy\full_deploy\host\hello\1.0\{build_type}\x86_64\bin\myapp.exe")
     check_exe_run(client.out, ["main", "hello"], "msvc", "19", build_type, "x86_64", cppstd="14")
 
 
diff --git a/conans/test/integration/command/remove_test.py b/conans/test/integration/command/remove_test.py
index 16d2a2d7d..5fc1bb384 100644
--- a/conans/test/integration/command/remove_test.py
+++ b/conans/test/integration/command/remove_test.py
@@ -329,6 +329,11 @@ def test_new_remove_package_revisions_expressions(populated_client, with_remote,
         assert data.get("error_msg") in populated_client.out
 
 
+def test_package_query_no_package_ref(populated_client):
+    populated_client.run("remove * -p 'compiler=clang'", assert_error=True)
+    assert "--package-query supplied but the pattern does not match packages" in populated_client.out
+
+
 def _get_all_recipes(client, with_remote):
     api = ConanAPI(client.cache_folder)
     remote = api.remotes.get("default") if with_remote else None
diff --git a/conans/test/integration/command_v2/list_test.py b/conans/test/integration/command_v2/list_test.py
index a9367e62b..87f5581a6 100644
--- a/conans/test/integration/command_v2/list_test.py
+++ b/conans/test/integration/command_v2/list_test.py
@@ -584,6 +584,37 @@ def test_list_prefs_query_custom_settings():
     assert "newsetting.subsetting: 2" not in c.out
 
 
+def test_list_query_options():
+    """
+    Make sure query works for custom settings
+    https://github.com/conan-io/conan/issues/13617
+    """
+    c = TestClient(default_server_user=True)
+    c.save({"conanfile.py": GenConanfile("pkg", "1.0").with_option("myoption", [1, 2, 3])})
+    c.run("create . -o myoption=1")
+    c.run("create . -o myoption=2")
+    c.run("create . -o myoption=3")
+
+    c.run("list pkg/1.0:* -p options.myoption=1")
+    assert "myoption: 1" in c.out
+    assert "myoption: 2" not in c.out
+    assert "myoption: 3" not in c.out
+    c.run("list pkg/1.0:* -p options.myoption=2")
+    assert "myoption: 1" not in c.out
+    assert "myoption: 2" in c.out
+    assert "myoption: 3" not in c.out
+
+    c.run("upload * -r=default -c")
+    c.run("list pkg/1.0:* -p options.myoption=1 -r=default")
+    assert "myoption: 1" in c.out
+    assert "myoption: 2" not in c.out
+    assert "myoption: 3" not in c.out
+    c.run("list pkg/1.0:* -p options.myoption=2 -r=default")
+    assert "myoption: 1" not in c.out
+    assert "myoption: 2" in c.out
+    assert "myoption: 3" not in c.out
+
+
 class TestListNoUserChannel:
     def test_no_user_channel(self):
         c = TestClient(default_server_user=True)
diff --git a/conans/test/integration/command_v2/test_output_level.py b/conans/test/integration/command_v2/test_output_level.py
index 60e2bfe36..ade77607c 100644
--- a/conans/test/integration/command_v2/test_output_level.py
+++ b/conans/test/integration/command_v2/test_output_level.py
@@ -41,7 +41,7 @@ def test_output_level():
     t.run("create . --name foo --version 1.0 -v")
     assert "This is a trace" not in t.out
     assert "This is a debug" not in t.out
-    assert "This is a verbose" in t.out
+    assert "This is a verbose" not in t.out
     assert "This is a info" in t.out
     assert "This is a highlight" in t.out
     assert "This is a success" in t.out
diff --git a/conans/test/integration/settings/settings_override_test.py b/conans/test/integration/settings/settings_override_test.py
index 7a628ae80..97c40d95a 100644
--- a/conans/test/integration/settings/settings_override_test.py
+++ b/conans/test/integration/settings/settings_override_test.py
@@ -81,7 +81,7 @@ def test_exclude_patterns_settings():
     client.run("create zlib --name zlib --version 1.0")
     client.run("create openssl --name openssl --version 1.0")
 
-    # We miss openss and zlib debug packages
+    # We miss openssl and zlib debug packages
     client.run("install consumer -s build_type=Debug", assert_error=True)
     assert "ERROR: Missing prebuilt package for 'openssl/1.0', 'zlib/1.0'" in client.out
 
@@ -100,7 +100,7 @@ def test_exclude_patterns_settings():
     client.run("install --requires consumer/1.0 -s consumer/*:build_type=Debug")
 
     # Priority between package scoped settings
-    client.run('remove consumer/*#* -p="build_type=Debug" -c')
+    client.run('remove consumer/*#* -c')
     client.run("install --reference consumer/1.0 -s build_type=Debug", assert_error=True)
     # Pre-check, there is no Debug package for any of them
     assert "ERROR: Missing prebuilt package for 'consumer/1.0', 'openssl/1.0', 'zlib/1.0'"
diff --git a/conans/test/integration/symlinks/symlinks_test.py b/conans/test/integration/symlinks/symlinks_test.py
index 39ddba59e..544ee2323 100644
--- a/conans/test/integration/symlinks/symlinks_test.py
+++ b/conans/test/integration/symlinks/symlinks_test.py
@@ -58,7 +58,7 @@ def test_complete_round_trip():
     c.run("remove * -c")
     c.save({}, clean_first=True)
     c.run("install --requires=hello/0.1 --deploy=full_deploy")
-    checker(os.path.join(c.current_folder, "host", "hello", "0.1"))
+    checker(os.path.join(c.current_folder, "full_deploy", "host", "hello", "0.1"))
 
 
 @pytest.mark.skipif(platform.system() == "Windows", reason="Requires Symlinks")
@@ -90,7 +90,7 @@ def test_complete_round_trip_broken_link():
     c.run("remove * -c")
     c.save({}, clean_first=True)
     c.run("install --requires=hello/0.1 --deploy=full_deploy")
-    checker(os.path.join(c.current_folder, "host", "hello", "0.1"))
+    checker(os.path.join(c.current_folder, "full_deploy", "host", "hello", "0.1"))
 
 
 @pytest.mark.skipif(platform.system() == "Windows", reason="Requires Symlinks")
@@ -127,7 +127,7 @@ def test_complete_round_trip_external_link():
     c.run("remove * -c")
     c.save({}, clean_first=True)
     c.run("install --requires=hello/0.1 --deploy=full_deploy")
-    checker(os.path.join(c.current_folder, "host", "hello", "0.1"))
+    checker(os.path.join(c.current_folder, "full_deploy", "host", "hello", "0.1"))
 
 
 @pytest.mark.skipif(platform.system() == "Windows", reason="Requires Symlinks")
@@ -172,7 +172,7 @@ def test_complete_round_trip_folders():
     c.run("remove * -c")
     c.save({}, clean_first=True)
     c.run("install --requires=hello/0.1 --deploy=full_deploy")
-    checker(os.path.join(c.current_folder, "host", "hello", "0.1"))
+    checker(os.path.join(c.current_folder, "full_deploy", "host", "hello", "0.1"))
 
 
 @pytest.mark.skipif(platform.system() != "Linux", reason="Only linux")
@@ -232,7 +232,7 @@ def test_package_with_symlinks(package_files):
     # Check package files are there
     package_folder = client2.get_latest_pkg_layout(pref).package()
     assert_folder_symlinks(package_folder)
-    assert_folder_symlinks(os.path.join(client2.current_folder, "host", "hello", "0.1"))
+    assert_folder_symlinks(os.path.join(client2.current_folder, "full_deploy", "host", "hello", "0.1"))
 
 
 @pytest.mark.skipif(platform.system() == "Windows", reason="Symlinks not in Windows")
diff --git a/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py b/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
index 125e37d87..792f69d98 100644
--- a/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
+++ b/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
@@ -727,7 +727,7 @@ def test_pkg_config_block():
     assert 'set(PKG_CONFIG_EXECUTABLE /usr/local/bin/pkg-config CACHE FILEPATH ' in toolchain
     pathsep = ":" if os_ != "Windows" else ";"
     pkg_config_path_set = 'set(ENV{PKG_CONFIG_PATH} "%s$ENV{PKG_CONFIG_PATH}")' % \
-                          (client.current_folder.replace("\\", "/") + pathsep)
+                          ("${CMAKE_CURRENT_LIST_DIR}" + pathsep)
     assert pkg_config_path_set in toolchain
 
 
diff --git a/conans/test/unittests/tools/cmake/test_cmakedeps.py b/conans/test/unittests/tools/cmake/test_cmakedeps.py
index 95ce84b81..6320daa5d 100644
--- a/conans/test/unittests/tools/cmake/test_cmakedeps.py
+++ b/conans/test/unittests/tools/cmake/test_cmakedeps.py
@@ -22,7 +22,7 @@ def test_cpp_info_name_cmakedeps():
                                    "arch": ["x86"]})
     conanfile.settings.build_type = "Release"
     conanfile.settings.arch = "x86"
-    conanfile.folders.set_base_generators("/")
+    conanfile.folders.set_base_generators("/some/abs/path")  # non-existing to not relativize
 
     cpp_info = CppInfo(set_defaults=True)
     cpp_info.set_property("cmake_target_name", "MySuperPkg1::MySuperPkg1")
@@ -63,7 +63,7 @@ def test_cpp_info_name_cmakedeps_components():
                                    "arch": ["x86", "x64"]})
     conanfile.settings.build_type = "Debug"
     conanfile.settings.arch = "x64"
-    conanfile.folders.set_base_generators("/")
+    conanfile.folders.set_base_generators("/some/abs/path")  # non-existing to not relativize
 
     cpp_info = CppInfo()
     cpp_info.set_property("cmake_file_name", "ComplexFileName1")
@@ -113,7 +113,7 @@ def test_cmake_deps_links_flags():
                                    "arch": ["x86"]})
     conanfile.settings.build_type = "Release"
     conanfile.settings.arch = "x86"
-    conanfile.folders.set_base_generators("/")
+    conanfile.folders.set_base_generators("/some/abs/path")  # non-existing to not relativize
 
     cpp_info = CppInfo()
     # https://github.com/conan-io/conan/issues/8811 regression, fix with explicit - instead of /
@@ -161,7 +161,7 @@ def test_component_name_same_package():
                                    "arch": ["x86"]})
     conanfile.settings.build_type = "Release"
     conanfile.settings.arch = "x86"
-    conanfile.folders.set_base_generators("/")
+    conanfile.folders.set_base_generators("/some/abs/path")  # non-existing to not relativize
 
     cpp_info = CppInfo(set_defaults=True)
 
diff --git a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
index a75a300a6..cfa06ebf9 100644
--- a/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
+++ b/conans/test/unittests/tools/cmake/test_cmaketoolchain.py
@@ -32,7 +32,7 @@ def conanfile():
     c.settings.os = "Windows"
     c.conf = Conf()
     c.conf.define("tools.cmake.cmaketoolchain:system_name", "potato")
-    c.folders.set_base_generators(".")
+    c.folders.set_base_generators("/some/abs/path")  # non-existing to not relativize
     c._conan_node = Mock()
     c._conan_node.transitive_deps = {}
     return c
@@ -146,7 +146,7 @@ def conanfile_apple():
     c.settings.os.version = "10.15"
     c.settings_build = c.settings
     c.conf = Conf()
-    c.folders.set_base_generators(".")
+    c.folders.set_base_generators("/some/abs/path")  # non-existing to not relativize
     c._conan_node = Mock()
     c._conan_node.dependencies = []
     c._conan_node.transitive_deps = {}