diff --git a/conan/tools/microsoft/msbuilddeps.py b/conan/tools/microsoft/msbuilddeps.py index 5c84e68e267..60c566725c9 100644 --- a/conan/tools/microsoft/msbuilddeps.py +++ b/conan/tools/microsoft/msbuilddeps.py @@ -140,7 +140,7 @@ def _dep_name(dep, build): dep_name += "_build" return dep_name - def _vars_props_file(self, dep, name, cpp_info, deps, build): + def _vars_props_file(self, require, dep, name, cpp_info, deps, build): """ content for conan_vars_poco_x86_release.props, containing the variables for 1 config This will be for 1 package or for one component of a package @@ -176,11 +176,11 @@ def join_paths(paths): fields = { 'name': name, 'root_folder': package_folder, - 'bin_dirs': join_paths(cpp_info.bindirs), + 'bin_dirs': join_paths(cpp_info.bindirs) if require.run else "", 'res_dirs': join_paths(cpp_info.resdirs), - 'include_dirs': join_paths(cpp_info.includedirs), - 'lib_dirs': join_paths(cpp_info.libdirs), - 'libs': "".join([add_valid_ext(lib) for lib in cpp_info.libs]), + 'include_dirs': join_paths(cpp_info.includedirs) if require.headers else "", + 'lib_dirs': join_paths(cpp_info.libdirs) if require.libs else "", + 'libs': "".join([add_valid_ext(lib) for lib in cpp_info.libs]) if require.libs else "", # TODO: Missing objects 'system_libs': "".join([add_valid_ext(sys_dep) for sys_dep in cpp_info.system_libs]), 'definitions': "".join("%s;" % d for d in cpp_info.defines), @@ -276,7 +276,7 @@ def _conandeps(self): content=pkg_aggregated_content) return {conandeps_filename: pkg_aggregated_content} - def _package_props_files(self, dep, build=False): + def _package_props_files(self, require, dep, build=False): """ all the files for a given package: - conan_pkgname_vars_config.props: definition of variables, one per config - conan_pkgname_config.props: The one using those variables. This is very different for @@ -305,8 +305,8 @@ def _package_props_files(self, dep, build=False): public_deps.append(pkg if pkg == cmp_name else "{}_{}".format(pkg, cmp_name)) else: # Points to a component of same package public_deps.append("{}_{}".format(dep_name, r)) - result[vars_filename] = self._vars_props_file(dep, full_comp_name, comp_info, - public_deps, build=build) + result[vars_filename] = self._vars_props_file(require, dep, full_comp_name, + comp_info, public_deps, build=build) result[activate_filename] = self._activate_props_file(full_comp_name, vars_filename, public_deps, build=build) result[comp_filename] = self._dep_props_file(full_comp_name, comp_filename, @@ -323,7 +323,7 @@ def _package_props_files(self, dep, build=False): pkg_filename = "conan_%s.props" % dep_name public_deps = [self._dep_name(d, build) for r, d in dep.dependencies.direct_host.items() if r.visible] - result[vars_filename] = self._vars_props_file(dep, dep_name, cpp_info, + result[vars_filename] = self._vars_props_file(require, dep, dep_name, cpp_info, public_deps, build=build) result[activate_filename] = self._activate_props_file(dep_name, vars_filename, public_deps, build=build) @@ -336,14 +336,12 @@ def _content(self): raise ConanException("The 'msbuild' generator requires a 'build_type' setting value") result = {} - host_req = list(self._conanfile.dependencies.host.values()) - test_req = list(self._conanfile.dependencies.test.values()) - for dep in host_req + test_req: - result.update(self._package_props_files(dep, build=False)) - - build_req = list(self._conanfile.dependencies.build.values()) - for dep in build_req: - result.update(self._package_props_files(dep, build=True)) + for req, dep in self._conanfile.dependencies.host.items(): + result.update(self._package_props_files(req, dep, build=False)) + for req, dep in self._conanfile.dependencies.test.items(): + result.update(self._package_props_files(req, dep, build=False)) + for req, dep in self._conanfile.dependencies.build.items(): + result.update(self._package_props_files(req, dep, build=True)) # Include all direct build_requires for host context. This might change result.update(self._conandeps()) diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_transitivity.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_transitivity.py index 0d881eaa673..aec37ec1c10 100644 --- a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_transitivity.py +++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_transitivity.py @@ -5,20 +5,13 @@ from conan.tools.env.environment import environment_wrap_command from conans.test.assets.cmake import gen_cmakelists -from conans.test.assets.pkg_cmake import pkg_cmake from conans.test.assets.sources import gen_function_cpp -from conans.test.utils.tools import TestClient @pytest.mark.skipif(platform.system() != "Windows", reason="Requires MSBuild") @pytest.mark.tool("cmake") -def test_transitive_headers_not_public(): - c = TestClient() - - c.save(pkg_cmake("liba", "0.1")) - c.run("create .") - c.save(pkg_cmake("libb", "0.1", requires=["liba/0.1"]), clean_first=True) - c.run("create .") +def test_transitive_headers_not_public(transitive_libraries): + c = transitive_libraries conanfile = textwrap.dedent("""\ from conan import ConanFile @@ -57,13 +50,8 @@ def build(self): @pytest.mark.skipif(platform.system() != "Windows", reason="Requires MSBuild") @pytest.mark.tool("cmake") -def test_shared_requires_static(): - c = TestClient() - - c.save(pkg_cmake("liba", "0.1")) - c.run("create .") - c.save(pkg_cmake("libb", "0.1", requires=["liba/0.1"]), clean_first=True) - c.run("create . -o libb/*:shared=True") +def test_shared_requires_static(transitive_libraries): + c = transitive_libraries conanfile = textwrap.dedent("""\ from conan import ConanFile @@ -97,13 +85,8 @@ def build(self): @pytest.mark.skipif(platform.system() != "Windows", reason="Requires MSBuild") @pytest.mark.tool("cmake") -def test_transitive_binary_skipped(): - c = TestClient() - - c.save(pkg_cmake("liba", "0.1")) - c.run("create .") - c.save(pkg_cmake("libb", "0.1", requires=["liba/0.1"]), clean_first=True) - c.run("create . -o libb/*:shared=True") +def test_transitive_binary_skipped(transitive_libraries): + c = transitive_libraries # IMPORTANT: liba binary can be removed, no longer necessary c.run("remove liba* -p -f") diff --git a/conans/test/functional/toolchains/conftest.py b/conans/test/functional/toolchains/conftest.py new file mode 100644 index 00000000000..0ebdd659865 --- /dev/null +++ b/conans/test/functional/toolchains/conftest.py @@ -0,0 +1,28 @@ +import os +import shutil + +import pytest + +from conans.test.assets.pkg_cmake import pkg_cmake +from conans.test.utils.test_files import temp_folder +from conans.test.utils.tools import TestClient + + +@pytest.fixture(scope="session") +def _transitive_libraries(): + c = TestClient() + + c.save(pkg_cmake("liba", "0.1")) + c.run("create .") + c.save(pkg_cmake("libb", "0.1", requires=["liba/0.1"]), clean_first=True) + c.run("create .") + c.run("create . -o libb/*:shared=True") + return c + + +@pytest.fixture() +def transitive_libraries(_transitive_libraries): + c = TestClient() + c.cache_folder = os.path.join(temp_folder(), ".conan2") + shutil.copytree(_transitive_libraries.cache_folder, c.cache_folder) + return c diff --git a/conans/test/functional/toolchains/microsoft/test_msbuilddeps_traits.py b/conans/test/functional/toolchains/microsoft/test_msbuilddeps_traits.py new file mode 100644 index 00000000000..e55d24d6645 --- /dev/null +++ b/conans/test/functional/toolchains/microsoft/test_msbuilddeps_traits.py @@ -0,0 +1,39 @@ +import os +import platform +import textwrap + +import pytest + +from conan.tools.env.environment import environment_wrap_command +from conans.test.assets.cmake import gen_cmakelists +from conans.test.assets.genconanfile import GenConanfile +from conans.test.assets.sources import gen_function_cpp + + +@pytest.mark.skipif(platform.system() != "Windows", reason="Requires MSBuild") +def test_transitive_headers_not_public(transitive_libraries): + c = transitive_libraries + c.save({"conanfile.py": GenConanfile().with_settings("build_type", "arch") + .with_generator("MSBuildDeps").with_requires("libb/0.1")}, + clean_first=True) + + c.run("install .") + liba_data = c.load("conan_liba_vars_release_x64.props") + assert "" in liba_data + assert "$(ConanlibaRootFolder)/lib;" \ + in liba_data + assert "liba.lib;" in liba_data + + +@pytest.mark.skipif(platform.system() != "Windows", reason="Requires MSBuild") +def test_shared_requires_static(transitive_libraries): + c = transitive_libraries + c.save({"conanfile.py": GenConanfile().with_settings("build_type", "arch") + .with_generator("MSBuildDeps").with_requires("libb/0.1")}, + clean_first=True) + + c.run("install . -o libb*:shared=True") + assert not os.path.exists(os.path.join(c.current_folder, "conan_liba_vars_release_x64.props")) + libb_data = c.load("conan_libb_vars_release_x64.props") + # No dependency to liba, it has been skipped as unnecessary + assert "" in libb_data