Repository: conan-io/conan
Pull request #11971 (2022-08-27 12:01:22)

Added endeavouros to the distro list in `with_pacman` in oss.py  #11970
Changelog: (Bugfix): Adds "endeavouros" to the list of distros in with_pacman #11970

- [x] Refer to the issue that supports this Pull Request.
- [x] If the issue has missing info, explain the purpose/use case/pain/need that covers this Pull Request.
- [x] I've read the [Contributing guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).
- [x] I've followed the PEP8 style guides for Python code.
- [ ] I've opened another PR in the Conan docs repo to the ``develop`` branch, documenting this one. 

<sup>**Note:** By default this PR will skip the slower tests and will use a limited set of python versions. Check [here](https://github.com/conan-io/conan/blob/develop/.github/PR_INCREASE_TESTING.md) how to increase the testing level by writing some tags in the current PR body text.</sup>


<sup>**Note:** By default this PR will skip the slower tests and will use a limited set of python versions. Check [here](https://github.com/conan-io/conan/blob/develop/.github/PR_INCREASE_TESTING.md) how to increase the testing level by writing some tags in the current PR body text.</sup>


CLAassistant: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/conan-io/conan?pullRequest=11971) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/conan-io/conan?pullRequest=11971) before we can accept your contribution.<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/conan-io/conan?pullRequest=11971) it.</sub>
cchulo: @memsharded done
cchulo: well this is why I had the previous change, I traced the code back to oss.py, though you said it was legacy, that's what led me to that file
cchulo: Actually I should be more specific, the initial commit to oss.py was traced back from OpenGL's recipe, tools which is imported from `conans` and then just reading that code led me to `oss.py`, I decided not to change that file at your advise that it is legacy and instead implemented the change at the other location you suggested, not exactly sure how to test it to ensure that it is working. Still with your earlier advise to setup `[conf]` flags in my profile I was able to work around this anyway
memsharded: No, the code is ok, the change you did put the fix in the right place. I think the problem would be the same in the other legacy place as well.

The underlying issue is that Conan uses the return of ``distro.id()`` to feed it into those dictionaries. But it seems that ``distro.id()`` doesn't return ``endeavouros`` string, at least my inspection of the ``distro`` code. The way to check it would be just ``import distro + distro.id()`` in your ``python`` in your system.
cchulo: > No, the code is ok, the change you did put the fix in the right place. I think the problem would be the same in the other legacy place as well.
> 
> The underlying issue is that Conan uses the return of `distro.id()` to feed it into those dictionaries. But it seems that `distro.id()` doesn't return `endeavouros` string, at least my inspection of the `distro` code. The way to check it would be just `import distro + distro.id()` in your `python` in your system.

I had my hard drive fail, its going to take me a bit to get back to you, I will ping you as soon as I am able to, would be back up and running, but I have work, I may not be able to get back to this until this upcoming weekend

Patch:
diff --git a/conan/tools/gnu/pkgconfigdeps.py b/conan/tools/gnu/pkgconfigdeps.py
index 36cb3178d..2eb5a8ff8 100644
--- a/conan/tools/gnu/pkgconfigdeps.py
+++ b/conan/tools/gnu/pkgconfigdeps.py
@@ -36,21 +36,37 @@ def _get_component_aliases(dep, comp_name):
     return comp_aliases or []
 
 
-def _get_package_name(dep):
-    pkg_name = dep.cpp_info.get_property("pkg_config_name")
-    return pkg_name or _get_package_reference_name(dep)
+def _get_package_name(dep, build_context_suffix=None):
+    pkg_name = dep.cpp_info.get_property("pkg_config_name") or _get_package_reference_name(dep)
+    suffix = _get_suffix(dep, build_context_suffix)
+    return f"{pkg_name}{suffix}"
 
 
-def _get_component_name(dep, comp_name):
+def _get_component_name(dep, comp_name, build_context_suffix=None):
     if comp_name not in dep.cpp_info.components:
         # foo::foo might be referencing the root cppinfo
         if _get_package_reference_name(dep) == comp_name:
-            return _get_package_name(dep)
+            return _get_package_name(dep, build_context_suffix)
         raise ConanException("Component '{name}::{cname}' not found in '{name}' "
                              "package requirement".format(name=_get_package_reference_name(dep),
                                                           cname=comp_name))
     comp_name = dep.cpp_info.components[comp_name].get_property("pkg_config_name")
-    return comp_name
+    suffix = _get_suffix(dep, build_context_suffix)
+    return f"{comp_name}{suffix}" if comp_name else None
+
+
+def _get_suffix(req, build_context_suffix=None):
+    """
+    Get the package name suffix coming from PkgConfigDeps.build_context_suffix attribute, but only
+    for requirements declared as build requirement.
+
+    :param req: requirement ConanFile instance
+    :param build_context_suffix: `dict` with all the suffixes
+    :return: `str` with the suffix
+    """
+    if not build_context_suffix or not req.is_build_context:
+        return ""
+    return build_context_suffix.get(req.ref.name, "")
 
 
 def _get_formatted_dirs(folders, prefix_path_):
@@ -184,8 +200,9 @@ class PCContentGenerator:
 
 class PCGenerator:
 
-    def __init__(self, conanfile, dep):
+    def __init__(self, conanfile, dep, build_context_suffix=None):
         self._conanfile = conanfile
+        self._build_context_suffix = build_context_suffix or {}
         self._dep = dep
         self._content_generator = PCContentGenerator(self._conanfile, self._dep)
 
@@ -223,9 +240,9 @@ class PCGenerator:
                 req_conanfile = self._dep.dependencies.host[pkg_ref_name]
             else:  # For instance, dep == "hello/1.0" and req == "hello::cmp1" -> hello == hello
                 req_conanfile = self._dep
-            comp_name = _get_component_name(req_conanfile, comp_ref_name)
+            comp_name = _get_component_name(req_conanfile, comp_ref_name, self._build_context_suffix)
             if not comp_name:
-                pkg_name = _get_package_name(req_conanfile)
+                pkg_name = _get_package_name(req_conanfile, self._build_context_suffix)
                 # Creating a component name with namespace, e.g., dep-comp1
                 comp_name = _get_name_with_namespace(pkg_name, comp_ref_name)
             ret.append(comp_name)
@@ -239,16 +256,18 @@ class PCGenerator:
 
         :return: `list` of `_PCInfo` objects with all the components information
         """
-        pkg_name = _get_package_name(self._dep)
+        pkg_name = _get_package_name(self._dep, self._build_context_suffix)
         components_info = []
         # Loop through all the package's components
         for comp_ref_name, cpp_info in self._dep.cpp_info.get_sorted_components().items():
             # At first, let's check if we have defined some components requires, e.g., "dep::cmp1"
             comp_requires_names = self._get_cpp_info_requires_names(cpp_info)
-            comp_name = _get_component_name(self._dep, comp_ref_name)
+            comp_name = _get_component_name(self._dep, comp_ref_name, self._build_context_suffix)
             if not comp_name:
                 comp_name = _get_name_with_namespace(pkg_name, comp_ref_name)
-            comp_description = "Conan component: %s-%s" % (pkg_name, comp_name)
+                comp_description = f"Conan component: {comp_name}"
+            else:
+                comp_description = f"Conan component: {pkg_name}-{comp_name}"
             comp_aliases = _get_component_aliases(self._dep, comp_ref_name)
             # Save each component information
             components_info.append(_PCInfo(comp_name, comp_requires_names, comp_description,
@@ -262,14 +281,15 @@ class PCGenerator:
 
         :return: `_PCInfo` object with the package information
         """
-        pkg_name = _get_package_name(self._dep)
+        pkg_name = _get_package_name(self._dep, self._build_context_suffix)
         # At first, let's check if we have defined some global requires, e.g., "other::cmp1"
         requires = self._get_cpp_info_requires_names(self._dep.cpp_info)
         # If we have found some component requires it would be enough
         if not requires:
             # If no requires were found, let's try to get all the direct dependencies,
             # e.g., requires = "other_pkg/1.0"
-            requires = [_get_package_name(req) for req in self._dep.dependencies.direct_host.values()]
+            requires = [_get_package_name(req, self._build_context_suffix)
+                        for req in self._dep.dependencies.direct_host.values()]
         description = "Conan package: %s" % pkg_name
         aliases = _get_package_aliases(self._dep)
         cpp_info = self._dep.cpp_info
@@ -317,7 +337,7 @@ class PCGenerator:
         # Second, let's load the root package's PC file ONLY
         # if it does not already exist in components one
         # Issue related: https://github.com/conan-io/conan/issues/10341
-        pkg_name = _get_package_name(self._dep)
+        pkg_name = _get_package_name(self._dep, self._build_context_suffix)
         if f"{pkg_name}.pc" not in pc_files:
             package_info = _PCInfo(pkg_name, pkg_requires, f"Conan package: {pkg_name}", None,
                                    _get_package_aliases(self._dep))
@@ -335,6 +355,29 @@ class PkgConfigDeps:
 
     def __init__(self, conanfile):
         self._conanfile = conanfile
+        # Activate the build *.pc files for the specified libraries
+        self.build_context_activated = []
+        # If specified, the files/requires/names for the build context will be renamed appending
+        # a suffix. It is necessary in case of same require and build_require and will cause an error
+        self.build_context_suffix = {}
+
+    def _validate_build_requires(self, host_req, build_req):
+        """
+        Check if any package exists at host and build context at the same time, and
+        it doesn't have any suffix to avoid any name collisions
+
+        :param host_req: list of host requires
+        :param build_req: list of build requires
+        """
+        activated_br = {r.ref.name for r in build_req.values()
+                        if r.ref.name in self.build_context_activated}
+        common_names = {r.ref.name for r in host_req.values()}.intersection(activated_br)
+        without_suffixes = [common_name for common_name in common_names
+                            if self.build_context_suffix.get(common_name) is None]
+        if without_suffixes:
+            raise ConanException(f"The packages {without_suffixes} exist both as 'require' and as"
+                                 f" 'build require'. You need to specify a suffix using the "
+                                 f"'build_context_suffix' attribute at the PkgConfigDeps generator.")
 
     @property
     def content(self):
@@ -342,17 +385,32 @@ class PkgConfigDeps:
         pc_files = {}
         # Get all the dependencies
         host_req = self._conanfile.dependencies.host
+        build_req = self._conanfile.dependencies.build  # tool_requires
         test_req = self._conanfile.dependencies.test
 
-        for require, dep in list(host_req.items()) + list(test_req.items()):
+        # Check if it exists both as require and as build require without a suffix
+        self._validate_build_requires(host_req, build_req)
+
+        for require, dep in list(host_req.items()) + list(build_req.items()) + list(test_req.items()):
             # Require is not used at the moment, but its information could be used,
             # and will be used in Conan 2.0
-            pc_generator = PCGenerator(self._conanfile, dep)
+            # Filter the build_requires not activated with PkgConfigDeps.build_context_activated
+            if dep.is_build_context and dep.ref.name not in self.build_context_activated:
+                continue
+
+            pc_generator = PCGenerator(self._conanfile, dep, build_context_suffix=self.build_context_suffix)
             pc_files.update(pc_generator.pc_files)
         return pc_files
 
     def generate(self):
         """Save all the *.pc files"""
+        # FIXME: Remove this in 2.0
+        if not hasattr(self._conanfile, "settings_build") and \
+                      (self.build_context_activated or self.build_context_suffix):
+            raise ConanException("The 'build_context_activated' and 'build_context_build_modules' of"
+                                 " the PkgConfigDeps generator cannot be used without specifying"
+                                 " a build profile. e.g: -pr:b=default")
+
         # Current directory is the generators_folder
         generator_files = self.content
         for generator_file, content in generator_files.items():
diff --git a/conan/tools/microsoft/msbuild.py b/conan/tools/microsoft/msbuild.py
index 287c46d72..e7a8df5fb 100644
--- a/conan/tools/microsoft/msbuild.py
+++ b/conan/tools/microsoft/msbuild.py
@@ -28,7 +28,7 @@ class MSBuild(object):
             msvc_arch = conanfile.settings.get_safe("os.platform")
         self.platform = msvc_arch
 
-    def command(self, sln):
+    def command(self, sln, targets=None):
         cmd = ('msbuild "%s" /p:Configuration=%s /p:Platform=%s'
                % (sln, self.build_type, self.platform))
 
@@ -41,10 +41,15 @@ class MSBuild(object):
         if maxcpucount:
             cmd += " /m:{}".format(maxcpucount)
 
+        if targets:
+            if not isinstance(targets, list):
+                raise ConanException("targets argument should be a list")
+            cmd += " /target:{}".format(";".join(targets))
+
         return cmd
 
-    def build(self, sln):
-        cmd = self.command(sln)
+    def build(self, sln, targets=None):
+        cmd = self.command(sln, targets=targets)
         self._conanfile.run(cmd)
 
     @staticmethod
diff --git a/conan/tools/system/package_manager.py b/conan/tools/system/package_manager.py
index a416d2db5..ef281980f 100644
--- a/conan/tools/system/package_manager.py
+++ b/conan/tools/system/package_manager.py
@@ -38,7 +38,7 @@ class _SystemPackageManagerTool(object):
                                    "almalinux", "rocky"],
                            "dnf": ["fedora", "rhel", "centos", "mageia"],
                            "brew": ["Darwin"],
-                           "pacman": ["arch", "manjaro", "msys2"],
+                           "pacman": ["arch", "manjaro", "msys2", "endeavouros"],
                            "choco": ["Windows"],
                            "zypper": ["opensuse", "sles"],
                            "pkg": ["freebsd"],
diff --git a/conans/__init__.py b/conans/__init__.py
index 993b6a958..683fbf0a5 100644
--- a/conans/__init__.py
+++ b/conans/__init__.py
@@ -20,4 +20,4 @@ OAUTH_TOKEN = "oauth_token"
 SERVER_CAPABILITIES = [COMPLEX_SEARCH_CAPABILITY, REVISIONS]  # Server is always with revisions
 DEFAULT_REVISION_V1 = "0"
 
-__version__ = '1.52.0-dev'
+__version__ = '1.53.0-dev'
diff --git a/conans/client/graph/compatibility.py b/conans/client/graph/compatibility.py
index d4fee651c..b3440eaa0 100644
--- a/conans/client/graph/compatibility.py
+++ b/conans/client/graph/compatibility.py
@@ -27,6 +27,8 @@ class BinaryCompatibility:
                     compat_info.settings.update_values(settings)
                 options = elem.get("options")
                 if options:
-                    compat_info.options.update(options_values=OrderedDict(options))
+                    from conans.model.options import OptionsValues
+                    new_options = OptionsValues(options)
+                    compat_info.options.update(new_options)
                 result.append(compat_info)
         return result
diff --git a/conans/client/migrations_settings.py b/conans/client/migrations_settings.py
index 48c1a322a..3fb8f3df5 100644
--- a/conans/client/migrations_settings.py
+++ b/conans/client/migrations_settings.py
@@ -3873,3 +3873,5 @@ build_type: [None, Debug, Release, RelWithDebInfo, MinSizeRel]
 
 cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]  # Deprecated, use compiler.cppstd
 """
+
+settings_1_53_0 = settings_1_52_0


Test patch:
diff --git a/conans/test/functional/tools/test_files.py b/conans/test/functional/tools/test_files.py
index 6951636c3..cb6503ca0 100644
--- a/conans/test/functional/tools/test_files.py
+++ b/conans/test/functional/tools/test_files.py
@@ -359,8 +359,7 @@ def test_export_conandata_patches(mock_patch_ng):
                 export_conandata_patches(self)
 
             def source(self):
-                self.output.info(load(self, os.path.join(self.export_sources_folder,
-                                                         "patches/mypatch.patch")))
+                self.output.info(load(self, os.path.join(self.export_sources_folder, "patches/mypatch.patch")))
         """)
     conandata_yml = textwrap.dedent("""
         patches:
@@ -375,7 +374,7 @@ def test_export_conandata_patches(mock_patch_ng):
     client.save({"conandata.yml": ""})
     client.run("create .", assert_error=True)
     assert "export_conandata_patches(): No patches defined in conandata" in client.out
-    assert "ERROR: mypkg/1.0: Error in source() method, line 18" in client.out
+    assert "ERROR: mypkg/1.0: Error in source() method" in client.out
     # wrong patches
     client.save({"conandata.yml": "patches: 123"})
     client.run("create .", assert_error=True)
diff --git a/conans/test/integration/package_id/compatible_test.py b/conans/test/integration/package_id/compatible_test.py
index bc8918a7b..fb9393812 100644
--- a/conans/test/integration/package_id/compatible_test.py
+++ b/conans/test/integration/package_id/compatible_test.py
@@ -664,3 +664,43 @@ class TestNewCompatibility:
         assert "pkg/0.1: PackageInfo!: Gcc version: 4.8!" in c.out
         assert "pkg/0.1:22c594d7fed4994c59a1eacb24ff6ff48bc5c51c" in c.out
         assert "pkg/0.1: Already installed!" in c.out
+
+    # FIXME: This test already exists in Conan 2.0 (in this file). Please, remove this one.
+    def test_compatible_option(self):
+        client = TestClient()
+        conanfile = textwrap.dedent("""
+             from conan import ConanFile
+
+             class Pkg(ConanFile):
+                 options = {"optimized": [1, 2, 3]}
+                 default_options = {"optimized": 1}
+
+                 def compatibility(self):
+                     return [{"options": [("optimized", v)]}
+                             for v in range(int(self.options.optimized), 0, -1)]
+
+                 def package_info(self):
+                     self.output.info("PackageInfo!: Option optimized %s!"
+                                      % self.options.optimized)
+             """)
+        client.save({"conanfile.py": conanfile})
+        client.run("create . pkg/0.1@user/stable")
+        package_id = "a97db2488658dd582a070ba8b6c6975eb1601a33"
+        # package_id = client.created_package_id("pkg/0.1@user/stable")
+        assert f"pkg/0.1@user/stable: Package '{package_id}' created" in client.out
+
+        client.save({"conanfile.py": GenConanfile().with_require("pkg/0.1@user/stable")})
+        client.run("install . -o pkg/*:optimized=2")
+        # Information messages
+        missing_id = "d97fb97a840e4ac3b5e7bb8f79c87f1d333a85bc"
+        assert "pkg/0.1@user/stable: PackageInfo!: Option optimized 1!" in client.out
+        assert f"pkg/0.1@user/stable: Compatible package ID " \
+               f"{missing_id} equal to the default package ID" in client.out
+        assert f"pkg/0.1@user/stable: Main binary package '{missing_id}' missing. " \
+               f"Using compatible package '{package_id}'" in client.out
+        # checking the resulting dependencies
+        assert f"pkg/0.1@user/stable:{package_id} - Cache" in client.out
+        assert "pkg/0.1@user/stable: Already installed!" in client.out
+        client.run("install . -o pkg/*:optimized=3")
+        assert "pkg/0.1@user/stable: Already installed!" in client.out
+        assert f"pkg/0.1@user/stable:{package_id} - Cache" in client.out
diff --git a/conans/test/integration/toolchains/gnu/test_pkgconfigdeps.py b/conans/test/integration/toolchains/gnu/test_pkgconfigdeps.py
index 93ab67dc6..cda97f82f 100644
--- a/conans/test/integration/toolchains/gnu/test_pkgconfigdeps.py
+++ b/conans/test/integration/toolchains/gnu/test_pkgconfigdeps.py
@@ -2,8 +2,6 @@ import glob
 import os
 import textwrap
 
-import pytest
-
 from conans.test.assets.genconanfile import GenConanfile
 from conans.test.utils.tools import TestClient
 from conans.util.files import load
@@ -524,22 +522,28 @@ def test_pkgconfigdeps_with_test_requires():
     Related issue: https://github.com/conan-io/conan/issues/11376
     """
     client = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        class Pkg(ConanFile):
+            def package_info(self):
+                self.cpp_info.libs = ["lib%s"]
+        """)
     with client.chdir("app"):
-        client.run("new app/1.0 -m cmake_lib")
-        # client.run("new cmake_lib -d name=app -d version=1.0")
-        client.run("create .")
+        client.save({"conanfile.py": conanfile % "app"})
+        # client.run("create . --name=app --version=1.0")
+        client.run("create . app/1.0@")
     with client.chdir("test"):
-        client.run("new test/1.0 -m cmake_lib")
-        # client.run("new cmake_lib -d name=test -d version=1.0")
-        client.run("create .")
+        client.save({"conanfile.py": conanfile % "test"})
+        # client.run("create . --name=test --version=1.0")
+        client.run("create . test/1.0@")
     # Create library having build and test requires
-    conanfile = textwrap.dedent(r'''
+    conanfile = textwrap.dedent("""
         from conan import ConanFile
         class HelloLib(ConanFile):
             def build_requirements(self):
                 self.test_requires('app/1.0')
                 self.test_requires('test/1.0')
-        ''')
+        """)
     client.save({"conanfile.py": conanfile}, clean_first=True)
     client.run("install . -g PkgConfigDeps")
     assert "Description: Conan package: test" in client.load("test.pc")
@@ -573,3 +577,151 @@ def test_with_editable_layout():
         assert "Libs: -lmylib" in pc
         assert 'includedir1=' in pc
         assert 'Cflags: -I"${includedir1}"' in pc
+
+
+def test_tool_requires():
+    """
+    Testing if PC files are created for tool requires if build_context_activated/_suffix is used.
+
+    Issue related: https://github.com/conan-io/conan/issues/11710
+    """
+    client = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+
+        class PkgConfigConan(ConanFile):
+
+            def package_info(self):
+                self.cpp_info.libs = ["libtool"]
+        """)
+    client.save({"conanfile.py": conanfile})
+    client.run("create . tool/1.0@")
+
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+
+        class PkgConfigConan(ConanFile):
+
+            def package_info(self):
+                self.cpp_info.set_property("pkg_config_name", "libother")
+                self.cpp_info.components["cmp1"].libs = ["other_cmp1"]
+                self.cpp_info.components["cmp1"].set_property("pkg_config_name", "component1")
+                self.cpp_info.components["cmp2"].libs = ["other_cmp2"]
+                self.cpp_info.components["cmp3"].requires.append("cmp1")
+                self.cpp_info.components["cmp3"].set_property("pkg_config_name", "component3")
+        """)
+    client.save({"conanfile.py": conanfile}, clean_first=True)
+    client.run("create . other/1.0@")
+
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.gnu import PkgConfigDeps
+
+        class PkgConfigConan(ConanFile):
+            name = "demo"
+            version = "1.0"
+
+            def build_requirements(self):
+                self.build_requires("tool/1.0")
+                self.build_requires("other/1.0")
+
+            def generate(self):
+                tc = PkgConfigDeps(self)
+                tc.build_context_activated = ["other", "tool"]
+                tc.build_context_suffix = {"tool": "_bt", "other": "_bo"}
+                tc.generate()
+        """)
+    client.save({"conanfile.py": conanfile}, clean_first=True)
+    client.run("install . -pr:h default -pr:b default")
+    pc_files = [os.path.basename(i) for i in glob.glob(os.path.join(client.current_folder, '*.pc'))]
+    pc_files.sort()
+    # Let's check all the PC file names created just in case
+    assert pc_files == ['component1_bo.pc', 'component3_bo.pc',
+                        'libother_bo-cmp2.pc', 'libother_bo.pc', 'tool_bt.pc']
+    pc_content = client.load("tool_bt.pc")
+    assert "Name: tool_bt" in pc_content
+    pc_content = client.load("libother_bo.pc")
+    assert "Name: libother_bo" in pc_content
+    assert "Requires: component1_bo libother_bo-cmp2 component3_bo" == get_requires_from_content(pc_content)
+    pc_content = client.load("component1_bo.pc")
+    assert "Name: component1_bo" in pc_content
+    pc_content = client.load("libother_bo-cmp2.pc")
+    assert "Name: libother_bo-cmp2" in pc_content
+    pc_content = client.load("component3_bo.pc")
+    assert "Name: component3_bo" in pc_content
+    assert "Requires: component1_bo" == get_requires_from_content(pc_content)
+
+
+def test_tool_requires_not_created_if_no_activated():
+    """
+    Testing if there are no PC files created in no context are activated
+    """
+    client = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+
+        class PkgConfigConan(ConanFile):
+
+            def package_info(self):
+                self.cpp_info.libs = ["libtool"]
+        """)
+    client.save({"conanfile.py": conanfile})
+    client.run("create . tool/1.0@")
+
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+
+        class PkgConfigConan(ConanFile):
+            name = "demo"
+            version = "1.0"
+            generators = "PkgConfigDeps"
+
+            def build_requirements(self):
+                self.build_requires("tool/1.0")
+
+        """)
+    client.save({"conanfile.py": conanfile}, clean_first=True)
+    client.run("install . -pr:h default -pr:b default")
+    pc_files = [os.path.basename(i) for i in glob.glob(os.path.join(client.current_folder, '*.pc'))]
+    pc_files.sort()
+    assert pc_files == []
+
+
+def test_tool_requires_raise_exception_if_exist_both_require_and_build_one():
+    """
+    Testing if same dependency exists in both require and build require (without suffix)
+    """
+    client = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+
+        class PkgConfigConan(ConanFile):
+
+            def package_info(self):
+                self.cpp_info.libs = ["libtool"]
+        """)
+    client.save({"conanfile.py": conanfile})
+    client.run("create . tool/1.0@")
+
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        from conan.tools.gnu import PkgConfigDeps
+
+        class PkgConfigConan(ConanFile):
+            name = "demo"
+            version = "1.0"
+
+            def requirements(self):
+                self.requires("tool/1.0")
+
+            def build_requirements(self):
+                self.build_requires("tool/1.0")
+
+            def generate(self):
+                tc = PkgConfigDeps(self)
+                tc.build_context_activated = ["tool"]
+                tc.generate()
+        """)
+    client.save({"conanfile.py": conanfile}, clean_first=True)
+    client.run("install . -pr:h default -pr:b default", assert_error=True)
+    assert "The packages ['tool'] exist both as 'require' and as 'build require'" in client.out
diff --git a/conans/test/unittests/tools/microsoft/test_msbuild.py b/conans/test/unittests/tools/microsoft/test_msbuild.py
index 82bceeaf9..2311e5c0d 100644
--- a/conans/test/unittests/tools/microsoft/test_msbuild.py
+++ b/conans/test/unittests/tools/microsoft/test_msbuild.py
@@ -13,6 +13,23 @@ from conans.tools import load
 from conans import ConanFile, Settings
 
 
+def test_msbuild_targets():
+    c = ConfDefinition()
+    settings = MockSettings({"build_type": "Release",
+                             "compiler": "gcc",
+                             "compiler.version": "7",
+                             "os": "Linux",
+                             "arch": "x86_64"})
+    conanfile = ConanFileMock()
+    conanfile.settings = settings
+    conanfile.conf = c.get_conanfile_conf(None)
+
+    msbuild = MSBuild(conanfile)
+    cmd = msbuild.command('project.sln', targets=["static", "shared"])
+
+    assert '/target:static;shared' in cmd
+
+
 def test_msbuild_cpu_count():
     c = ConfDefinition()
     c.loads(textwrap.dedent("""\