Exemplo n.º 1
0
Arquivo: info.py Projeto: yiakwy/conan
 def _get_key(self, item):
     for reference in self._data:
         if reference.ref.name == item:
             return reference
     raise ConanException("No requirement matching for %s" % (item))
Exemplo n.º 2
0
    def __init__(self,
                 conanfile,
                 generator=None,
                 cmake_system_name=True,
                 parallel=True,
                 build_type=None,
                 toolset=None,
                 make_program=None,
                 set_cmake_flags=False,
                 msbuild_verbosity="minimal",
                 cmake_program=None,
                 generator_platform=None,
                 append_vcvars=False):
        """
        :param conanfile: Conanfile instance
        :param generator: Generator name to use or none to autodetect
        :param cmake_system_name: False to not use CMAKE_SYSTEM_NAME variable,
               True for auto-detect or directly a string with the system name
        :param parallel: Try to build with multiple cores if available
        :param build_type: Overrides default build type coming from settings
        :param toolset: Toolset name to use (such as llvm-vs2014) or none for default one,
                applies only to certain generators (e.g. Visual Studio)
        :param set_cmake_flags: whether or not to set CMake flags like CMAKE_CXX_FLAGS,
                CMAKE_C_FLAGS, etc. it's vital to set for certain projects
                (e.g. using CMAKE_SIZEOF_VOID_P or CMAKE_LIBRARY_ARCHITECTURE)
        :param msbuild_verbosity: verbosity level for MSBuild (in case of Visual Studio generator)
        :param cmake_program: Path to the custom cmake executable
        :param generator_platform: Generator platform name or none to autodetect (-A cmake option)
        """
        if not isinstance(conanfile, ConanFile):
            raise ConanException(
                "First argument of CMake() has to be ConanFile. Use CMake(self)"
            )

        self._append_vcvars = append_vcvars
        self._conanfile = conanfile
        self._settings = conanfile.settings
        self._build_type = build_type or conanfile.settings.get_safe(
            "build_type")
        self._cmake_program = os.getenv(
            "CONAN_CMAKE_PROGRAM") or cmake_program or "cmake"

        self.generator_platform = generator_platform
        self.generator = generator or get_generator(conanfile.settings)

        if not self.generator:
            self._conanfile.output.warn(
                "CMake generator could not be deduced from settings")
        self.parallel = parallel
        # Initialize definitions (won't be updated if conanfile or any of these variables change)
        builder = CMakeDefinitionsBuilder(self._conanfile,
                                          cmake_system_name=cmake_system_name,
                                          make_program=make_program,
                                          parallel=parallel,
                                          generator=self.generator,
                                          set_cmake_flags=set_cmake_flags,
                                          forced_build_type=build_type,
                                          output=self._conanfile.output)
        # FIXME CONAN 2.0: CMake() interface should be always the constructor and self.definitions.
        # FIXME CONAN 2.0: Avoid properties and attributes to make the user interface more clear

        self.definitions = builder.get_definitions()
        self.definitions["CONAN_EXPORTED"] = "1"

        self.toolset = toolset or get_toolset(self._settings)
        self.build_dir = None
        self.msbuild_verbosity = os.getenv(
            "CONAN_MSBUILD_VERBOSITY") or msbuild_verbosity
Exemplo n.º 3
0
 def add_repository(self, repository, repo_key=None):
     raise ConanException("PkgUtilTool::add_repository not implemented")
Exemplo n.º 4
0
    def install_packages(self,
                         packages,
                         update=True,
                         force=False,
                         arch_names=None):
        """ Get the system package tool install command and install all packages and/or variants.
            Inputs:
            "pkg-variant1"  # (1) Install only one package
            ["pkg-variant1", "otherpkg", "thirdpkg"] # (2) All must be installed
            [("pkg-variant1", "pkg-variant2"), "otherpkg", "thirdpkg"] # (3) Install only one variant
                                                                             and all other packages
            "pkg1 pkg2", "pkg3 pkg4" # (4) Invalid
            ["pkg1 pkg2", "pkg3 pkg4"] # (5) Invalid

        :param packages: Supports multiple formats (string,list,tuple). Lists and tuples into a list
        are considered variants and is processed just like self.install(). A list of string is
        considered a list of packages to be installed (only not installed yet).
        :param update: Run update command before to install
        :param force: Force installing all packages, including all installed.
        :param arch_names: Package suffix/prefix name used by installer tool e.g. {"x86_64": "amd64"}
        :return: None
        """
        packages = [packages] if isinstance(
            packages, six.string_types) else list(packages)
        # only one (first) variant will be installed
        list_variants = list(
            filter(lambda x: isinstance(x, (tuple, list)), packages))
        # all packages will be installed
        packages = list(
            filter(lambda x: not isinstance(x, (tuple, list)), packages))

        if [pkg for pkg in packages if " " in pkg]:
            raise ConanException(
                "Each string must contain only one package to be installed. "
                "Use a list instead e.g. ['foo', 'bar'].")

        for variant in list_variants:
            self.install(variant,
                         update=update,
                         force=force,
                         arch_names=arch_names)

        packages = self._get_package_names(packages, arch_names)

        mode = self._get_sysrequire_mode()

        if mode in ("verify", "disabled"):
            # Report to output packages need to be installed
            if mode == "disabled":
                self._output.info(
                    "The following packages need to be installed:\n %s" %
                    "\n".join(packages))
                return

            if mode == "verify" and not self._installed(packages):
                self._output.error(
                    "The following packages need to be installed:\n %s" %
                    "\n".join(packages))
                raise ConanException(
                    "Aborted due to CONAN_SYSREQUIRES_MODE=%s. "
                    "Some system packages need to be installed" % mode)

        packages = packages if force else self._to_be_installed(packages)
        if not force and not packages:
            return

        # From here system packages can be updated/modified
        if update and not self._is_up_to_date:
            self.update()
        self._install_all(packages)
Exemplo n.º 5
0
def unzip(filename, destination=".", keep_permissions=False, pattern=None, output=None):
    """
    Unzip a zipped file
    :param filename: Path to the zip file
    :param destination: Destination folder (or file for .gz files)
    :param keep_permissions: Keep the zip permissions. WARNING: Can be
    dangerous if the zip was not created in a NIX system, the bits could
    produce undefined permission schema. Use this option only if you are sure
    that the zip was created correctly.
    :param pattern: Extract only paths matching the pattern. This should be a
    Unix shell-style wildcard, see fnmatch documentation for more details.
    :param output: output
    :return:
    """
    output = default_output(output, 'conans.client.tools.files.unzip')

    if (filename.endswith(".tar.gz") or filename.endswith(".tgz") or
            filename.endswith(".tbz2") or filename.endswith(".tar.bz2") or
            filename.endswith(".tar")):
        return untargz(filename, destination, pattern)
    if filename.endswith(".gz"):
        import gzip
        with gzip.open(filename, 'rb') as f:
            file_content = f.read()
        target_name = filename[:-3] if destination == "." else destination
        save(target_name, file_content)
        return
    if filename.endswith(".tar.xz") or filename.endswith(".txz"):
        if six.PY2:
            raise ConanException("XZ format not supported in Python 2. Use Python 3 instead")
        return untargz(filename, destination, pattern)

    import zipfile
    full_path = os.path.normpath(os.path.join(get_cwd(), destination))

    if hasattr(sys.stdout, "isatty") and sys.stdout.isatty():
        def print_progress(the_size, uncomp_size):
            the_size = (the_size * 100.0 / uncomp_size) if uncomp_size != 0 else 0
            txt_msg = "Unzipping %d %%"
            if the_size > print_progress.last_size + 1:
                output.rewrite_line(txt_msg % the_size)
                print_progress.last_size = the_size
                if int(the_size) == 99:
                    output.rewrite_line(txt_msg % 100)
    else:
        def print_progress(_, __):
            pass

    with zipfile.ZipFile(filename, "r") as z:
        if not pattern:
            zip_info = z.infolist()
        else:
            zip_info = [zi for zi in z.infolist() if fnmatch(zi.filename, pattern)]
        uncompress_size = sum((file_.file_size for file_ in zip_info))
        if uncompress_size > 100000:
            output.info("Unzipping %s, this can take a while" % human_size(uncompress_size))
        else:
            output.info("Unzipping %s" % human_size(uncompress_size))
        extracted_size = 0

        print_progress.last_size = -1
        if platform.system() == "Windows":
            for file_ in zip_info:
                extracted_size += file_.file_size
                print_progress(extracted_size, uncompress_size)
                try:
                    z.extract(file_, full_path)
                except Exception as e:
                    output.error("Error extract %s\n%s" % (file_.filename, str(e)))
        else:  # duplicated for, to avoid a platform check for each zipped file
            for file_ in zip_info:
                extracted_size += file_.file_size
                print_progress(extracted_size, uncompress_size)
                try:
                    z.extract(file_, full_path)
                    if keep_permissions:
                        # Could be dangerous if the ZIP has been created in a non nix system
                        # https://bugs.python.org/issue15795
                        perm = file_.external_attr >> 16 & 0xFFF
                        os.chmod(os.path.join(full_path, file_.filename), perm)
                except Exception as e:
                    output.error("Error extract %s\n%s" % (file_.filename, str(e)))
        output.writeln("")
Exemplo n.º 6
0
 def __getitem__(self, value):
     value = str(value)
     try:
         return self._definition[value]
     except:
         raise ConanException(bad_value_msg(self._name, value, self.values_range))
Exemplo n.º 7
0
 def value(self, v):
     v = str(v)
     if self._definition != "ANY" and v not in self._definition:
         raise ConanException(bad_value_msg(self._name, v, self.values_range))
     self._value = v
Exemplo n.º 8
0
 def configure(self):
     del self.settings.compiler.libcxx
     if self.settings.compiler == "Visual Studio" and int(
             str(self.settings.compiler.version)) < 14:
         raise ConanException("Visual Studio >= 14 (2015) is required")
Exemplo n.º 9
0
 def exists_function(remotes):
     if remote_name in remotes:
         raise ConanException(
             "Remote '%s' already exists in remotes (use update to modify)"
             % remote_name)
Exemplo n.º 10
0
 def loads(text):
     try:
         return Settings(yaml.safe_load(text) or {})
     except (yaml.YAMLError, AttributeError) as ye:
         raise ConanException("Invalid settings.yml format: {}".format(ye))
Exemplo n.º 11
0
def _replace_scm_data_in_conanfile(conanfile_path, scm_data):
    # Parsing and replacing the SCM field
    content = load(conanfile_path)
    headers = []

    if six.PY2:
        # Workaround for https://bugs.python.org/issue22221
        lines_without_headers = []
        lines = content.splitlines(True)
        for line in lines:
            if not lines_without_headers and line.startswith("#"):
                headers.append(line)
            else:
                lines_without_headers.append(line)
        content = ''.join(lines_without_headers)

    lines = content.splitlines(True)
    tree = ast.parse(content)
    to_replace = []
    comments = []
    class_line = None
    tab_size = 4
    for i_body, item in enumerate(tree.body):
        if isinstance(item, ast.ClassDef):
            statements = item.body
            class_line = item.lineno
            for i, stmt in enumerate(item.body):
                if isinstance(stmt, ast.Assign) and len(stmt.targets) == 1:
                    line = lines[stmt.lineno - 1]
                    tab_size = len(line) - len(line.lstrip())
                    if isinstance(stmt.targets[0],
                                  ast.Name) and stmt.targets[0].id == "scm":
                        try:
                            if i + 1 == len(statements
                                            ):  # Last statement in my ClassDef
                                if i_body + 1 == len(
                                        tree.body):  # Last statement over all
                                    next_line = len(lines)
                                else:
                                    next_line = tree.body[i_body +
                                                          1].lineno - 1
                            else:
                                next_line = statements[i + 1].lineno - 1
                                next_line_content = lines[next_line].strip()
                                if (next_line_content.endswith('"""')
                                        or next_line_content.endswith("'''")):
                                    next_line += 1
                        except IndexError:
                            next_line = stmt.lineno
                        replace = [
                            line for line in lines[(stmt.lineno - 1):next_line]
                        ]
                        to_replace.append("".join(replace).lstrip())
                        comments = [
                            line.strip('\n') for line in replace if
                            line.strip().startswith("#") or not line.strip()
                        ]
                        break

    if len(to_replace) > 1:
        raise ConanException(
            "The conanfile.py defines more than one class level 'scm' attribute"
        )

    new_text = "scm = " + ",\n          ".join(str(scm_data).split(",")) + "\n"

    if len(to_replace) == 0:
        # SCM exists, but not found in the conanfile, probably inherited from superclass
        # FIXME: This will inject the lines only the latest class declared in the conanfile
        tmp = lines[0:class_line]
        tmp.append("{}{}".format(" " * tab_size, new_text))
        tmp.extend(lines[class_line:])
        content = ''.join(tmp)
    else:
        if comments:
            new_text += '\n'.join(comments) + "\n"
        content = content.replace(to_replace[0], new_text)
        content = content if not headers else ''.join(headers) + content

    remove(conanfile_path)
    save(conanfile_path, content)
Exemplo n.º 12
0
 def value(self, v):
     v = str(v)
     if self._not_any() and v not in self.values_range:
         raise ConanException(
             bad_value_msg(self._name, v, self.values_range))
     self._value = v
 def configure(self):
     v = Version(str(self.settings.compiler.version))
     if self.settings.compiler == "gcc" and v < "7.0":
         raise ConanException("GCC >= 7.0 is required")
     if self.settings.compiler == "clang" and v < "5.0":
         raise ConanException("clang >= 5.0 is required")
Exemplo n.º 14
0
def call_system_requirements(conanfile, output):
    try:
        return conanfile.system_requirements()
    except Exception as e:
        output.error("while executing system_requirements(): %s" % str(e))
        raise ConanException("Error in system requirements")
Exemplo n.º 15
0
 def __getitem__(self, item):
     raise ConanException(
         "self.%s not defined. If you need it for a "
         "local command run 'conan install'" % field_name)
Exemplo n.º 16
0
 def exists_function(remotes):
     if remote_name not in remotes:
         raise ConanException("Remote '%s' not found in remotes" %
                              remote_name)
Exemplo n.º 17
0
def patch(base_path=None, patch_file=None, patch_string=None, strip=0, output=None):
    """Applies a diff from file (patch_file)  or string (patch_string)
    in base_path directory or current dir if None"""

    class PatchLogHandler(logging.Handler):
        def __init__(self):
            logging.Handler.__init__(self, logging.DEBUG)
            self.output = output or ConanOutput(sys.stdout, True)
            self.patchname = patch_file if patch_file else "patch"

        def emit(self, record):
            logstr = self.format(record)
            if record.levelno == logging.WARN:
                self.output.warn("%s: %s" % (self.patchname, logstr))
            else:
                self.output.info("%s: %s" % (self.patchname, logstr))

    patchlog = logging.getLogger("patch")
    if patchlog:
        patchlog.handlers = []
        patchlog.addHandler(PatchLogHandler())

    if not patch_file and not patch_string:
        return
    if patch_file:
        patchset = fromfile(patch_file)
    else:
        patchset = fromstring(patch_string.encode())

    if not patchset:
        raise ConanException("Failed to parse patch: %s" % (patch_file if patch_file else "string"))

    def decode_clean(path, prefix):
        path = path.decode("utf-8").replace("\\", "/")
        if path.startswith(prefix):
            path = path[2:]
        return path

    def strip_path(path):
        tokens = path.split("/")[strip:]
        path = "/".join(tokens)
        if base_path:
            path = os.path.join(base_path, path)
        return path
    # account for new and deleted files, upstream dep won't fix them
    items = []
    for p in patchset:
        source = decode_clean(p.source, "a/")
        target = decode_clean(p.target, "b/")
        if "dev/null" in source:
            target = strip_path(target)
            hunks = [s.decode("utf-8") for s in p.hunks[0].text]
            new_file = "".join(hunk[1:] for hunk in hunks)
            save(target, new_file)
        elif "dev/null" in target:
            source = strip_path(source)
            os.unlink(source)
        else:
            items.append(p)
    patchset.items = items

    if not patchset.apply(root=base_path, strip=strip):
        raise ConanException("Failed to apply patch: %s" % patch_file)
Exemplo n.º 18
0
 def raise_get_version():
     raise ConanException('Error retrieving CMake version')
Exemplo n.º 19
0
def undefined_field(name, field, fields=None, value=None):
    value_str = " for '%s'" % value if value else ""
    result = ["'%s.%s' doesn't exist%s" % (name, field, value_str),
              "'%s' possible configurations are %s" % (name, fields or "none")]
    return ConanException("\n".join(result))
Exemplo n.º 20
0
 def compiler(self):
     raise ConanException("mock: not available")
Exemplo n.º 21
0
def undefined_value(name):
    return ConanException("'%s' value not defined" % name)
Exemplo n.º 22
0
def msbuild_verbosity_cmd_line_arg(conanfile):
    verbosity = conanfile.conf["tools.microsoft.msbuild:verbosity"]
    if verbosity:
        if verbosity not in ("Quiet", "Minimal", "Normal", "Detailed", "Diagnostic"):
            raise ConanException("Unknown msbuild verbosity: {}".format(verbosity))
        return '/verbosity:{}'.format(verbosity)
Exemplo n.º 23
0
 def get_conf(self, varname):
     """Gets the section from config file or raises an exception"""
     try:
         return self.items(varname)
     except NoSectionError:
         raise ConanException("Invalid configuration, missing %s" % varname)
Exemplo n.º 24
0
    def _config_node(self, conanfile, conanref, down_reqs, down_ref,
                     down_options):
        """ update settings and option in the current ConanFile, computing actual
        requirement values, cause they can be overriden by downstream requires
        param settings: dict of settings values => {"os": "windows"}
        """
        try:
            with environment_append(conanfile.env):
                if hasattr(conanfile, "config"):
                    if not conanref:
                        output = ScopedOutput(str("PROJECT"), self._output)
                        output.warn("config() has been deprecated."
                                    " Use config_options and configure")
                    with conanfile_exception_formatter(str(conanfile),
                                                       "config"):
                        conanfile.config()
                with conanfile_exception_formatter(str(conanfile),
                                                   "config_options"):
                    conanfile.config_options()
                conanfile.options.propagate_upstream(down_options, down_ref,
                                                     conanref, self._output)
                if hasattr(conanfile, "config"):
                    with conanfile_exception_formatter(str(conanfile),
                                                       "config"):
                        conanfile.config()

                with conanfile_exception_formatter(str(conanfile),
                                                   "configure"):
                    conanfile.configure()

                conanfile.settings.validate()  # All has to be ok!
                conanfile.options.validate()

                # Update requirements (overwrites), computing new upstream
                if hasattr(conanfile, "requirements"):
                    # If re-evaluating the recipe, in a diamond graph, with different options,
                    # it could happen that one execution path of requirements() defines a package
                    # and another one a different package raising Duplicate dependency error
                    # Or the two consecutive calls, adding 2 different dependencies for the two paths
                    # So it is necessary to save the "requires" state and restore it before a second
                    # execution of requirements(). It is a shallow copy, if first iteration is
                    # RequireResolve'd or overridden, the inner requirements are modified
                    if not hasattr(conanfile, "_original_requires"):
                        conanfile._original_requires = conanfile.requires.copy(
                        )
                    else:
                        conanfile.requires = conanfile._original_requires.copy(
                        )

                    with conanfile_exception_formatter(str(conanfile),
                                                       "requirements"):
                        conanfile.requirements()

                new_options = conanfile.options.deps_package_values
                new_down_reqs = conanfile.requires.update(
                    down_reqs, self._output, conanref, down_ref)
        except ConanExceptionInUserConanfileMethod:
            raise
        except ConanException as e:
            raise ConanException("%s: %s" % (conanref or "Conanfile", str(e)))
        except Exception as e:
            raise ConanException(e)

        return new_down_reqs, new_options
Exemplo n.º 25
0
def create_package(conanfile,
                   package_id,
                   source_folder,
                   build_folder,
                   package_folder,
                   install_folder,
                   hook_manager,
                   conanfile_path,
                   ref,
                   local=False,
                   copy_info=False):
    """ copies built artifacts, libs, headers, data, etc. from build_folder to
    package folder
    """
    mkdir(package_folder)

    output = conanfile.output
    # Make the copy of all the patterns
    output.info("Generating the package")
    output.info("Package folder %s" % package_folder)

    try:
        conanfile.package_folder = package_folder
        conanfile.source_folder = source_folder
        conanfile.install_folder = install_folder
        conanfile.build_folder = build_folder

        hook_manager.execute("pre_package",
                             conanfile=conanfile,
                             conanfile_path=conanfile_path,
                             reference=ref,
                             package_id=package_id)

        package_output = ScopedOutput("%s package()" % output.scope, output)
        output.highlight("Calling package()")

        def recipe_has(attribute):
            return attribute in conanfile.__class__.__dict__

        if source_folder != build_folder:
            conanfile.copy = FileCopier(source_folder, package_folder,
                                        build_folder)
            with conanfile_exception_formatter(str(conanfile), "package"):
                with tools.chdir(source_folder):
                    conanfile.package()
            copy_done = conanfile.copy.report(package_output)
            if not copy_done and recipe_has("package"):
                output.warn("No files copied from source folder!")

        conanfile.copy = FileCopier(build_folder, package_folder)
        with tools.chdir(build_folder):
            with conanfile_exception_formatter(str(conanfile), "package"):
                conanfile.package()
        copy_done = conanfile.copy.report(package_output)
        if not copy_done and recipe_has("build") and recipe_has("package"):
            output.warn("No files copied from build folder!")
    except Exception as e:
        if not local:
            os.chdir(build_folder)
            try:
                rmdir(package_folder)
            except Exception as e_rm:
                output.error("Unable to remove package folder %s\n%s" %
                             (package_folder, str(e_rm)))
                output.warn("**** Please delete it manually ****")

        if isinstance(e, ConanExceptionInUserConanfileMethod):
            raise
        raise ConanException(e)

    _create_aux_files(install_folder, package_folder, conanfile, copy_info)
    package_id = package_id or os.path.basename(package_folder)
    output.success("Package '%s' created" % package_id)
    hook_manager.execute("post_package",
                         conanfile=conanfile,
                         conanfile_path=conanfile_path,
                         reference=ref,
                         package_id=package_id)
Exemplo n.º 26
0
    def write_generators(self, conanfile, old_gen_folder, new_gen_folder,
                         output):
        """ produces auxiliary files, required to build a project or a package.
        """
        _receive_conf(conanfile)

        for generator_name in set(conanfile.generators):
            generator_class = self._new_generator(generator_name, output)
            if generator_class:
                if generator_name == "msbuild":
                    msg = (
                        "\n*****************************************************************\n"
                        "******************************************************************\n"
                        "'msbuild' has been deprecated and moved.\n"
                        "It will be removed in next Conan release.\n"
                        "Use 'MSBuildDeps' method instead.\n"
                        "********************************************************************\n"
                        "********************************************************************\n"
                    )
                    from conans.client.output import Color
                    output.writeln(msg, front=Color.BRIGHT_RED)
                try:
                    generator = generator_class(conanfile)
                    output.highlight(
                        "Generator '{}' calling 'generate()'".format(
                            generator_name))
                    mkdir(new_gen_folder)
                    with chdir(new_gen_folder):
                        generator.generate()
                    continue
                except Exception as e:
                    raise ConanException("Error in generator '{}': {}".format(
                        generator_name, str(e)))

            try:
                generator_class = self._generators[generator_name]
            except KeyError:
                available = list(
                    self._generators.keys()) + self._new_generators
                raise ConanException(
                    "Invalid generator '%s'. Available types: %s" %
                    (generator_name, ", ".join(available)))
            try:
                generator = generator_class(conanfile)
            except TypeError:
                # To allow old-style generator packages to work (e.g. premake)
                output.warn(
                    "Generator %s failed with new __init__(), trying old one")
                generator = generator_class(conanfile.deps_cpp_info,
                                            conanfile.cpp_info)

            try:
                generator.output_path = old_gen_folder
                content = generator.content
                if isinstance(content, dict):
                    if generator.filename:
                        output.warn(
                            "Generator %s is multifile. Property 'filename' not used"
                            % (generator_name, ))
                    for k, v in content.items():
                        if generator.normalize:  # To not break existing behavior, to be removed 2.0
                            v = normalize(v)
                        output.info("Generator %s created %s" %
                                    (generator_name, k))
                        save(join(old_gen_folder, k), v, only_if_modified=True)
                else:
                    content = normalize(content)
                    output.info("Generator %s created %s" %
                                (generator_name, generator.filename))
                    save(join(old_gen_folder, generator.filename),
                         content,
                         only_if_modified=True)
            except Exception as e:
                if get_env("CONAN_VERBOSE_TRACEBACK", False):
                    output.error(traceback.format_exc())
                output.error("Generator %s(file:%s) failed\n%s" %
                             (generator_name, generator.filename, str(e)))
                raise ConanException(e)
Exemplo n.º 27
0
    def patch_config_paths(self):
        """
        changes references to the absolute path of the installed package and its dependencies in
        exported cmake config files to the appropriate conan variable. This makes
        most (sensible) cmake config files portable.

        For example, if a package foo installs a file called "fooConfig.cmake" to
        be used by cmake's find_package method, normally this file will contain
        absolute paths to the installed package folder, for example it will contain
        a line such as:

            SET(Foo_INSTALL_DIR /home/developer/.conan/data/Foo/1.0.0/...)

        This will cause cmake find_package() method to fail when someone else
        installs the package via conan.

        This function will replace such mentions to

            SET(Foo_INSTALL_DIR ${CONAN_FOO_ROOT})

        which is a variable that is set by conanbuildinfo.cmake, so that find_package()
        now correctly works on this conan package.

        For dependent packages, if a package foo installs a file called "fooConfig.cmake" to
        be used by cmake's find_package method and if it depends to a package bar,
        normally this file will contain absolute paths to the bar package folder,
        for example it will contain a line such as:

            SET_TARGET_PROPERTIES(foo PROPERTIES
                  INTERFACE_INCLUDE_DIRECTORIES
                  "/home/developer/.conan/data/Bar/1.0.0/user/channel/id/include")

        This function will replace such mentions to

            SET_TARGET_PROPERTIES(foo PROPERTIES
                  INTERFACE_INCLUDE_DIRECTORIES
                  "${CONAN_BAR_ROOT}/include")

        If the install() method of the CMake object in the conan file is used, this
        function should be called _after_ that invocation. For example:

            def build(self):
                cmake = CMake(self)
                cmake.configure()
                cmake.build()
                cmake.install()
                cmake.patch_config_paths()
        """

        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 = self.definitions.get(cmake_install_prefix_var_name)
        replstr = "${CONAN_%s_ROOT}" % self._conanfile.name.upper()
        allwalk = chain(walk(self._conanfile.build_folder),
                        walk(self._conanfile.package_folder))

        # We don't want warnings printed because there is no replacement of the abs path.
        # there could be MANY cmake files in the package and the normal thing is to not find
        # the abs paths
        _null_out = ConanOutput(StringIO())
        for root, _, files in allwalk:
            for f in files:
                if f.endswith(".cmake") and not f.startswith("conan"):
                    path = os.path.join(root, f)

                    tools.replace_path_in_file(path,
                                               pf,
                                               replstr,
                                               strict=False,
                                               output=_null_out)

                    # patch paths of dependent packages that are found in any cmake files of the
                    # current package
                    for dep in self._conanfile.deps_cpp_info.deps:
                        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,
                                                         output=_null_out)
                        if ret:
                            self._conanfile.output.info(
                                "Patched paths for %s: %s to %s" %
                                (dep, from_str, dep_str))
Exemplo n.º 28
0
 def _match_manifests(self, read_manifest, expected_manifest, reference):
     if read_manifest is None or read_manifest != expected_manifest:
         raise ConanException("%s local cache package is corrupted: "
                              "some file hash doesn't match manifest" %
                              (str(reference)))
Exemplo n.º 29
0
 def add_repository(self, repository, repo_key=None):
     raise ConanException("ChocolateyTool::add_repository not implemented")
Exemplo n.º 30
0
def _invalid_python_requires(require):
    raise ConanException("Invalid use of python_requires(%s)" % require)