Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve relative paths in generators #17945

Open
wants to merge 3 commits into
base: develop2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions conan/internal/api/install/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,15 +242,20 @@ def relativize_paths(conanfile, placeholder):
return abs_base_path, new_path


def relativize_path(path, conanfile, placeholder):
abs_base_path, new_path = relativize_paths(conanfile, placeholder)
if abs_base_path is None:
def relativize_path(path, conanfile, placeholder, normalize=True):
"""
relative path from the "generators_folder" to "path", asuming the root file, like
conan_toolchain.cmake will be directly in the "generators_folder"
"""
base_common_folder = conanfile.folders._base_generators # noqa
if not base_common_folder or not os.path.isabs(base_common_folder):
return path
if path.startswith(abs_base_path):
path = path.replace(abs_base_path, new_path, 1)
else:
abs_base_path = abs_base_path.replace("\\", "/")
new_path = new_path.replace("\\", "/")
if path.startswith(abs_base_path):
path = path.replace(abs_base_path, new_path, 1)
try:
common_path = os.path.commonpath([path, conanfile.generators_folder, base_common_folder])
if common_path == base_common_folder:
rel_path = os.path.relpath(path, conanfile.generators_folder)
new_path = os.path.join(placeholder, rel_path)
return new_path.replace("\\", "/") if normalize else new_path
except ValueError: # In case the unit in Windows is different, path cannot be made relative
pass
return path
2 changes: 1 addition & 1 deletion conan/tools/microsoft/msbuilddeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def join_paths(paths):
root_folder = escape_path(root_folder)
# Make the root_folder relative to the generated conan_vars_xxx.props file
relative_root_folder = relativize_path(root_folder, self._conanfile,
"$(MSBuildThisFileDirectory)")
"$(MSBuildThisFileDirectory)", normalize=False)

bin_dirs = join_paths(cpp_info.bindirs)
res_dirs = join_paths(cpp_info.resdirs)
Expand Down
40 changes: 38 additions & 2 deletions test/functional/command/test_install_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,9 +511,10 @@ def package_info(self):
expected = sorted(["pkga.so", "pkgb.so", "pkga.dll"])
assert sorted(os.listdir(os.path.join(c.current_folder, "myruntime"))) == expected


@pytest.mark.parametrize("symlink, expected",
[(True, ["libfoo.so.0.1.0", "libfoo.so.0", "libfoo.so"]),
(False, ["libfoo.so.0.1.0",])])
(False, ["libfoo.so.0.1.0"])])
def test_runtime_deploy_symlinks(symlink, expected):
""" The deployer runtime_deploy should preserve symlinks when deploying shared libraries
"""
Expand All @@ -531,7 +532,7 @@ def package(self):
os.symlink(src="libfoo.so.0", dst="libfoo.so")
""")
c.save({"foo/conanfile.py": conanfile,
"foo/lib/libfoo.so.0.1.0": "",})
"foo/lib/libfoo.so.0.1.0": ""})
c.run("export-pkg foo/ --name=foo --version=0.1.0")
c.run(f"install --requires=foo/0.1.0 --deployer=runtime_deploy --deployer-folder=output -c:a tools.deployer:symlinks={symlink}")

Expand Down Expand Up @@ -565,3 +566,38 @@ def test_deployer_errors():
c.run("install . --deployer=mydeploy2.py", assert_error=True)
# The error message says conanfile, not a big deal still path to file is shown
assert "ERROR: Unable to load conanfile" in c.out


def test_deploy_relative_paths():
c = TestClient()
consumer = textwrap.dedent("""
import os
from conan import ConanFile
class Consumer(ConanFile):
requires = "pkg/0.1"
settings = "build_type"
os = "build_type"
generators = "CMakeDeps"
def layout(self):
self.folders.build = os.path.join("some/sub/folders")
self.folders.generators = os.path.join(self.folders.build, "generators")
""")
deploy = textwrap.dedent("""
import os, shutil
def deploy(graph, output_folder):
conanfile = graph.root.conanfile
output_folder = os.path.join(conanfile.build_folder, "installed")
for dep in conanfile.dependencies.values():
new_folder = os.path.join(output_folder, dep.ref.name)
shutil.copytree(dep.package_folder, new_folder, symlinks=True)
dep.set_deploy_folder(new_folder)
""")
c.save({"pkg/conanfile.py": GenConanfile("pkg", "0.1"),
"consumer/conanfile.py": consumer,
"mydeploy.py": deploy})
c.run("create pkg")

# If we don't change to another folder, the full_deploy will be recursive and fail
c.run("install consumer --build=missing --deployer=mydeploy.py")
data = c.load("consumer/some/sub/folders/generators/pkg-release-data.cmake")
assert 'set(pkg_PACKAGE_FOLDER_RELEASE "${CMAKE_CURRENT_LIST_DIR}/../installed/pkg")' in data