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

Fix cmake config file patching on Windows #3399

Merged
merged 15 commits into from Oct 8, 2018

Fixed tests

  • Loading branch information...
lasote committed Sep 28, 2018
commit 46f1b72f920017f8f8650008f293feba461e1785
@@ -14,7 +14,7 @@
from conans.model.version import Version
from conans.tools import cpu_count, args_to_string
from conans.util.config_parser import get_bool_from_text
from conans.util.files import mkdir, get_abs_path, decode_text
from conans.util.files import mkdir, get_abs_path, decode_text, load


class CMake(object):
@@ -302,36 +302,28 @@ def build(self):
cmake.patch_config_paths()
"""

def _format_cmake_config_path(pathstr):
if platform.system() == "Windows":
drive,path = os.path.splitdrive(pathstr)
return drive.upper() + path.replace(os.path.sep,"/")
return pathstr

if not self._conanfile.should_install:
return
if not self._conanfile.name:
raise ConanException("cmake.patch_config_paths() can't work without package name. "
"Define name in your recipe")
pf = _format_cmake_config_path(self.definitions.get(cmake_install_prefix_var_name))
pf = self.definitions.get(cmake_install_prefix_var_name)
replstr = "${CONAN_%s_ROOT}" % self._conanfile.name.upper()
allwalk = chain(os.walk(self._conanfile.build_folder), os.walk(self._conanfile.package_folder))
for root, _, files in allwalk:
for f in files:
if f.endswith(".cmake"):
path = os.path.join(root, f)
tools.replace_in_file(path, pf, replstr, strict=False)
tools.replace_path_in_file(path, pf, replstr, strict=False)

# patch paths of dependent packages that are found in any cmake files of the
# current package
path_content = tools.load(path)
for dep in self._conanfile.deps_cpp_info.deps:
from_str = _format_cmake_config_path(self._conanfile.deps_cpp_info[dep].rootpath)
# try to replace only if from str is found
if path_content.find(from_str) != -1:
dep_str = "${CONAN_%s_ROOT}" % dep.upper()
self._conanfile.output.info("Patching paths for %s: %s to %s" % (dep, from_str, dep_str))
tools.replace_in_file(path, from_str, dep_str, strict=False)
from_str = self._conanfile.deps_cpp_info[dep].rootpath
dep_str = "${CONAN_%s_ROOT}" % dep.upper()
ret = tools.replace_path_in_file(path, from_str, dep_str, strict=False)
if ret:
self._conanfile.output.info("Patched paths for %s: %s to %s" % (dep, from_str, dep_str))

@staticmethod
def get_version():
@@ -217,20 +217,51 @@ def emit(self, record):
raise ConanException("Failed to apply patch: %s" % patch_file)


def _manage_text_not_found(search, file_path, strict, function_name):
message = "%s didn't find pattern '%s' in '%s' file." % (function_name, search, file_path)
if strict:
raise ConanException(message)
else:
_global_output.warn(message)
return False


def replace_in_file(file_path, search, replace, strict=True):
content = load(file_path)
if -1 == content.find(search):
message = "replace_in_file didn't find pattern '%s' in '%s' file." % (search, file_path)
if strict:
raise ConanException(message)
else:
_global_output.warn(message)
_manage_text_not_found(search, file_path, strict, "replace_in_file")
content = content.replace(search, replace)
content = content.encode("utf-8")
with open(file_path, "wb") as handle:
handle.write(content)


def replace_path_in_file(file_path, search, replace, strict=True, windows_paths=None):
if windows_paths is False or (windows_paths is None and platform.system() != "Windows"):
return replace_in_file(file_path, search, replace, strict=strict)

def normalized_text(text):
return text.replace("\\", "/").lower()

content = load(file_path)
normalized_content = normalized_text(content)
normalized_search = normalized_text(search)
index = normalized_content.find(normalized_search)
if index == -1:
return _manage_text_not_found(search, file_path, strict, "replace_path_in_file")

while index != -1:
content = content[:index] + replace + content[index + len(search):]
normalized_content = normalized_text(content)
index = normalized_content.find(normalized_search)

content = content.encode("utf-8")
with open(file_path, "wb") as handle:
handle.write(content)

return True


def replace_prefix_in_pc_file(pc_file, new_prefix):
content = load(pc_file)
lines = []
@@ -12,7 +12,7 @@
from conans.client.tools.oss import detected_architecture, os_info
from conans.errors import ConanException
from conans.util.env_reader import get_env
from conans.util.files import decode_text, save, mkdir_tmp
from conans.util.files import decode_text, save, mkdir_tmp, load

This comment has been minimized.

Copy link
@lasote

lasote Sep 28, 2018

Contributor

Sorry, I forgot to remove this unused import

This comment has been minimized.

Copy link
@lasote

lasote Sep 28, 2018

Contributor

Some tests failing, I'll reopen the pull request fixing everything.

from conans.unicode import get_cwd

_global_output = None
@@ -22,11 +22,13 @@
from conans.model.options import Options, PackageOptions
from conans.errors import ConanException

def _format_cmake_config_path(pathstr):
if platform.system() == "Windows":
drive,path = os.path.splitdrive(pathstr)
return drive.upper() + path.replace(os.path.sep,"/")
return pathstr

def _format_path_as_cmake(pathstr):
if platform.system() == "Windows":
drive,path = os.path.splitdrive(pathstr)
return drive.upper() + path.replace(os.path.sep,"/")
return pathstr


class CMakeTest(unittest.TestCase):

@@ -48,7 +50,7 @@ def config_patch_test(self):
conan_file.package_folder = os.path.join(self.tempdir, "pkg")
conan_file.deps_cpp_info = DepsCppInfo()

msg = "FOLDER: " + _format_cmake_config_path(conan_file.package_folder)
msg = "FOLDER: " + _format_path_as_cmake(conan_file.package_folder)
for folder in (conan_file.build_folder, conan_file.package_folder):
save(os.path.join(folder, "file1.cmake"), "Nothing")
save(os.path.join(folder, "file2"), msg)
@@ -85,7 +87,7 @@ def config_patch_deps_test(self):
self.assertEqual(conan_file.deps_cpp_info['MyPkg1'].rootpath,
self.tempdir2)

msg = "FOLDER: " + _format_cmake_config_path(self.tempdir2)
msg = "FOLDER: " + _format_path_as_cmake(self.tempdir2)
for folder in (conan_file.build_folder, conan_file.package_folder):
save(os.path.join(folder, "file1.cmake"), "Nothing")
save(os.path.join(folder, "file2"), msg)
@@ -1,6 +1,7 @@
import unittest
from conans.test.utils.tools import TestClient


class CMakeInstallPackageTest(unittest.TestCase):

def patch_config_test(self):
@@ -10,17 +11,17 @@ def patch_config_test(self):
import os
import platform
def _format_cmake_config_path(pathstr):
def _mess_with_path(pathstr):
if platform.system() == "Windows":
drive,path = os.path.splitdrive(pathstr)
drive, path = os.path.splitdrive(pathstr)
return drive.upper() + path.replace(os.path.sep,"/")
return pathstr
class AConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
def build(self):
cmake = CMake(self)
pth = _format_cmake_config_path(self.package_folder)
pth = _mess_with_path(self.package_folder)
self.output.info("output path: %s" % pth)
save("file1.cmake", "FOLDER " + pth)
save("sub/file1.cmake", "FOLDER " + pth)
@@ -458,6 +458,42 @@ def test_replace_in_file(self):

class ToolsTest(unittest.TestCase):

def replace_paths_test(self):
folder = temp_folder()
path = os.path.join(folder, "file")
replace_with = "MYPATH"
expected = 'Some other contentsMYPATH"finally all text'

save(path, 'Some other contentsc:\\Path\\TO\\file.txt"finally all text')
ret = tools.replace_path_in_file(path, "C:/Path/to/file.txt", replace_with, windows_paths=True)
self.assertEquals(load(path), expected)
self.assertTrue(ret)

save(path, 'Some other contentsC:/Path\\TO\\file.txt"finally all text')
ret = tools.replace_path_in_file(path, "C:/PATH/to/FILE.txt", replace_with, windows_paths=True)
self.assertEquals(load(path), expected)
self.assertTrue(ret)

save(path, 'Some other contentsD:/Path\\TO\\file.txt"finally all text')
ret = tools.replace_path_in_file(path, "C:/PATH/to/FILE.txt", replace_with, strict=False, windows_paths=True)
self.assertEquals(load(path), 'Some other contentsD:/Path\\TO\\file.txt"finally all text')
self.assertFalse(ret)

# Multiple matches
save(path, 'Some other contentsD:/Path\\TO\\file.txt"finally all textd:\\PATH\\to\\file.TXTMoretext')
ret = tools.replace_path_in_file(path, "D:/PATH/to/FILE.txt", replace_with, strict=False, windows_paths=True)
self.assertEquals(load(path), 'Some other contentsMYPATH"finally all textMYPATHMoretext')
self.assertTrue(ret)

# Automatic windows_paths
save(path, 'Some other contentsD:/Path\\TO\\file.txt"finally all textd:\\PATH\\to\\file.TXTMoretext')
ret = tools.replace_path_in_file(path, "D:/PATH/to/FILE.txt", replace_with, strict=False)
if platform.system() == "Windows":
self.assertEquals(load(path), 'Some other contentsMYPATH"finally all textMYPATHMoretext')
self.assertTrue(ret)
else:
self.assertFalse(ret)

def load_save_test(self):
folder = temp_folder()
path = os.path.join(folder, "file")
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.