Ejemplo n.º 1
0
    def package(self):
        """Generate the info txt files and calls the conanfile package method.
        """

        # FIXME: Is weak to assign here the recipe_hash
        manifest = self._client_cache.load_manifest(self._conan_ref)
        self._conan_file.info.recipe_hash = manifest.summary_hash

        # Creating ***info.txt files
        save(os.path.join(self.build_folder, CONANINFO), self._conan_file.info.dumps())
        self._out.info("Generated %s" % CONANINFO)
        save(os.path.join(self.build_folder, BUILD_INFO), TXTGenerator(self._conan_file).content)
        self._out.info("Generated %s" % BUILD_INFO)

        os.chdir(self.build_folder)

        if getattr(self._conan_file, 'no_copy_source', False):
            source_folder = self.source_folder
        else:
            source_folder = self.build_folder
        with get_env_context_manager(self._conan_file):
            install_folder = self.build_folder  # While installing, the infos goes to build folder
            create_package(self._conan_file, source_folder, self.build_folder, self.package_folder,
                           install_folder, self._out)

        if get_env("CONAN_READ_ONLY_CACHE", False):
            make_read_only(self.package_folder)
Ejemplo n.º 2
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
Ejemplo n.º 3
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
Ejemplo n.º 4
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:]))
Ejemplo n.º 5
0
def run_imports(conanfile, dest_folder, output):
    if not hasattr(conanfile, "imports"):
        return []
    file_importer = _FileImporter(conanfile, dest_folder)
    conanfile.copy = file_importer
    conanfile.imports_folder = dest_folder
    with get_env_context_manager(conanfile):
        with tools.chdir(dest_folder):
            conanfile.imports()
    copied_files = file_importer.copied_files
    _make_files_writable(copied_files)
    import_output = ScopedOutput("%s imports()" % output.scope, output)
    _report_save_manifest(copied_files, import_output, dest_folder, IMPORTS_MANIFESTS)
    return copied_files
Ejemplo n.º 6
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)
 def _get_cmake_definitions(self):
     """
     Detect all definitions conan sends to cmake by command line and convert them to cmake commands. Removes the
     CONAN_EXPORTED definition, so that users may check if conan has been invoked or not.
     :return: string to print into a cmake file
     """
     with get_env_context_manager(self.conanfile):
         ret = []
         build_type = self.conanfile.settings.get_safe("build_type")
         generator = get_generator(self.conanfile.settings)
         def_builder = CMakeDefinitionsBuilder(self.conanfile,
                                               generator=generator,
                                               forced_build_type=build_type)
         cmake_version = self.get_version()
         definitions = def_builder.get_definitions(cmake_version)
         if "CONAN_EXPORTED" in definitions:
             del definitions["CONAN_EXPORTED"]
         for name, value in definitions.items():
             value = _cmake_escape_backslash(value)
             ret.append("set({name} {value})".format(name=name,
                                                     value=value))
         return os.linesep.join(ret)
    def _get_cmake_environment_setters(self):
        """
        Detect all environment changes made by conan and convert them to cmake commands
        :return: List of lines to print into a cmake file
        """
        old_env = dict(os.environ)

        with get_env_context_manager(self.conanfile):
            ret = ["\t\t\"environmentVariables\": {"]

            for name, value in self.conanfile.env.items():
                if isinstance(value, list):
                    if name in old_env:
                        value = str(get_env(name)).replace(
                            old_env[name], "${{env:{name}}}").format(name=name)
                    else:
                        value = str(value)
                value = _cmake_escape_backslash(value)
                ret.append("\t\t\t\"{name}\": \"{value}\"".format(name=name,
                                                                  value=value))
            ret[1:-1] = [line + "," for line in ret[1:-1]]
            return ret
Ejemplo n.º 9
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)
Ejemplo n.º 10
0
def config_source_local(dest_dir, conanfile, conanfile_folder, output):
    output.info('Configuring sources in %s' % dest_dir)
    conanfile.source_folder = dest_dir
    with tools.chdir(dest_dir):
        try:
            with conanfile_exception_formatter(str(conanfile), "source"):
                with get_env_context_manager(conanfile):
                    conanfile.build_folder = None
                    conanfile.package_folder = None
                    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()
        except ConanExceptionInUserConanfileMethod:
            raise
        except Exception as e:
            raise ConanException(e)
Ejemplo n.º 11
0
    def _config_node(node, 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"}
        """
        conanfile, ref = node.conanfile, node.ref
        try:
            run_configure_method(conanfile, down_options, down_ref, ref)

            with get_env_context_manager(conanfile, without_python=True):
                # 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 2 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
        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_options
Ejemplo n.º 12
0
    def package(self):
        """Generate the info txt files and calls the conanfile package method.
        """

        # FIXME: Is weak to assign here the recipe_hash
        manifest = self._client_cache.load_manifest(self._conan_ref)
        self._conan_file.info.recipe_hash = manifest.summary_hash

        # Creating ***info.txt files
        save(os.path.join(self.build_folder, CONANINFO), self._conan_file.info.dumps())
        self._out.info("Generated %s" % CONANINFO)
        save(os.path.join(self.build_folder, BUILD_INFO), TXTGenerator(self._conan_file).content)
        self._out.info("Generated %s" % BUILD_INFO)

        os.chdir(self.build_folder)

        if getattr(self._conan_file, 'no_copy_source', False):
            source_folder = self.source_folder
        else:
            source_folder = self.build_folder
        with get_env_context_manager(self._conan_file):
            install_folder = self.build_folder  # While installing, the infos goes to build folder
            pkg_id = self._conan_file.info.package_id()
            conanfile_path = self._client_cache.conanfile(self._conan_ref)

            create_package(self._conan_file, pkg_id, source_folder, self.build_folder,
                           self.package_folder, install_folder, self._out, self._hook_manager,
                           conanfile_path, self._conan_ref)

        p_hash = self._client_cache.package_summary_hash(self._package_reference)
        p_id = self._package_reference.package_id

        with self._client_cache.update_metadata(self._conan_ref) as metadata:
            metadata.packages[p_id].revision = p_hash
            metadata.packages[p_id].recipe_revision = self._conan_ref.revision

        if get_env("CONAN_READ_ONLY_CACHE", False):
            make_read_only(self.package_folder)
Ejemplo n.º 13
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)

        # Once the node is configured call the layout()
        if hasattr(conanfile, "layout"):
            conanfile.layout()
Ejemplo n.º 14
0
def run_deploy(conanfile, install_folder, output):
    deploy_output = ScopedOutput("%s deploy()" % output.scope, output)
    file_importer = _FileImporter(conanfile, install_folder)
    package_copied = set()

    # This is necessary to capture FileCopier full destination paths
    # Maybe could be improved in FileCopier
    def file_copier(*args, **kwargs):
        file_copy = FileCopier(conanfile.package_folder, install_folder)
        copied = file_copy(*args, **kwargs)
        _make_files_writable(copied)
        package_copied.update(copied)

    conanfile.copy_deps = file_importer
    conanfile.copy = file_copier
    conanfile.install_folder = install_folder
    with get_env_context_manager(conanfile):
        with tools.chdir(install_folder):
            conanfile.deploy()

    copied_files = file_importer.copied_files
    copied_files.update(package_copied)
    _report_save_manifest(copied_files, deploy_output, install_folder, "deploy_manifest.txt")
Ejemplo n.º 15
0
def run_deploy(conanfile, install_folder):
    deploy_output = ScopedOutput("%s deploy()" % conanfile.display_name, conanfile.output)
    file_importer = _FileImporter(conanfile, install_folder)
    package_copied = set()

    # This is necessary to capture FileCopier full destination paths
    # Maybe could be improved in FileCopier
    def file_copier(*args, **kwargs):
        file_copy = FileCopier(conanfile.package_folder, install_folder)
        copied = file_copy(*args, **kwargs)
        _make_files_writable(copied)
        package_copied.update(copied)

    conanfile.copy_deps = file_importer
    conanfile.copy = file_copier
    conanfile.install_folder = install_folder
    with get_env_context_manager(conanfile):
        with tools.chdir(install_folder):
            conanfile.deploy()

    copied_files = file_importer.copied_files
    copied_files.update(package_copied)
    _report_save_manifest(copied_files, deploy_output, install_folder, "deploy_manifest.txt")
Ejemplo n.º 16
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
Ejemplo n.º 17
0
def export_pkg(cache, graph_manager, hook_manager, recorder, output, ref,
               source_folder, build_folder, package_folder, install_folder,
               graph_info, force):

    conan_file_path = cache.conanfile(ref)
    if not os.path.exists(conan_file_path):
        raise ConanException("Package recipe '%s' does not exist" % str(ref))

    # The graph has to be loaded with build_mode=[ref.name], so that node is not tried
    # to be downloaded from remotes
    deps_graph, _ = graph_manager.load_graph(ref,
                                             None,
                                             graph_info=graph_info,
                                             build_mode=[ref.name],
                                             check_updates=False,
                                             update=False,
                                             remote_name=None,
                                             recorder=recorder,
                                             apply_build_requires=False)
    # this is a bit tricky, but works. The root (virtual), has only 1 neighbor,
    # which is the exported pkg
    nodes = deps_graph.root.neighbors()
    conanfile = nodes[0].conanfile
    from conans.client.conan_api import existing_info_files
    if install_folder and existing_info_files(install_folder):
        load_deps_info(install_folder, conanfile, required=True)
    package_id = nodes[0].package_id
    output.info("Packaging to %s" % package_id)
    pref = PackageReference(ref, package_id)
    dest_package_folder = cache.package(pref,
                                        short_paths=conanfile.short_paths)

    if os.path.exists(dest_package_folder):
        if force:
            rmdir(dest_package_folder)
        else:
            raise ConanException(
                "Package already exists. Please use --force, -f to "
                "overwrite it")

    recipe_hash = cache.package_layout(ref).recipe_manifest().summary_hash
    conanfile.info.recipe_hash = recipe_hash
    conanfile.develop = True
    if package_folder:
        packager.export_pkg(conanfile, package_id, package_folder,
                            dest_package_folder, hook_manager, conan_file_path,
                            ref)
    else:
        with get_env_context_manager(conanfile):
            packager.create_package(conanfile,
                                    package_id,
                                    source_folder,
                                    build_folder,
                                    dest_package_folder,
                                    install_folder,
                                    hook_manager,
                                    conan_file_path,
                                    ref,
                                    local=True)

    readed_manifest = FileTreeManifest.load(dest_package_folder)
    pref = PackageReference(pref.ref, pref.id, readed_manifest.summary_hash)
    output.info("Package revision %s" % pref.revision)
    with cache.package_layout(ref).update_metadata() as metadata:
        metadata.packages[package_id].revision = pref.revision
        metadata.packages[
            package_id].recipe_revision = metadata.recipe.revision

    recorder.package_exported(pref)
Ejemplo n.º 18
0
def config_source(export_folder, export_source_folder, local_sources_path,
                  src_folder, conanfile, output, conanfile_path, reference,
                  hook_manager, client_cache):
    """ creates src folder and retrieve, calling source() from conanfile
    the necessary source code
    """
    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:
            set_dirty(src_folder)
            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 is_dirty(src_folder):
        output.warn("Trying to remove corrupted source folder")
        remove_source()
    elif conanfile.build_policy_always:
        output.warn(
            "Detected build_policy 'always', trying to remove source folder")
        remove_source()
    elif local_sources_path and os.path.exists(local_sources_path):
        output.warn(
            "Detected 'scm' auto in conanfile, trying to remove source folder")
        remove_source()

    if not os.path.exists(src_folder):
        set_dirty(src_folder)
        mkdir(src_folder)
        os.chdir(src_folder)
        conanfile.source_folder = src_folder
        try:
            with conanfile_exception_formatter(str(conanfile), "source"):
                with get_env_context_manager(conanfile):
                    conanfile.build_folder = None
                    conanfile.package_folder = None
                    hook_manager.execute("pre_source",
                                         conanfile=conanfile,
                                         conanfile_path=conanfile_path,
                                         reference=reference)
                    output.info('Configuring sources in %s' % src_folder)
                    scm_data = get_scm_data(conanfile)
                    if scm_data:
                        dest_dir = os.path.normpath(
                            os.path.join(src_folder, scm_data.subfolder))
                        captured = local_sources_path and os.path.exists(
                            local_sources_path)
                        local_sources_path = local_sources_path if captured else None
                        _fetch_scm(scm_data, dest_dir, local_sources_path,
                                   output)

                    # Files from python requires are obtained before the self files
                    from conans.client.cmd.export import export_source
                    for python_require in conanfile.python_requires:
                        src = client_cache.export_sources(
                            python_require.conan_ref)
                        export_source(conanfile, src, src_folder, output)

                    # so self exported files have precedence over python_requires ones
                    merge_directories(export_folder, src_folder)
                    # Now move the export-sources to the right location
                    merge_directories(export_source_folder, src_folder)
                    _clean_source_folder(src_folder)
                    try:
                        shutil.rmtree(os.path.join(src_folder, "__pycache__"))
                    except OSError:
                        pass

                    conanfile.source()
                    hook_manager.execute("post_source",
                                         conanfile=conanfile,
                                         conanfile_path=conanfile_path,
                                         reference=reference)
            clean_dirty(src_folder)  # 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 corrupted source folder")
            remove_source(raise_error=False)
            if isinstance(e, ConanExceptionInUserConanfileMethod):
                raise e
            raise ConanException(e)
Ejemplo n.º 19
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,
              should_test=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._graph_manager.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
        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
            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:]))
Ejemplo n.º 20
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 overridden 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
Ejemplo n.º 21
0
def config_source(export_folder,
                  export_source_folder,
                  local_sources_path,
                  src_folder,
                  conan_file,
                  output,
                  force=False):
    """ creates src folder and retrieve, calling source() from conanfile
    the necessary source code
    """
    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:
            set_dirty(src_folder)
            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 is_dirty(src_folder):
        output.warn("Trying to remove corrupted 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
        merge_directories(export_source_folder, src_folder)
        _clean_source_folder(src_folder)
        try:
            shutil.rmtree(os.path.join(src_folder, "__pycache__"))
        except OSError:
            pass

        set_dirty(src_folder)
        os.chdir(src_folder)
        conan_file.source_folder = src_folder
        try:
            with get_env_context_manager(conan_file):
                with conanfile_exception_formatter(str(conan_file), "source"):
                    conan_file.build_folder = None
                    conan_file.package_folder = None

                    scm = get_scm(conan_file, src_folder)
                    if scm:
                        # scm.capture_origin before exporting
                        if local_sources_path and os.path.exists(
                                local_sources_path):
                            output.info("Getting sources from folder: %s" %
                                        local_sources_path)
                            merge_directories(local_sources_path, src_folder)
                            _clean_source_folder(src_folder)
                        else:
                            output.info("Getting sources from url: '%s'" %
                                        scm.url)
                            scm.clone()
                            scm.checkout()

                    conan_file.source()
            clean_dirty(src_folder)  # 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 corrupted source folder")
            remove_source(raise_error=False)
            if isinstance(e, ConanExceptionInUserConanfileMethod):
                raise e
            raise ConanException(e)
Ejemplo n.º 22
0
def cmd_build(app,
              conanfile_path,
              base_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 = app.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:
        # FIXME: Conan 2.0 all these build_folder, source_folder will disappear
        #  Only base_path and conanfile_path will remain
        if hasattr(conan_file, "layout"):
            conanfile_folder = os.path.dirname(conanfile_path)
            conan_file.folders.set_base_build(conanfile_folder)
            conan_file.folders.set_base_source(conanfile_folder)
            conan_file.folders.set_base_package(conanfile_folder)
            conan_file.folders.set_base_generators(conanfile_folder)
            conan_file.folders.set_base_install(conanfile_folder)
        else:
            conan_file.folders.set_base_build(build_folder)
            conan_file.folders.set_base_source(source_folder)
            conan_file.folders.set_base_package(package_folder)
            conan_file.folders.set_base_generators(base_path)
            conan_file.folders.set_base_install(install_folder)

        mkdir(conan_file.build_folder)
        with chdir(conan_file.build_folder):
            run_build_method(conan_file,
                             app.hook_manager,
                             conanfile_path=conanfile_path)

        if test:
            with get_env_context_manager(conan_file):
                conan_file.output.highlight("Running test()")
                with conanfile_exception_formatter(str(conan_file), "test"):
                    with chdir(conan_file.build_folder):
                        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:]))
Ejemplo n.º 23
0
def export_pkg(app, recorder, full_ref, source_folder, build_folder,
               package_folder, install_folder, graph_info, force, remotes):
    ref = full_ref.copy_clear_rev()
    cache, output, hook_manager = app.cache, app.out, app.hook_manager
    graph_manager = app.graph_manager
    conan_file_path = cache.package_layout(ref).conanfile()
    if not os.path.exists(conan_file_path):
        raise ConanException("Package recipe '%s' does not exist" % str(ref))

    # The graph has to be loaded with build_mode=[ref.name], so that node is not tried
    # to be downloaded from remotes
    deps_graph, _ = graph_manager.load_graph(ref,
                                             None,
                                             graph_info=graph_info,
                                             build_mode=[ref.name],
                                             check_updates=False,
                                             update=False,
                                             remotes=remotes,
                                             recorder=recorder,
                                             apply_build_requires=False)
    # this is a bit tricky, but works. The root (virtual), has only 1 neighbor,
    # which is the exported pkg
    nodes = deps_graph.root.neighbors()
    conanfile = nodes[0].conanfile
    from conans.client.conan_api import existing_info_files
    if install_folder and existing_info_files(install_folder):
        load_deps_info(install_folder, conanfile, required=True)
    package_id = nodes[0].package_id
    output.info("Packaging to %s" % package_id)
    pref = PackageReference(ref, package_id)
    layout = cache.package_layout(ref, short_paths=conanfile.short_paths)
    dest_package_folder = layout.package(pref)

    if os.path.exists(dest_package_folder):
        if force:
            rmdir(dest_package_folder)
        else:
            raise ConanException(
                "Package already exists. Please use --force, -f to "
                "overwrite it")

    recipe_hash = layout.recipe_manifest().summary_hash
    conanfile.info.recipe_hash = recipe_hash
    conanfile.develop = True
    if package_folder:
        prev = packager.export_pkg(conanfile, package_id, package_folder,
                                   dest_package_folder, hook_manager,
                                   conan_file_path, ref)
    else:
        with get_env_context_manager(conanfile):
            prev = packager.create_package(conanfile,
                                           package_id,
                                           source_folder,
                                           build_folder,
                                           dest_package_folder,
                                           install_folder,
                                           hook_manager,
                                           conan_file_path,
                                           ref,
                                           local=True)

    packager.update_package_metadata(prev, layout, package_id,
                                     full_ref.revision)
    pref = PackageReference(pref.ref, pref.id, prev)
    if graph_info.graph_lock:
        # after the package has been created we need to update the node PREV
        nodes[0].prev = pref.revision
        graph_info.graph_lock.update_check_graph(deps_graph, output)
    recorder.package_exported(pref)
Ejemplo n.º 24
0
def config_source(export_folder, export_source_folder, src_folder,
                  conan_file, output, force=False):
    """ creates src folder and retrieve, calling source() from conanfile
    the necessary source code
    """

    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:
            set_dirty(src_folder)
            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 is_dirty(src_folder):
        output.warn("Trying to remove corrupted 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
        merge_directories(export_source_folder, src_folder)
        for f in (EXPORT_TGZ_NAME, EXPORT_SOURCES_TGZ_NAME, CONANFILE+"c",
                  CONANFILE+"o", CONANFILE, CONAN_MANIFEST):
            try:
                os.remove(os.path.join(src_folder, f))
            except OSError:
                pass
        try:
            shutil.rmtree(os.path.join(src_folder, "__pycache__"))
        except OSError:
            pass

        set_dirty(src_folder)
        os.chdir(src_folder)
        conan_file.source_folder = src_folder
        try:
            with get_env_context_manager(conan_file):
                with conanfile_exception_formatter(str(conan_file), "source"):
                    conan_file.build_folder = None
                    conan_file.package_folder = None
                    conan_file.source()
            clean_dirty(src_folder)  # 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 corrupted source folder")
            remove_source(raise_error=False)
            if isinstance(e, ConanExceptionInUserConanfileMethod):
                raise e
            raise ConanException(e)
Ejemplo n.º 25
0
 def build(self):
     """Calls the conanfile's build method"""
     if self._skip_build:
         return
     with get_env_context_manager(self._conan_file):
         self._build_package()
Ejemplo n.º 26
0
 def build(self):
     """Calls the conanfile's build method"""
     if self._skip_build:
         return
     with get_env_context_manager(self._conan_file):
         self._build_package()
Ejemplo n.º 27
0
def cmd_build(app,
              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 = app.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
        app.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()
            app.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:]))