From a46d4f7300eae3cbd7ec614a890ecdca425ae6be Mon Sep 17 00:00:00 2001 From: James Date: Tue, 15 Nov 2022 11:30:27 +0100 Subject: [PATCH] fixing package_folder=None in editable (#12529) * fixing package_folder=None in editable * fix * fix and test PkgConfigDeps and CMakeDeps too * fix test --- .../cmake/cmakedeps/templates/target_data.py | 27 ++++++--------- conan/tools/gnu/pkgconfigdeps.py | 6 ++-- conan/tools/microsoft/msbuilddeps.py | 9 ++--- .../layout/test_editable_msbuild.py | 24 ++++++++++++++ .../integration/layout/test_layout_paths.py | 33 +++++++++++++++++++ 5 files changed, 76 insertions(+), 23 deletions(-) create mode 100644 conans/test/integration/layout/test_layout_paths.py diff --git a/conan/tools/cmake/cmakedeps/templates/target_data.py b/conan/tools/cmake/cmakedeps/templates/target_data.py index 61011bb0cf5..cb4b733b0ec 100644 --- a/conan/tools/cmake/cmakedeps/templates/target_data.py +++ b/conan/tools/cmake/cmakedeps/templates/target_data.py @@ -44,15 +44,13 @@ def context(self): dependency_filenames = self._get_dependency_filenames() # Get the nodes that have the property cmake_find_mode=None (no files to generate) dependency_find_modes = self._get_dependencies_find_modes() - # package_folder might not be defined if Editable and layout() - package_folder = self.conanfile.package_folder or "" - package_folder = package_folder.replace('\\', '/').replace('$', '\\$').replace('"', '\\"') + root_folder = self._root_folder.replace('\\', '/').replace('$', '\\$').replace('"', '\\"') return {"global_cpp": global_cpp, "has_components": self.conanfile.cpp_info.has_components, "pkg_name": self.pkg_name, "file_name": self.file_name, - "package_folder": package_folder, + "package_folder": root_folder, "config_suffix": self.config_suffix, "components_names": components_names, "components_cpp": components_cpp, @@ -139,7 +137,12 @@ def template(self): def _get_global_cpp_cmake(self): global_cppinfo = self.conanfile.cpp_info.aggregated_components() pfolder_var_name = "{}_PACKAGE_FOLDER{}".format(self.pkg_name, self.config_suffix) - return _TargetDataContext(global_cppinfo, pfolder_var_name, self.conanfile.package_folder) + return _TargetDataContext(global_cppinfo, pfolder_var_name, self._root_folder) + + @property + def _root_folder(self): + return self.conanfile.recipe_folder if self.conanfile.package_folder is None \ + else self.conanfile.package_folder def _get_required_components_cpp(self): """Returns a list of (component_name, DepsCppCMake)""" @@ -149,8 +152,7 @@ def _get_required_components_cpp(self): direct_visible_host = self.conanfile.dependencies.filter({"build": False, "visible": True, "direct": True}) for comp_name, comp in sorted_comps.items(): - deps_cpp_cmake = _TargetDataContext(comp, pfolder_var_name, - self.conanfile.package_folder) + deps_cpp_cmake = _TargetDataContext(comp, pfolder_var_name, self._root_folder) public_comp_deps = [] for require in comp.requires: if "::" in require: # Points to a component of a different package @@ -216,9 +218,7 @@ def join_paths(paths): assert os.path.isabs(p), "{} is not absolute".format(p) # Trying to use a ${mypkg_PACKAGE_FOLDER}/include path instead of full - # TODO: We could do something similar for some build_folder for editables - # package_folder can be None if editable and layout() - if package_folder is not None and p.startswith(package_folder): + if p.startswith(package_folder): # Prepend the {{ pkg_name }}_PACKAGE_FOLDER{{ config_suffix }} rel = p[len(package_folder):] rel = rel.replace('\\', '/').replace('$', '\\$').replace('"', '\\"').lstrip("/") @@ -241,13 +241,6 @@ def join_defines(values, prefix=""): replace('"', '\\"')) for v in values) - def join_paths_single_var(values): - """ - semicolon-separated list of dirs: - e.g: set(LIBFOO_INCLUDE_DIR "/path/to/included/dir;/path/to/included/dir2") - """ - return '"%s"' % ";".join(p.replace('\\', '/').replace('$', '\\$') for p in values) - self.include_paths = join_paths(cpp_info.includedirs) self.lib_paths = join_paths(cpp_info.libdirs) self.res_paths = join_paths(cpp_info.resdirs) diff --git a/conan/tools/gnu/pkgconfigdeps.py b/conan/tools/gnu/pkgconfigdeps.py index 38a7737d6da..122e667b1a1 100644 --- a/conan/tools/gnu/pkgconfigdeps.py +++ b/conan/tools/gnu/pkgconfigdeps.py @@ -157,10 +157,12 @@ def __init__(self, conanfile, dep): def content(self, info): assert isinstance(info, _PCInfo) and info.cpp_info is not None - package_folder = self._dep.package_folder or "" # If editable, package_folder can be None + # If editable, package_folder can be None + root_folder = self._dep.recipe_folder if self._dep.package_folder is None \ + else self._dep.package_folder version = info.cpp_info.get_property("component_version") or self._dep.ref.version - prefix_path = package_folder.replace("\\", "/") + prefix_path = root_folder.replace("\\", "/") libdirs = _get_formatted_dirs(info.cpp_info.libdirs, prefix_path) includedirs = _get_formatted_dirs(info.cpp_info.includedirs, prefix_path) custom_content = info.cpp_info.get_property("pkg_config_custom_content") diff --git a/conan/tools/microsoft/msbuilddeps.py b/conan/tools/microsoft/msbuilddeps.py index 3c3d2739c7d..2053d38a033 100644 --- a/conan/tools/microsoft/msbuilddeps.py +++ b/conan/tools/microsoft/msbuilddeps.py @@ -158,17 +158,18 @@ def join_paths(paths): for p in paths: assert os.path.isabs(p), "{} is not absolute".format(p) full_path = escape_path(p) - if full_path.startswith(package_folder): - rel = full_path[len(package_folder)+1:] + if full_path.startswith(root_folder): + rel = full_path[len(root_folder)+1:] full_path = ("%s/%s" % (pkg_placeholder, rel)) ret.append(full_path) return "".join("{};".format(e) for e in ret) - package_folder = escape_path(dep.package_folder) + root_folder = dep.recipe_folder if dep.package_folder is None else dep.package_folder + root_folder = escape_path(root_folder) fields = { 'name': name, - 'root_folder': package_folder, + 'root_folder': root_folder, 'bin_dirs': join_paths(cpp_info.bindirs), 'res_dirs': join_paths(cpp_info.resdirs), 'include_dirs': join_paths(cpp_info.includedirs), diff --git a/conans/test/functional/layout/test_editable_msbuild.py b/conans/test/functional/layout/test_editable_msbuild.py index a06d8779e26..4773d72aed2 100644 --- a/conans/test/functional/layout/test_editable_msbuild.py +++ b/conans/test/functional/layout/test_editable_msbuild.py @@ -1,8 +1,10 @@ import os import platform +import textwrap import pytest +from conans.test.assets.genconanfile import GenConanfile from conans.test.assets.pkg_cmake import pkg_cmake_app from conans.test.utils.tools import TestClient @@ -62,3 +64,25 @@ def build_pkg(msg): c.run("create pkg") # print(c.out) assert "pkg/0.1: Created package" in c.out + + +@pytest.mark.skipif(platform.system() != "Windows", reason="Only for windows") +def test_editable_msbuilddeps(): + # https://github.com/conan-io/conan/issues/12521 + c = TestClient() + dep = textwrap.dedent(""" + from conan import ConanFile + class Dep(ConanFile): + name = "dep" + version = "0.1" + def layout(self): + pass + """) + c.save({"dep/conanfile.py": dep, + "pkg/conanfile.py": GenConanfile("pkg", "0.1").with_settings("build_type", "arch") + .with_requires("dep/0.1") + .with_generator("MSBuildDeps")}) + c.run("editable add dep dep/0.1") + c.run("install pkg") + # It doesn't crash anymore + assert "dep/0.1:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Editable" in c.out diff --git a/conans/test/integration/layout/test_layout_paths.py b/conans/test/integration/layout/test_layout_paths.py new file mode 100644 index 00000000000..5d863f411f7 --- /dev/null +++ b/conans/test/integration/layout/test_layout_paths.py @@ -0,0 +1,33 @@ +import textwrap + +from conans.test.assets.genconanfile import GenConanfile +from conans.test.utils.tools import TestClient + + +def test_editable_layout_paths(): + # https://github.com/conan-io/conan/issues/12521 + c = TestClient() + dep = textwrap.dedent(""" + import os + from conan import ConanFile + from conan.tools.files import save + class Dep(ConanFile): + name = "dep" + version = "0.1" + def layout(self): + self.cpp.source.includedirs = ["include"] + """) + c.save({"dep/conanfile.py": dep, + "pkg/conanfile.py": GenConanfile("pkg", "0.1").with_settings("build_type", "arch") + .with_requires("dep/0.1") + .with_generator("CMakeDeps") + .with_generator("PkgConfigDeps")}) + c.run("editable add dep dep/0.1") + c.run("install pkg") + # It doesn't crash anymore + assert "dep/0.1:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Editable" in c.out + arch = c.get_default_host_profile().settings['arch'] + data = c.load(f"dep-release-{arch}-data.cmake") + assert 'set(dep_INCLUDE_DIRS_RELEASE "${dep_PACKAGE_FOLDER_RELEASE}/include")' in data + pc = c.load("dep.pc") + assert "includedir1=${prefix}/include" in pc