Example #1
0
def run_configure_method(conanfile, down_options, down_ref, ref):
    """ Run all the config-related functions for the given conanfile object """

    # Avoid extra time manipulating the sys.path for python
    with get_env_context_manager(conanfile, without_python=True):
        if hasattr(conanfile, "config"):
            conan_v2_behavior("config() has been deprecated. "
                              "Use config_options() and configure()",
                              v1_behavior=conanfile.output.warn)
            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, ref)

        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()

        _validate_fpic(conanfile)
Example #2
0
def write_toolchain(conanfile, path, output):
    if hasattr(conanfile, "toolchain"):
        msg = ("\n*****************************************************************\n"
               "******************************************************************\n"
               "The 'toolchain' attribute or method has been deprecated.\n"
               "It will be removed in next Conan release.\n"
               "Use 'generators = \"ClassName\"' or 'generate()' method instead.\n"
               "********************************************************************\n"
               "********************************************************************\n")
        output.warn(msg)
        warnings.warn(msg)
        output.highlight("Generating toolchain files")
        if callable(conanfile.toolchain):
            # This is the toolchain
            with chdir(path):
                with conanfile_exception_formatter(str(conanfile), "toolchain"):
                    conanfile.toolchain()
        else:
            try:
                toolchain = {"cmake": CMakeToolchain}[conanfile.toolchain]
            except KeyError:
                raise ConanException("Unknown toolchain '%s'" % conanfile.toolchain)
            tc = toolchain(conanfile)
            with chdir(path):
                tc.generate()

        # TODO: Lets discuss what to do with the environment

    if hasattr(conanfile, "generate"):
        output.highlight("Calling generate()")
        with chdir(path):
            with conanfile_exception_formatter(str(conanfile), "generate"):
                conanfile.generate()
Example #3
0
    def load_consumer_conanfile(self,
                                conanfile_path,
                                info_folder,
                                deps_info_required=False,
                                test=False):
        """loads a conanfile for local flow: source, imports, package, build
        """
        try:
            graph_info = GraphInfo.load(info_folder)
            graph_lock_file = GraphLockFile.load(
                info_folder, self._cache.config.revisions_enabled)
            graph_lock = graph_lock_file.graph_lock
            self._output.info(
                "Using lockfile: '{}/conan.lock'".format(info_folder))
            profile_host = graph_lock_file.profile_host
            self._output.info("Using cached profile from lockfile")
        except IOError:  # Only if file is missing
            graph_lock = None
            # This is very dirty, should be removed for Conan 2.0 (source() method only)
            profile_host = self._cache.default_profile
            profile_host.process_settings(self._cache)
            name, version, user, channel = None, None, None, None
        else:
            name, version, user, channel, _ = graph_info.root
            profile_host.process_settings(self._cache, preprocess=False)
            # This is the hack of recovering the options from the graph_info
            profile_host.options.update(graph_info.options)
        if conanfile_path.endswith(".py"):
            lock_python_requires = None
            if graph_lock and not test:  # Only lock python requires if it is not test_package
                node_id = graph_lock.get_node(graph_info.root)
                lock_python_requires = graph_lock.python_requires(node_id)
            conanfile = self._loader.load_consumer(
                conanfile_path,
                profile_host=profile_host,
                name=name,
                version=version,
                user=user,
                channel=channel,
                lock_python_requires=lock_python_requires)
            if test:
                conanfile.display_name = "%s (test package)" % str(test)
                conanfile.output.scope = conanfile.display_name
            with get_env_context_manager(conanfile, without_python=True):
                with conanfile_exception_formatter(str(conanfile),
                                                   "config_options"):
                    conanfile.config_options()
                with conanfile_exception_formatter(str(conanfile),
                                                   "configure"):
                    conanfile.configure()

                conanfile.settings.validate()  # All has to be ok!
                conanfile.options.validate()
        else:
            conanfile = self._loader.load_conanfile_txt(
                conanfile_path, profile_host)

        load_deps_info(info_folder, conanfile, required=deps_info_required)

        return conanfile
Example #4
0
    def load_named(self, conanfile_path, name, version, user, channel, lock_python_requires=None):
        """ loads the basic conanfile object and evaluates its name and version
        """
        conanfile, _ = self.load_basic_module(conanfile_path, lock_python_requires, user, channel)
        conanfile.recipe_folder = os.path.dirname(conanfile_path)

        if hasattr(conanfile, "set_name"):
            if conanfile.name:
                raise ConanException("Conanfile defined package 'name', set_name() redundant")
            with conanfile_exception_formatter("conanfile.py", "set_name"):
                conanfile.set_name()
        if hasattr(conanfile, "set_version"):
            if conanfile.version:
                raise ConanException("Conanfile defined package 'version', set_version() redundant")
            with conanfile_exception_formatter("conanfile.py", "set_version"):
                conanfile.set_version()
        # Make sure this is nowhere else available
        del conanfile.recipe_folder

        # Export does a check on existing name & version
        if name:
            if conanfile.name and name != conanfile.name:
                raise ConanException("Package recipe with name %s!=%s" % (name, conanfile.name))
            conanfile.name = name

        if version:
            if conanfile.version and version != conanfile.version:
                raise ConanException("Package recipe with version %s!=%s"
                                     % (version, conanfile.version))
            conanfile.version = version
        return conanfile
Example #5
0
def create_package(conanfile,
                   source_folder,
                   build_folder,
                   package_folder,
                   install_folder,
                   output,
                   local=False,
                   copy_info=False):
    """ copies built artifacts, libs, headers, data, etc from build_folder to
    package folder
    """
    mkdir(package_folder)

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

    try:
        package_output = ScopedOutput("%s package()" % output.scope, output)
        output.highlight("Calling package()")
        conanfile.package_folder = package_folder
        conanfile.source_folder = source_folder
        conanfile.install_folder = install_folder
        conanfile.build_folder = build_folder

        def recipe_has(conanfile, 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()
            warn = recipe_has(conanfile, "package")
            conanfile.copy.report(package_output, warn=warn)

        conanfile.copy = FileCopier(build_folder, package_folder)
        with tools.chdir(build_folder):
            with conanfile_exception_formatter(str(conanfile), "package"):
                conanfile.package()
        warn = recipe_has(conanfile, "build") and recipe_has(
            conanfile, "package")
        conanfile.copy.report(package_output, warn=warn)
    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)
    output.success("Package '%s' created" % os.path.basename(package_folder))
Example #6
0
def run_configure_method(conanfile, down_options, down_ref, ref):
    """ Run all the config-related functions for the given conanfile object """

    # Avoid extra time manipulating the sys.path for python
    with get_env_context_manager(conanfile, without_python=True):
        if hasattr(conanfile, "config"):
            conan_v2_error("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, ref)

        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()
        # Recipe provides its own name if nothing else is defined
        conanfile.provides = make_tuple(conanfile.provides or conanfile.name)

        if conanfile.deprecated:
            from six import string_types
            message = "Recipe '%s' is deprecated" % conanfile.display_name
            if isinstance(conanfile.deprecated, string_types):
                message += " in favor of '%s'" % conanfile.deprecated
            message += ". Please, consider changing your requirements."
            conanfile.output.warn(message)
Example #7
0
    def load_named(self, conanfile_path, name, version, user, channel, lock_python_requires=None):
        """ loads the basic conanfile object and evaluates its name and version
        """
        conanfile, _ = self.load_basic_module(conanfile_path, lock_python_requires, user, channel)

        # Export does a check on existing name & version
        if name:
            if conanfile.name and name != conanfile.name:
                raise ConanException("Package recipe with name %s!=%s" % (name, conanfile.name))
            conanfile.name = name

        if version:
            if conanfile.version and version != conanfile.version:
                raise ConanException("Package recipe with version %s!=%s"
                                     % (version, conanfile.version))
            conanfile.version = version

        if hasattr(conanfile, "set_name"):
            with conanfile_exception_formatter("conanfile.py", "set_name"):
                conanfile.set_name()
            if name and name != conanfile.name:
                raise ConanException("Package recipe with name %s!=%s" % (name, conanfile.name))
        if hasattr(conanfile, "set_version"):
            with conanfile_exception_formatter("conanfile.py", "set_version"):
                conanfile.set_version()
            if version and version != conanfile.version:
                raise ConanException("Package recipe with version %s!=%s"
                                     % (version, conanfile.version))

        return conanfile
Example #8
0
    def build(self,
              conanfile_path,
              source_folder,
              build_folder,
              package_folder,
              install_folder,
              test=False):
        """ Call to build() method saved on the conanfile.py
        param conanfile_path: path to a conanfile.py
        """
        logger.debug("Building in %s" % build_folder)
        logger.debug("Conanfile in %s" % conanfile_path)

        try:
            # Append env_vars to execution environment and clear when block code ends
            output = ScopedOutput(
                ("%s test package" % test) if test else "Project",
                self._user_io.out)
            conan_file = self.load_consumer_conanfile(conanfile_path,
                                                      install_folder,
                                                      output,
                                                      deps_info_required=True)
        except NotFoundException:
            # TODO: Auto generate conanfile from requirements file
            raise ConanException("'%s' file is needed for build.\n"
                                 "Create a '%s' and move manually the "
                                 "requirements and generators from '%s' file" %
                                 (CONANFILE, CONANFILE, CONANFILE_TXT))

        if test:
            try:
                conan_file.requires.add(test)
            except ConanException:
                pass

        try:
            mkdir(build_folder)
            os.chdir(build_folder)
            conan_file.conanfile_directory = source_folder
            conan_file.build_folder = build_folder
            conan_file.source_folder = source_folder
            conan_file.package_folder = package_folder
            conan_file.install_folder = install_folder
            with environment_append(conan_file.env):
                output.highlight("Running build()")
                with conanfile_exception_formatter(str(conan_file), "build"):
                    conan_file.build()
                if test:
                    output.highlight("Running test()")
                    with conanfile_exception_formatter(str(conan_file),
                                                       "test"):
                        conan_file.test()
        except ConanException:
            raise  # Raise but not let to reach the Exception except (not print traceback)
        except Exception:
            import traceback
            trace = traceback.format_exc().split('\n')
            raise ConanException("Unable to build it successfully\n%s" %
                                 '\n'.join(trace[3:]))
Example #9
0
    def _config_node(self, graph, node, down_reqs, down_ref, down_options):
        """ update settings and option in the current ConanFile, computing actual
        requirement values, cause they can be overridden by downstream requires
        param settings: dict of settings values => {"os": "windows"}
        """
        try:
            conanfile, ref = node.conanfile, node.ref
            # Avoid extra time manipulating the sys.path for python
            with get_env_context_manager(conanfile, without_python=True):
                if hasattr(conanfile, "config"):
                    if not ref:
                        conanfile.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, ref)
                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, "_conan_original_requires"):
                        conanfile._conan_original_requires = conanfile.requires.copy()
                    else:
                        conanfile.requires = conanfile._conan_original_requires.copy()

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

                new_options = conanfile.options.deps_package_values
                if graph.aliased:
                    for req in conanfile.requires.values():
                        req.ref = graph.aliased.get(req.ref, req.ref)
                new_down_reqs = conanfile.requires.update(down_reqs, self._output, ref, down_ref)
        except ConanExceptionInUserConanfileMethod:
            raise
        except ConanException as e:
            raise ConanException("%s: %s" % (ref or "Conanfile", str(e)))
        except Exception as e:
            raise ConanException(e)

        return new_down_reqs, new_options
Example #10
0
    def _compute_package_id(self, node, default_package_id_mode,
                            default_python_requires_id_mode):
        """
        Compute the binary package ID of this node
        :param node: the node to compute the package-ID
        :param default_package_id_mode: configuration of the package-ID mode
        """
        # TODO Conan 2.0. To separate the propagation of the graph (options) of the package-ID
        # A bit risky to be done now
        conanfile = node.conanfile
        neighbors = node.neighbors()

        direct_reqs, indirect_reqs = self.package_id_transitive_reqs(node)

        # FIXME: Conan v2.0 This is introducing a bug for backwards compatibility, it will add
        #   only the requirements available in the 'neighbour.info' object, not all the closure
        if not self._fixed_package_id:
            old_indirect = set()
            for neighbor in neighbors:
                old_indirect.update(
                    (p.ref, p.id)
                    for p in neighbor.conanfile.info.requires.refs())
            indirect_reqs = set(p for p in indirect_reqs
                                if (p.ref, p.id) in old_indirect)
            indirect_reqs.difference_update(direct_reqs)

        python_requires = getattr(conanfile, "python_requires", None)
        if python_requires:
            if isinstance(python_requires, dict):
                python_requires = None  # Legacy python-requires do not change package-ID
            else:
                python_requires = python_requires.all_refs()
        conanfile.info = ConanInfo.create(
            conanfile.settings.values,
            conanfile.options.values,
            direct_reqs,
            indirect_reqs,
            default_package_id_mode=default_package_id_mode,
            python_requires=python_requires,
            default_python_requires_id_mode=default_python_requires_id_mode)

        # Once we are done, call package_id() to narrow and change possible values
        with conanfile_exception_formatter(str(conanfile), "package_id"):
            with conan_v2_property(
                    conanfile, 'cpp_info',
                    "'self.cpp_info' access in package_id() method is deprecated"
            ):
                conanfile.package_id()

        if hasattr(conanfile, "validate") and callable(conanfile.validate):
            with conanfile_exception_formatter(str(conanfile), "validate"):
                try:
                    conanfile.validate()
                except ConanInvalidConfiguration as e:
                    conanfile.info.invalid = str(e)

        info = conanfile.info
        node.package_id = info.package_id()
Example #11
0
def create_package(conanfile,
                   source_folder,
                   build_folder,
                   package_folder,
                   output,
                   local=False,
                   copy_info=False):
    """ copies built artifacts, libs, headers, data, etc from build_folder to
    package folder
    """
    mkdir(package_folder)

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

    def wrap(dst_folder):
        def new_method(pattern, src=""):
            conanfile.copy(pattern, dst_folder, src)

        return new_method

    # FIXME: Deprecate these methods. Not documented. Confusing. Rely on LINTER
    conanfile.copy_headers = wrap(DEFAULT_INCLUDE)
    conanfile.copy_libs = wrap(DEFAULT_LIB)
    conanfile.copy_bins = wrap(DEFAULT_BIN)
    conanfile.copy_res = wrap(DEFAULT_RES)
    try:
        package_output = ScopedOutput("%s package()" % output.scope, output)
        output.highlight("Calling package()")
        if source_folder != build_folder:
            conanfile.copy = FileCopier(source_folder, package_folder,
                                        build_folder)
            with conanfile_exception_formatter(str(conanfile), "package"):
                conanfile.package()
            conanfile.copy.report(package_output, warn=True)
        conanfile.copy = FileCopier(build_folder, package_folder)
        with conanfile_exception_formatter(str(conanfile), "package"):
            conanfile.package()
        conanfile.copy.report(package_output, warn=True)
    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(build_folder, package_folder, conanfile, copy_info)
    output.success("Package '%s' created" % os.path.basename(package_folder))
Example #12
0
    def _config_node(self, node, 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:
            conanfile, conanref = node.conanfile, node.conan_ref
            # Avoid extra time manipulating the sys.path for python
            with get_env_context_manager(conanfile, without_python=True):
                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)
                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
Example #13
0
def build(graph_manager, hook_manager, conanfile_path,
          source_folder, build_folder, package_folder, install_folder,
          test=False, should_configure=True, should_build=True, should_install=True,
          should_test=True):
    """ Call to build() method saved on the conanfile.py
    param conanfile_path: path to a conanfile.py
    """
    logger.debug("BUILD: folder '%s'" % build_folder)
    logger.debug("BUILD: Conanfile at '%s'" % conanfile_path)

    try:
        conan_file = graph_manager.load_consumer_conanfile(conanfile_path, install_folder,
                                                           deps_info_required=True, test=test)
    except NotFoundException:
        # TODO: Auto generate conanfile from requirements file
        raise ConanException("'%s' file is needed for build.\n"
                             "Create a '%s' and move manually the "
                             "requirements and generators from '%s' file"
                             % (CONANFILE, CONANFILE, CONANFILE_TXT))

    if test:
        try:
            conan_file.requires.add_ref(test)
        except ConanException:
            pass

    conan_file.should_configure = should_configure
    conan_file.should_build = should_build
    conan_file.should_install = should_install
    conan_file.should_test = should_test

    try:
        mkdir(build_folder)
        os.chdir(build_folder)
        conan_file.build_folder = build_folder
        conan_file.source_folder = source_folder
        conan_file.package_folder = package_folder
        conan_file.install_folder = install_folder
        hook_manager.execute("pre_build", conanfile=conan_file,
                             conanfile_path=conanfile_path)
        with get_env_context_manager(conan_file):
            conan_file.output.highlight("Running build()")
            with conanfile_exception_formatter(str(conan_file), "build"):
                conan_file.build()
            hook_manager.execute("post_build", conanfile=conan_file,
                                 conanfile_path=conanfile_path)
            if test:
                conan_file.output.highlight("Running test()")
                with conanfile_exception_formatter(str(conan_file), "test"):
                    conan_file.test()
    except ConanException:
        raise  # Raise but not let to reach the Exception except (not print traceback)
    except Exception:
        import traceback
        trace = traceback.format_exc().split('\n')
        raise ConanException("Unable to build it successfully\n%s" % '\n'.join(trace[3:]))
Example #14
0
def create_package(conanfile, source_folder, build_folder, package_folder, install_folder,
                   output, local=False, copy_info=False):
    """ copies built artifacts, libs, headers, data, etc. from build_folder to
    package folder
    """
    mkdir(package_folder)

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

    try:
        package_output = ScopedOutput("%s package()" % output.scope, output)
        output.highlight("Calling package()")
        conanfile.package_folder = package_folder
        conanfile.source_folder = source_folder
        conanfile.install_folder = install_folder
        conanfile.build_folder = build_folder

        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)
    output.success("Package '%s' created" % os.path.basename(package_folder))
Example #15
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()")

        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()

        conanfile.copy = FileCopier(build_folder, package_folder)
        with tools.chdir(build_folder):
            with conanfile_exception_formatter(str(conanfile), "package"):
                conanfile.package()
    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)
    _report_files_from_manifest(package_output, package_folder)
    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)
Example #16
0
    def build(self, conanfile_path, source_folder, build_folder, package_folder, install_folder,
              test=False, should_configure=True, should_build=True, should_install=True):
        """ Call to build() method saved on the conanfile.py
        param conanfile_path: path to a conanfile.py
        """
        logger.debug("Building in %s" % build_folder)
        logger.debug("Conanfile in %s" % conanfile_path)

        try:
            # Append env_vars to execution environment and clear when block code ends
            output = ScopedOutput(("%s (test package)" % test) if test else "Project",
                                  self._user_io.out)
            conan_file = self._load_consumer_conanfile(conanfile_path, install_folder, output,
                                                       deps_info_required=True)
        except NotFoundException:
            # TODO: Auto generate conanfile from requirements file
            raise ConanException("'%s' file is needed for build.\n"
                                 "Create a '%s' and move manually the "
                                 "requirements and generators from '%s' file"
                                 % (CONANFILE, CONANFILE, CONANFILE_TXT))

        if test:
            try:
                conan_file.requires.add(test)
            except ConanException:
                pass

        conan_file.should_configure = should_configure
        conan_file.should_build = should_build
        conan_file.should_install = should_install

        try:
            mkdir(build_folder)
            os.chdir(build_folder)
            conan_file.build_folder = build_folder
            conan_file.source_folder = source_folder
            conan_file.package_folder = package_folder
            conan_file.install_folder = install_folder
            with get_env_context_manager(conan_file):
                output.highlight("Running build()")
                with conanfile_exception_formatter(str(conan_file), "build"):
                    conan_file.build()
                if test:
                    output.highlight("Running test()")
                    with conanfile_exception_formatter(str(conan_file), "test"):
                        conan_file.test()
        except ConanException:
            raise  # Raise but not let to reach the Exception except (not print traceback)
        except Exception:
            import traceback
            trace = traceback.format_exc().split('\n')
            raise ConanException("Unable to build it successfully\n%s" % '\n'.join(trace[3:]))
Example #17
0
    def load_basic_module(self, conanfile_path, lock_python_requires=None, user=None, channel=None,
                          display=""):
        """ loads a conanfile basic object without evaluating anything, returns the module too
        """
        cached = self._cached_conanfile_classes.get(conanfile_path)
        if cached and cached[1] == lock_python_requires:
            conanfile = cached[0](self._output, self._runner, display, user, channel,
                                  self._requester)
            if hasattr(conanfile, "init") and callable(conanfile.init):
                with conanfile_exception_formatter(str(conanfile), "init"):
                    conanfile.init()
            return conanfile, cached[2]

        if lock_python_requires is not None:
            self._python_requires.locked_versions = {r.name: r for r in lock_python_requires}
        try:
            self._python_requires.valid = True
            module, conanfile = parse_conanfile(conanfile_path, self._python_requires,
                                                self._generator_manager)
            self._python_requires.valid = False

            self._python_requires.locked_versions = None

            # This is the new py_requires feature, to supersede the old python_requires
            if self._pyreq_loader:
                self._pyreq_loader.load_py_requires(conanfile, lock_python_requires, self)

            conanfile.recipe_folder = os.path.dirname(conanfile_path)

            # If the scm is inherited, create my own instance
            if hasattr(conanfile, "scm") and "scm" not in conanfile.__class__.__dict__:
                if isinstance(conanfile.scm, dict):
                    conanfile.scm = conanfile.scm.copy()

            # Load and populate dynamic fields from the data file
            conan_data = self._load_data(conanfile_path)
            conanfile.conan_data = conan_data
            if conan_data and '.conan' in conan_data:
                scm_data = conan_data['.conan'].get('scm')
                if scm_data:
                    conanfile.scm.update(scm_data)

            self._cached_conanfile_classes[conanfile_path] = (conanfile, lock_python_requires,
                                                              module)
            result = conanfile(self._output, self._runner, display, user, channel, self._requester)
            if hasattr(result, "init") and callable(result.init):
                with conanfile_exception_formatter(str(result), "init"):
                    result.init()
            return result, module
        except ConanException as e:
            raise ConanException("Error loading conanfile at '{}': {}".format(conanfile_path, e))
Example #18
0
    def _call_package_info(conanfile, package_folder):
        conanfile.cpp_info = CppInfo(package_folder)
        conanfile.cpp_info.version = conanfile.version
        conanfile.cpp_info.description = conanfile.description
        conanfile.env_info = EnvInfo()
        conanfile.user_info = UserInfo()

        # Get deps_cpp_info from upstream nodes
        public_deps = [
            name for name, req in conanfile.requires.items() if not req.private
        ]
        conanfile.cpp_info.public_deps = public_deps
        # Once the node is build, execute package info, so it has access to the
        # package folder and artifacts
        with pythonpath(
                conanfile
        ):  # Minimal pythonpath, not the whole context, make it 50% slower
            with tools.chdir(package_folder):
                with conanfile_exception_formatter(str(conanfile),
                                                   "package_info"):
                    conanfile.package_folder = package_folder
                    conanfile.source_folder = None
                    conanfile.build_folder = None
                    conanfile.install_folder = None
                    conanfile.package_info()
Example #19
0
    def _compute_package_id(node, default_package_id_mode):
        conanfile = node.conanfile
        neighbors = node.neighbors()
        direct_reqs = []  # of PackageReference
        indirect_reqs = set()  # of PackageReference, avoid duplicates
        for neighbor in neighbors:
            ref, nconan = neighbor.ref, neighbor.conanfile
            direct_reqs.append(neighbor.pref)
            indirect_reqs.update(nconan.info.requires.refs())
            conanfile.options.propagate_downstream(ref,
                                                   nconan.info.full_options)
            # Might be never used, but update original requirement, just in case
            conanfile.requires[ref.name].ref = ref

        # Make sure not duplicated
        indirect_reqs.difference_update(direct_reqs)
        # There might be options that are not upstream, backup them, might be
        # for build-requires
        conanfile.build_requires_options = conanfile.options.values
        conanfile.options.clear_unused(indirect_reqs.union(direct_reqs))
        conanfile.options.freeze()

        conanfile.info = ConanInfo.create(
            conanfile.settings.values,
            conanfile.options.values,
            direct_reqs,
            indirect_reqs,
            default_package_id_mode=default_package_id_mode)

        # Once we are done, call package_id() to narrow and change possible values
        with conanfile_exception_formatter(str(conanfile), "package_id"):
            conanfile.package_id()

        info = conanfile.info
        node.package_id = info.package_id()
Example #20
0
def write_toolchain(conanfile, path, output):
    if hasattr(conanfile, "toolchain"):
        msg = (
            "\n*****************************************************************\n"
            "******************************************************************\n"
            "The 'toolchain' attribute or method has been deprecated and removed\n"
            "Use 'generators = \"ClassName\"' or 'generate()' method instead.\n"
            "********************************************************************\n"
            "********************************************************************\n"
        )
        raise ConanException(msg)

    _receive_conf(conanfile)

    if hasattr(conanfile, "generate"):
        output.highlight("Calling generate()")
        mkdir(path)
        with chdir(path):
            with conanfile_exception_formatter(str(conanfile), "generate"):
                conanfile.generate()

    # tools.env.virtualenv:auto_use will be always True in Conan 2.0
    if conanfile.conf["tools.env.virtualenv:auto_use"] and conanfile.virtualenv:
        with chdir(path):
            from conan.tools.env.virtualbuildenv import VirtualBuildEnv
            env = VirtualBuildEnv(conanfile)
            env.generate()

            env = VirtualRunEnv(conanfile)
            env.generate()

    output.highlight("Aggregating env generators")
    _generate_aggregated_env(conanfile)
Example #21
0
    def compute_package_ids(self):
        ordered = self.by_levels()
        for level in ordered:
            for node in level:
                conanfile = node.conanfile
                neighbors = node.neighbors()
                direct_reqs = []  # of PackageReference
                indirect_reqs = set()   # of PackageReference, avoid duplicates
                for neighbor in neighbors:
                    nref, nconan = neighbor.conan_ref, neighbor.conanfile
                    package_id = nconan.info.package_id()
                    package_reference = PackageReference(nref, package_id)
                    direct_reqs.append(package_reference)
                    indirect_reqs.update(nconan.info.requires.refs())
                    conanfile.options.propagate_downstream(nref, nconan.info.full_options)
                    # Might be never used, but update original requirement, just in case
                    conanfile.requires[nref.name].conan_reference = nref

                # Make sure not duplicated
                indirect_reqs.difference_update(direct_reqs)
                # There might be options that are not upstream, backup them, might be
                # for build-requires
                conanfile.build_requires_options = conanfile.options.values
                conanfile.options.clear_unused(indirect_reqs.union(direct_reqs))

                conanfile.info = ConanInfo.create(conanfile.settings.values,
                                                  conanfile.options.values,
                                                  direct_reqs,
                                                  indirect_reqs)

                # Once we are done, call package_id() to narrow and change possible values
                with conanfile_exception_formatter(str(conanfile), "package_id"):
                    conanfile.package_id()
        return ordered
Example #22
0
def config_source_local(dest_dir, conan_file, conanfile_folder, output):
    output.info('Configuring sources in %s' % dest_dir)
    conan_file.source_folder = dest_dir
    with tools.chdir(dest_dir):
        try:
            with conanfile_exception_formatter(str(conan_file), "source"):
                with get_env_context_manager(conan_file):
                    conan_file.build_folder = None
                    conan_file.package_folder = None
                    scm = get_scm(conan_file, dest_dir)
                    if scm:
                        if scm.capture_origin or scm.capture_revision:
                            output.info("Getting sources from folder: %s" %
                                        conanfile_folder)
                            merge_directories(conanfile_folder, dest_dir)
                            _clean_source_folder(dest_dir)
                        else:
                            output.info("Getting sources from url: '%s'" %
                                        scm.url)
                            scm.clone()
                            scm.checkout()

                    conan_file.source()
        except ConanExceptionInUserConanfileMethod:
            raise
        except Exception as e:
            raise ConanException(e)
Example #23
0
    def _build(self, conanfile, pref, build_folder):
        # Read generators from conanfile and generate the needed files
        logger.info("GENERATORS: Writing generators")
        write_generators(conanfile, build_folder, self._output)

        # Build step might need DLLs, binaries as protoc to generate source files
        # So execute imports() before build, storing the list of copied_files
        copied_files = run_imports(conanfile, build_folder)

        try:
            self._hook_manager.execute("pre_build", conanfile=conanfile,
                                       reference=pref.ref, package_id=pref.id)
            logger.debug("Call conanfile.build() with files in build folder: %s",
                         os.listdir(build_folder))
            self._output.highlight("Calling build()")
            with conanfile_exception_formatter(str(conanfile), "build"):
                conanfile.build()

            self._output.success("Package '%s' built" % pref.id)
            self._output.info("Build folder %s" % build_folder)
            self._hook_manager.execute("post_build", conanfile=conanfile,
                                       reference=pref.ref, package_id=pref.id)
        except Exception as exc:
            self._output.writeln("")
            self._output.error("Package '%s' build failed" % pref.id)
            self._output.warn("Build folder %s" % build_folder)
            if isinstance(exc, ConanExceptionInUserConanfileMethod):
                raise exc
            raise ConanException(exc)
        finally:
            # Now remove all files that were imported with imports()
            remove_imports(conanfile, copied_files, self._output)
Example #24
0
def _run_source(conanfile, conanfile_path, src_folder, hook_manager, reference, cache,
                get_sources_from_exports):
    """Execute the source core functionality, both for local cache and user space, in order:
        - Calling pre_source hook
        - Getting sources from SCM
        - Getting sources from exported folders in the local cache
        - Clean potential TGZ and other files in the local cache
        - Executing the recipe source() method
        - Calling post_source hook
    """
    conanfile.source_folder = src_folder
    conanfile.build_folder = None
    conanfile.package_folder = None
    with tools.chdir(src_folder):
        try:
            with get_env_context_manager(conanfile):
                hook_manager.execute("pre_source", conanfile=conanfile,
                                     conanfile_path=conanfile_path,
                                     reference=reference)
                output = conanfile.output
                output.info('Configuring sources in %s' % src_folder)
                get_sources_from_exports()

                if cache:
                    _clean_source_folder(src_folder)  # TODO: Why is it needed in cache?
                with conanfile_exception_formatter(conanfile.display_name, "source"):
                    conanfile.source()

                hook_manager.execute("post_source", conanfile=conanfile,
                                     conanfile_path=conanfile_path,
                                     reference=reference)
        except ConanExceptionInUserConanfileMethod:
            raise
        except Exception as e:
            raise ConanException(e)
Example #25
0
    def _build_package(self):
        """ builds the package, creating the corresponding build folder if necessary
        and copying there the contents from the src folder. The code is duplicated
        in every build, as some configure processes actually change the source
        code. Receives the build_folder because it can change if the method build_id() exists
        """
        package_folder = self._client_cache.package(
            self._package_reference, self._conan_file.short_paths)

        os.chdir(self.build_folder)
        self._conan_file.build_folder = self.build_folder
        self._conan_file.conanfile_directory = self.build_folder
        self._conan_file.package_folder = package_folder
        # In local cache, install folder always is build_folder
        self._conan_file.install_folder = self.build_folder

        # Read generators from conanfile and generate the needed files
        logger.debug("Writing generators")
        write_generators(self._conan_file, self.build_folder, self._out)
        logger.debug("Files copied after generators %s",
                     os.listdir(self.build_folder))

        # Build step might need DLLs, binaries as protoc to generate source files
        # So execute imports() before build, storing the list of copied_files
        from conans.client.importer import run_imports
        copied_files = run_imports(self._conan_file, self.build_folder,
                                   self._out)

        try:
            # This is necessary because it is different for user projects
            # than for packages
            logger.debug(
                "Call conanfile.build() with files in build folder: %s",
                os.listdir(self.build_folder))
            self._out.highlight("Calling build()")
            with conanfile_exception_formatter(str(self._conan_file), "build"):
                self._conan_file.build()

            self._out.success("Package '%s' built" %
                              self._conan_file.info.package_id())
            self._out.info("Build folder %s" % self.build_folder)
        except Exception as exc:
            self._out.writeln("")
            self._out.error("Package '%s' build failed" %
                            self._conan_file.info.package_id())
            self._out.warn("Build folder %s" % self.build_folder)
            if isinstance(exc, ConanExceptionInUserConanfileMethod):
                raise exc
            raise ConanException(exc)
        finally:
            export_folder = self._client_cache.export(self._conan_ref)
            self._conan_file.conanfile_directory = export_folder
            # Now remove all files that were imported with imports()
            for f in copied_files:
                try:
                    if f.startswith(self.build_folder):
                        os.remove(f)
                except OSError:
                    self._out.warn(
                        "Unable to remove imported file from build: %s" % f)
Example #26
0
def config_source_local(dest_dir, conanfile, conanfile_folder, output,
                        conanfile_path, hook_manager):
    conanfile.source_folder = dest_dir
    conanfile.build_folder = None
    conanfile.package_folder = None
    with tools.chdir(dest_dir):
        try:
            with conanfile_exception_formatter(str(conanfile), "source"):
                with get_env_context_manager(conanfile):
                    hook_manager.execute("pre_source",
                                         conanfile=conanfile,
                                         conanfile_path=conanfile_path)
                    output.info('Configuring sources in %s' % dest_dir)
                    scm_data = get_scm_data(conanfile)
                    if scm_data:
                        dest_dir = os.path.join(dest_dir, scm_data.subfolder)
                        capture = scm_data.capture_origin or scm_data.capture_revision
                        local_sources_path = conanfile_folder if capture else None
                        _fetch_scm(scm_data, dest_dir, local_sources_path,
                                   output)

                    conanfile.source()
                    hook_manager.execute("post_source",
                                         conanfile=conanfile,
                                         conanfile_path=conanfile_path)
        except ConanExceptionInUserConanfileMethod:
            raise
        except Exception as e:
            raise ConanException(e)
Example #27
0
    def _compute_package_id(node, default_package_id_mode):
        """
        Compute the binary package ID of this node
        :param node: the node to compute the package-ID
        :param default_package_id_mode: configuration of the package-ID mode
        """
        # TODO Conan 2.0. To separate the propagation of the graph (options) of the package-ID
        # A bit risky to be done now
        conanfile = node.conanfile
        neighbors = node.neighbors()
        direct_reqs = []  # of PackageReference
        indirect_reqs = set()  # of PackageReference, avoid duplicates
        for neighbor in neighbors:
            ref, nconan = neighbor.ref, neighbor.conanfile
            direct_reqs.append(neighbor.pref)
            indirect_reqs.update(nconan.info.requires.refs())

        # Make sure not duplicated
        indirect_reqs.difference_update(direct_reqs)
        conanfile.info = ConanInfo.create(
            conanfile.settings.values,
            conanfile.options.values,
            direct_reqs,
            indirect_reqs,
            default_package_id_mode=default_package_id_mode)

        # Once we are done, call package_id() to narrow and change possible values
        with conanfile_exception_formatter(str(conanfile), "package_id"):
            conanfile.package_id()

        info = conanfile.info
        node.package_id = info.package_id()
Example #28
0
def _call_package(conanfile, package_id, source_folder, build_folder, package_folder,
                  install_folder, hook_manager, conanfile_path, ref, copy_info):
    output = conanfile.output

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

    output.highlight("Calling package()")
    folders = [source_folder, build_folder] if source_folder != build_folder else [build_folder]
    conanfile.copy = FileCopier(folders, package_folder)
    with conanfile_exception_formatter(str(conanfile), "package"):
        with chdir(build_folder):
            with conan_v2_property(conanfile, 'info',
                                   "'self.info' access in package() method is deprecated"):
                conanfile.package()

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

    manifest = _create_aux_files(install_folder, package_folder, conanfile, copy_info)
    package_output = ScopedOutput("%s package()" % output.scope, output)
    report_files_from_manifest(package_output, manifest)
    package_id = package_id or os.path.basename(package_folder)

    output.success("Package '%s' created" % package_id)

    prev = manifest.summary_hash
    output.info("Created package revision %s" % prev)
    return prev
Example #29
0
    def _call_package_info(self, conanfile, package_folder, ref):
        conanfile.cpp_info = CppInfo(conanfile.name, package_folder)
        conanfile.cpp_info.version = conanfile.version
        conanfile.cpp_info.description = conanfile.description
        conanfile.env_info = EnvInfo()
        conanfile.user_info = UserInfo()

        # Get deps_cpp_info from upstream nodes
        public_deps = [name for name, req in conanfile.requires.items() if not req.private
                       and not req.override]
        conanfile.cpp_info.public_deps = public_deps
        # Once the node is build, execute package info, so it has access to the
        # package folder and artifacts
        conan_v2 = get_env(CONAN_V2_MODE_ENVVAR, False)
        with pythonpath(conanfile) if not conan_v2 else no_op():  # Minimal pythonpath, not the whole context, make it 50% slower
            with tools.chdir(package_folder):
                with conanfile_exception_formatter(str(conanfile), "package_info"):
                    conanfile.package_folder = package_folder
                    conanfile.source_folder = None
                    conanfile.build_folder = None
                    conanfile.install_folder = None
                    self._hook_manager.execute("pre_package_info", conanfile=conanfile,
                                               reference=ref)
                    conanfile.package_info()
                    if conanfile._conan_dep_cpp_info is None:
                        try:
                            conanfile.cpp_info._raise_incorrect_components_definition(
                                conanfile.name, conanfile.requires)
                        except ConanException as e:
                            raise ConanException("%s package_info(): %s" % (str(conanfile), e))
                        conanfile._conan_dep_cpp_info = DepCppInfo(conanfile.cpp_info)
                    self._hook_manager.execute("post_package_info", conanfile=conanfile,
                                               reference=ref)
Example #30
0
    def load_consumer_conanfile(self,
                                conanfile_path,
                                info_folder,
                                deps_info_required=False,
                                test=None):
        """loads a conanfile for local flow: source, imports, package, build
        """
        try:
            graph_info = GraphInfo.load(info_folder)
        except IOError:  # Only if file is missing
            # This is very dirty, should be removed for Conan 2.0 (source() method only)
            profile = self._cache.default_profile
            profile.process_settings(self._cache)
            name, version, user, channel = None, None, None, None
        else:
            name, version, user, channel, _ = graph_info.root
            profile = graph_info.profile
            profile.process_settings(self._cache, preprocess=False)
            # This is the hack of recovering the options from the graph_info
            profile.options.update(graph_info.options)
        processed_profile = ProcessedProfile(profile, None)
        if conanfile_path.endswith(".py"):
            conanfile = self._loader.load_consumer(
                conanfile_path,
                processed_profile=processed_profile,
                test=test,
                name=name,
                version=version,
                user=user,
                channel=channel)
            with get_env_context_manager(conanfile, without_python=True):
                with conanfile_exception_formatter(str(conanfile),
                                                   "config_options"):
                    conanfile.config_options()
                with conanfile_exception_formatter(str(conanfile),
                                                   "configure"):
                    conanfile.configure()

                conanfile.settings.validate()  # All has to be ok!
                conanfile.options.validate()
        else:
            conanfile = self._loader.load_conanfile_txt(
                conanfile_path, processed_profile)

        load_deps_info(info_folder, conanfile, required=deps_info_required)

        return conanfile
Example #31
0
    def _get_recipe_build_requires(conanfile):
        conanfile.build_requires = _RecipeBuildRequires(conanfile)
        if hasattr(conanfile, "build_requirements"):
            with get_env_context_manager(conanfile):
                with conanfile_exception_formatter(str(conanfile), "build_requirements"):
                    conanfile.build_requirements()

        return conanfile.build_requires
Example #32
0
    def _get_recipe_build_requires(conanfile):
        conanfile.build_requires = _RecipeBuildRequires(conanfile)
        if hasattr(conanfile, "build_requirements"):
            with get_env_context_manager(conanfile):
                with conanfile_exception_formatter(str(conanfile), "build_requirements"):
                    conanfile.build_requirements()

        return conanfile.build_requires
Example #33
0
    def _compute_package_id(self, node, default_package_id_mode,
                            default_python_requires_id_mode):
        """
        Compute the binary package ID of this node
        :param node: the node to compute the package-ID
        :param default_package_id_mode: configuration of the package-ID mode
        """
        # TODO Conan 2.0. To separate the propagation of the graph (options) of the package-ID
        # A bit risky to be done now
        conanfile = node.conanfile
        neighbors = node.neighbors()
        if not self._fixed_package_id:
            direct_reqs = []  # of PackageReference
            indirect_reqs = set()  # of PackageReference, avoid duplicates
            for neighbor in neighbors:
                ref, nconan = neighbor.ref, neighbor.conanfile
                direct_reqs.append(neighbor.pref)
                indirect_reqs.update(nconan.info.requires.refs())
            # Make sure not duplicated
            indirect_reqs.difference_update(direct_reqs)
        else:
            node.id_direct_prefs = set()  # of PackageReference
            node.id_indirect_prefs = set(
            )  # of PackageReference, avoid duplicates
            for neighbor in neighbors:
                node.id_direct_prefs.add(neighbor.pref)
                node.id_indirect_prefs.update(neighbor.id_direct_prefs)
                node.id_indirect_prefs.update(neighbor.id_indirect_prefs)
            # Make sure not duplicated, totally necessary
            node.id_indirect_prefs.difference_update(node.id_direct_prefs)
            direct_reqs = node.id_direct_prefs
            indirect_reqs = node.id_indirect_prefs

        python_requires = getattr(conanfile, "python_requires", None)
        if python_requires:
            if isinstance(python_requires, dict):
                python_requires = None  # Legacy python-requires do not change package-ID
            else:
                python_requires = python_requires.all_refs()
        conanfile.info = ConanInfo.create(
            conanfile.settings.values,
            conanfile.options.values,
            direct_reqs,
            indirect_reqs,
            default_package_id_mode=default_package_id_mode,
            python_requires=python_requires,
            default_python_requires_id_mode=default_python_requires_id_mode)

        # Once we are done, call package_id() to narrow and change possible values
        with conanfile_exception_formatter(str(conanfile), "package_id"):
            with conan_v2_property(
                    conanfile, 'cpp_info',
                    "'self.cpp_info' access in package_id() method is deprecated"
            ):
                conanfile.package_id()

        info = conanfile.info
        node.package_id = info.package_id()
Example #34
0
def call_package_info(conanfile, package_folder):
    # Once the node is build, execute package info, so it has access to the
    # package folder and artifacts
    with tools.chdir(package_folder):
        with conanfile_exception_formatter(str(conanfile), "package_info"):
            conanfile.source_folder = None
            conanfile.build_folder = None
            conanfile.install_folder = None
            conanfile.package_info()
Example #35
0
def build_id(conanfile):
    if hasattr(conanfile, "build_id"):
        # construct new ConanInfo
        build_id_info = conanfile.info.copy()
        conanfile.info_build = build_id_info
        # effectively call the user function to change the package values
        with conanfile_exception_formatter(str(conanfile), "build_id"):
            conanfile.build_id()
        # compute modified ID
        return build_id_info.package_id()
    return None
Example #36
0
def config_source_local(dest_dir, conan_file, output):
    output.info('Configuring sources in %s' % dest_dir)
    conan_file.source_folder = dest_dir

    with tools.chdir(dest_dir):
        try:
            with conanfile_exception_formatter(str(conan_file), "source"):
                with get_env_context_manager(conan_file):
                    conan_file.build_folder = None
                    conan_file.package_folder = None
                    conan_file.source()
        except ConanExceptionInUserConanfileMethod:
            raise
        except Exception as e:
            raise ConanException(e)
Example #37
0
def config_source_local(current_path, conan_file, output):
    output.info('Configuring sources in %s' % current_path)
    dirty = os.path.join(current_path, DIRTY_FILE)
    if os.path.exists(dirty):
        output.warn("Your previous source command failed")

    save(dirty, "")  # Creation of DIRTY flag
    try:
        with conanfile_exception_formatter(str(conan_file), "source"):
            with tools.environment_append(conan_file.env):
                conan_file.source()
            os.remove(dirty)  # Everything went well, remove DIRTY flag
    except ConanExceptionInUserConanfileMethod:
        raise
    except Exception as e:
        raise ConanException(e)
Example #38
0
    def propagate_info(self):
        """ takes the exports from upper level and updates the imports
        right now also the imports are propagated, but should be checked
        E.g. Conan A, depends on B.  A=>B
        B exports an include directory "my_dir", with root "/...../0123efe"
        A imports are the exports of B, plus any other conans it depends on
        A.imports.include_dirs = B.export.include_paths.
        Note the difference, include_paths used to compute full paths as the user
        defines export relative to its folder
        """
        ordered = self.by_levels()
        for level in ordered:
            for node in level:
                _, conanfile = node
                neighbors = self._neighbors[node]
                direct_reqs = []  # of PackageReference
                indirect_reqs = set()   # of PackageReference, avoid duplicates
                for nref, nconan in neighbors:
                    package_id = nconan.info.package_id()
                    package_reference = PackageReference(nref, package_id)
                    direct_reqs.append(package_reference)
                    indirect_reqs.update(nconan.info.requires.refs())
                    conanfile.options.propagate_downstream(nref, nconan.info.full_options)
                    # Might be never used, but update original requirement, just in case
                    conanfile.requires[nref.name].conan_reference = nref

                # Make sure not duplicated
                indirect_reqs.difference_update(direct_reqs)
                # There might be options that are not upstream
                conanfile.options.clear_unused(indirect_reqs.union(direct_reqs))

                non_devs = self.non_dev_nodes(node)

                conanfile.info = ConanInfo.create(conanfile.settings.values,
                                                  conanfile.options.values,
                                                  direct_reqs,
                                                  indirect_reqs,
                                                  non_devs)

                # Once we are done, call package_id() to narrow and change possible values
                if hasattr(conanfile, "conan_info"):
                    # Deprecated in 0.19
                    conanfile.conan_info()
                else:
                    with conanfile_exception_formatter(str(conanfile), "package_id"):
                        conanfile.package_id()
        return ordered
Example #39
0
    def _call_package_info(conanfile, package_folder):
        conanfile.cpp_info = CppInfo(package_folder)
        conanfile.cpp_info.version = conanfile.version
        conanfile.cpp_info.description = conanfile.description
        conanfile.env_info = EnvInfo()
        conanfile.user_info = UserInfo()

        # Get deps_cpp_info from upstream nodes
        public_deps = [name for name, req in conanfile.requires.items() if not req.private]
        conanfile.cpp_info.public_deps = public_deps
        # Once the node is build, execute package info, so it has access to the
        # package folder and artifacts
        with pythonpath(conanfile):  # Minimal pythonpath, not the whole context, make it 50% slower
            with tools.chdir(package_folder):
                with conanfile_exception_formatter(str(conanfile), "package_info"):
                    conanfile.package_folder = package_folder
                    conanfile.source_folder = None
                    conanfile.build_folder = None
                    conanfile.install_folder = None
                    conanfile.package_info()
Example #40
0
    def _build_package(self):
        """ calls the imports + conanfile.build() method
        """
        os.chdir(self.build_folder)
        self._conan_file.build_folder = self.build_folder
        self._conan_file.package_folder = self.package_folder
        # In local cache, install folder always is build_folder
        self._conan_file.install_folder = self.build_folder

        # Read generators from conanfile and generate the needed files
        logger.debug("Writing generators")
        write_generators(self._conan_file, self.build_folder, self._out)
        logger.debug("Files copied after generators %s", os.listdir(self.build_folder))

        # Build step might need DLLs, binaries as protoc to generate source files
        # So execute imports() before build, storing the list of copied_files
        from conans.client.importer import run_imports
        copied_files = run_imports(self._conan_file, self.build_folder, self._out)

        try:
            # This is necessary because it is different for user projects
            # than for packages
            logger.debug("Call conanfile.build() with files in build folder: %s",
                         os.listdir(self.build_folder))
            self._out.highlight("Calling build()")
            with conanfile_exception_formatter(str(self._conan_file), "build"):
                self._conan_file.build()

            self._out.success("Package '%s' built" % self._conan_file.info.package_id())
            self._out.info("Build folder %s" % self.build_folder)
        except Exception as exc:
            self._out.writeln("")
            self._out.error("Package '%s' build failed" % self._conan_file.info.package_id())
            self._out.warn("Build folder %s" % self.build_folder)
            if isinstance(exc, ConanExceptionInUserConanfileMethod):
                raise exc
            raise ConanException(exc)
        finally:
            # Now remove all files that were imported with imports()
            remove_imports(self._conan_file, copied_files, self._out)
Example #41
0
    def _build_package(self, export_folder, src_folder, build_folder, package_folder, conan_file, output):
        """ builds the package, creating the corresponding build folder if necessary
        and copying there the contents from the src folder. The code is duplicated
        in every build, as some configure processes actually change the source
        code
        """

        try:
            rmdir(build_folder)
            rmdir(package_folder)
        except Exception as e:
            raise ConanException("%s\n\nCouldn't remove folder, might be busy or open\n"
                                 "Close any app using it, and retry" % str(e))

        output.info('Building your package in %s' % build_folder)
        config_source(export_folder, src_folder, conan_file, output)
        output.info('Copying sources to build folder')

        def check_max_path_len(src, files):
            if platform.system() != "Windows":
                return []
            filtered_files = []
            for the_file in files:
                source_path = os.path.join(src, the_file)
                # Without storage path, just relative
                rel_path = os.path.relpath(source_path, src_folder)
                dest_path = os.path.normpath(os.path.join(build_folder, rel_path))
                # it is NOT that "/" is counted as "\\" so it counts double
                # seems a bug in python, overflows paths near the limit of 260,
                if len(dest_path) >= 249:
                    filtered_files.append(the_file)
                    output.warn("Filename too long, file excluded: %s" % dest_path)
            return filtered_files

        if getattr(conan_file, 'no_copy_source', False):
            mkdir(build_folder)
            conan_file.source_folder = src_folder
        else:
            shutil.copytree(src_folder, build_folder, symlinks=True, ignore=check_max_path_len)
            logger.debug("Copied to %s" % build_folder)
            logger.debug("Files copied %s" % os.listdir(build_folder))
            conan_file.source_folder = build_folder

        os.chdir(build_folder)
        conan_file.build_folder = build_folder
        conan_file._conanfile_directory = build_folder
        # Read generators from conanfile and generate the needed files
        logger.debug("Writing generators")
        write_generators(conan_file, build_folder, output)
        logger.debug("Files copied after generators %s" % os.listdir(build_folder))

        # Build step might need DLLs, binaries as protoc to generate source files
        # So execute imports() before build, storing the list of copied_files
        from conans.client.importer import run_imports
        copied_files = run_imports(conan_file, build_folder, output)

        try:
            # This is necessary because it is different for user projects
            # than for packages
            logger.debug("Call conanfile.build() with files in build folder: %s" % os.listdir(build_folder))
            with conanfile_exception_formatter(str(conan_file), "build"):
                conan_file.build()

            self._out.writeln("")
            output.success("Package '%s' built" % conan_file.info.package_id())
            output.info("Build folder %s" % build_folder)
        except Exception as exc:
            os.chdir(src_folder)
            self._out.writeln("")
            output.error("Package '%s' build failed" % conan_file.info.package_id())
            output.warn("Build folder %s" % build_folder)
            if isinstance(exc, ConanExceptionInUserConanfileMethod):
                raise exc
            raise ConanException(exc)

        finally:
            conan_file._conanfile_directory = export_folder
            # Now remove all files that were imported with imports()
            for f in copied_files:
                try:
                    if(f.startswith(build_folder)):
                        os.remove(f)
                except Exception:
                    self._out.warn("Unable to remove imported file from build: %s" % f)
Example #42
0
def config_source(export_folder, src_folder, conan_file, output, force=False):
    """ creates src folder and retrieve, calling source() from conanfile
    the necessary source code
    """
    dirty = os.path.join(src_folder, DIRTY_FILE)

    def remove_source(raise_error=True):
        output.warn("This can take a while for big packages")
        try:
            rmdir(src_folder)
        except BaseException as e_rm:
            save(dirty, "")  # Creation of DIRTY flag
            msg = str(e_rm)
            if six.PY2:
                msg = str(e_rm).decode("latin1")  # Windows prints some chars in latin1
            output.error("Unable to remove source folder %s\n%s" % (src_folder, msg))
            output.warn("**** Please delete it manually ****")
            if raise_error or isinstance(e_rm, KeyboardInterrupt):
                raise ConanException("Unable to remove source folder")

    if force:
        output.warn("Forced removal of source folder")
        remove_source()
    elif os.path.exists(dirty):
        output.warn("Trying to remove dirty source folder")
        remove_source()
    elif conan_file.build_policy_always:
        output.warn("Detected build_policy 'always', trying to remove source folder")
        remove_source()

    if not os.path.exists(src_folder):
        output.info('Configuring sources in %s' % src_folder)
        shutil.copytree(export_folder, src_folder, symlinks=True)
        # Now move the export-sources to the right location
        source_sources_folder = os.path.join(src_folder, EXPORT_SOURCES_DIR)
        if os.path.exists(source_sources_folder):
            _merge_directories(source_sources_folder, src_folder)
            # finally remove copied folder
            shutil.rmtree(source_sources_folder)
        for f in (EXPORT_TGZ_NAME, EXPORT_SOURCES_TGZ_NAME, CONANFILE+"c", CONANFILE+"o"):
            try:
                os.remove(os.path.join(src_folder, f))
            except OSError:
                pass
        try:
            shutil.rmtree(os.path.join(src_folder, "__pycache__"))
        except OSError:
            pass

        save(dirty, "")  # Creation of DIRTY flag
        os.chdir(src_folder)
        try:
            with tools.environment_append(conan_file.env):
                with conanfile_exception_formatter(str(conan_file), "source"):
                    conan_file.source()
            os.remove(dirty)  # Everything went well, remove DIRTY flag
        except Exception as e:
            os.chdir(export_folder)
            # in case source() fails (user error, typically), remove the src_folder
            # and raise to interrupt any other processes (build, package)
            output.warn("Trying to remove dirty source folder")
            remove_source(raise_error=False)
            if isinstance(e, ConanExceptionInUserConanfileMethod):
                raise e
            raise ConanException(e)
Example #43
0
 def _package_info_conanfile(self, conan_ref, conan_file):
     # Once the node is build, execute package info, so it has access to the
     # package folder and artifacts
     with conanfile_exception_formatter(str(conan_file), "package_info"):
         conan_file.package_info()