Esempio n. 1
0
    def _get_recipe(self, layout, ref, check_updates, update, remotes,
                    recorder):
        output = ScopedOutput(str(ref), self._out)
        # check if it is in disk
        conanfile_path = layout.conanfile()

        # NOT in disk, must be retrieved from remotes
        if not os.path.exists(conanfile_path):
            remote, new_ref = self._download_recipe(layout, ref, output,
                                                    remotes, remotes.selected,
                                                    recorder)
            status = RECIPE_DOWNLOADED
            return conanfile_path, status, remote, new_ref

        metadata = layout.load_metadata()
        cur_revision = metadata.recipe.revision
        cur_remote = metadata.recipe.remote
        cur_remote = remotes[cur_remote] if cur_remote else None
        selected_remote = remotes.selected or cur_remote

        check_updates = check_updates or update
        requested_different_revision = (
            ref.revision is not None) and cur_revision != ref.revision
        if requested_different_revision:
            if check_updates or self._cache.new_config[
                    "core:allow_explicit_revision_update"]:
                remote, new_ref = self._download_recipe(
                    layout, ref, output, remotes, selected_remote, recorder)
                status = RECIPE_DOWNLOADED
                return conanfile_path, status, remote, new_ref
            else:
                raise NotFoundException(
                    "The '%s' revision recipe in the local cache doesn't "
                    "match the requested '%s'."
                    " Use '--update' to check in the remote." %
                    (cur_revision, repr(ref)))

        if not check_updates:
            status = RECIPE_INCACHE
            ref = ref.copy_with_rev(cur_revision)
            return conanfile_path, status, cur_remote, ref

        # Checking updates in the server
        if not selected_remote:
            status = RECIPE_NO_REMOTE
            ref = ref.copy_with_rev(cur_revision)
            return conanfile_path, status, None, ref

        try:  # get_recipe_manifest can fail, not in server
            upstream_manifest, ref = self._remote_manager.get_recipe_manifest(
                ref, selected_remote)
        except NotFoundException:
            status = RECIPE_NOT_IN_REMOTE
            ref = ref.copy_with_rev(cur_revision)
            return conanfile_path, status, selected_remote, ref

        read_manifest = layout.recipe_manifest()
        if upstream_manifest != read_manifest:
            if upstream_manifest.time > read_manifest.time:
                if update:
                    DiskRemover().remove_recipe(layout, output=output)
                    output.info("Retrieving from remote '%s'..." %
                                selected_remote.name)
                    self._download_recipe(layout, ref, output, remotes,
                                          selected_remote, recorder)
                    status = RECIPE_UPDATED
                    return conanfile_path, status, selected_remote, ref
                else:
                    status = RECIPE_UPDATEABLE
            else:
                status = RECIPE_NEWER
        else:
            status = RECIPE_INCACHE

        ref = ref.copy_with_rev(cur_revision)
        return conanfile_path, status, selected_remote, ref
Esempio n. 2
0
    def create(self, conanfile_path, name=None, version=None, user=None, channel=None,
               profile_name=None, settings=None,
               options=None, env=None, test_folder=None, not_export=False,
               build_modes=None,
               keep_source=False, verify=None,
               manifests=None, manifests_interactive=None,
               remote=None, update=False, cwd=None):

        settings = settings or []
        options = options or []
        env = env or []

        cwd = cwd or os.getcwd()
        conanfile_path = _get_conanfile_path(conanfile_path, cwd, py=True)

        if not name or not version:
            conanfile = load_conanfile_class(conanfile_path)
            name, version = conanfile.name, conanfile.version
            if not name or not version:
                raise ConanException("conanfile.py doesn't declare package name or version")

        reference = ConanFileReference(name, version, user, channel)
        scoped_output = ScopedOutput(str(reference), self._user_io.out)
        # Forcing an export!
        if not not_export:
            scoped_output.highlight("Exporting package recipe")
            self._manager.export(conanfile_path, name, version, user, channel, keep_source)

        if build_modes is None:  # Not specified, force build the tested library
            build_modes = [name]

        manifests = _parse_manifests_arguments(verify, manifests, manifests_interactive, cwd)
        manifest_folder, manifest_interactive, manifest_verify = manifests
        profile = profile_from_args(profile_name, settings, options, env,
                                    cwd, self._client_cache)

        def get_test_conanfile_path(tf):
            """Searchs in the declared test_folder or in the standard locations"""
            test_folders = [tf] if tf else ["test_package", "test"]
            base_folder = os.path.dirname(conanfile_path)
            for test_folder_name in test_folders:
                test_folder = os.path.join(base_folder, test_folder_name)
                test_conanfile_path = os.path.join(test_folder, "conanfile.py")
                if os.path.exists(test_conanfile_path):
                    return test_conanfile_path
            else:
                if tf:
                    raise ConanException("test folder '%s' not available, "
                                         "or it doesn't have a conanfile.py" % tf)

        test_conanfile_path = get_test_conanfile_path(test_folder)

        if test_conanfile_path:
            pt = PackageTester(self._manager, self._user_io)
            pt.install_build_and_test(test_conanfile_path, reference, profile,
                                      remote, update, build_modes=build_modes,
                                      manifest_folder=manifest_folder,
                                      manifest_verify=manifest_verify,
                                      manifest_interactive=manifest_interactive)
        else:
            self._manager.install(reference=reference,
                                  install_folder=None,  # Not output anything
                                  manifest_folder=manifest_folder,
                                  manifest_verify=manifest_verify,
                                  manifest_interactive=manifest_interactive,
                                  remote=remote,
                                  profile=profile,
                                  build_modes=build_modes,
                                  update=update)
Esempio n. 3
0
    def install(self,
                reference,
                install_folder,
                profile,
                remote=None,
                build_modes=None,
                filename=None,
                update=False,
                manifest_folder=None,
                manifest_verify=False,
                manifest_interactive=False,
                generators=None,
                no_imports=False,
                inject_require=None,
                cwd=None,
                deploy=False):
        """ Fetch and build all dependencies for the given reference
        @param reference: ConanFileReference or path to user space conanfile
        @param install_folder: where the output files will be saved
        @param remote: install only from that remote
        @param profile: Profile object with both the -s introduced options and profile read values
        @param build_modes: List of build_modes specified
        @param filename: Optional filename of the conanfile
        @param update: Check for updated in the upstream remotes (and update)
        @param manifest_folder: Folder to install the manifests
        @param manifest_verify: Verify dependencies manifests against stored ones
        @param manifest_interactive: Install deps manifests in folder for later verify, asking user
        for confirmation
        @param generators: List of generators from command line. If False, no generator will be
        written
        @param no_imports: Install specified packages but avoid running imports
        @param inject_require: Reference to add as a requirement to the conanfile
        @param cwd: Only used in case of reference, to get a conanfile_directory to a virtual SMELL
        """
        if generators is not False:
            generators = set(generators) if generators else set()
            generators.add("txt")  # Add txt generator by default

        manifest_manager = ManifestManager(
            manifest_folder,
            user_io=self._user_io,
            client_cache=self._client_cache,
            verify=manifest_verify,
            interactive=manifest_interactive) if manifest_folder else None
        remote_proxy = ConanProxy(self._client_cache,
                                  self._user_io,
                                  self._remote_manager,
                                  remote,
                                  update=update,
                                  manifest_manager=manifest_manager)

        loader = self.get_loader(profile)
        conanfile = self._get_conanfile_object(loader,
                                               reference,
                                               filename,
                                               cwd=cwd)
        if inject_require:
            self._inject_require(conanfile, inject_require)
        graph_builder = self._get_graph_builder(loader, update, remote_proxy)
        deps_graph = graph_builder.load(conanfile)

        # This line is so the conaninfo stores the correct complete info
        conanfile.info.scope = profile.scopes

        registry = RemoteRegistry(self._client_cache.registry,
                                  self._user_io.out)

        if inject_require:
            output = ScopedOutput("%s test package" % str(inject_require),
                                  self._user_io.out)
            output.info("Installing dependencies")
        else:
            if not isinstance(reference, ConanFileReference):
                output = ScopedOutput("PROJECT", self._user_io.out)
                output.highlight("Installing %s" % reference)
            else:
                output = ScopedOutput(str(reference), self._user_io.out)
                output.highlight("Installing package")
            Printer(self._user_io.out).print_graph(deps_graph, registry)

        try:
            if loader._settings.os and detected_os() != loader._settings.os:
                message = "Cross-platform from '%s' to '%s'" % (
                    detected_os(), loader._settings.os)
                self._user_io.out.writeln(message, Color.BRIGHT_MAGENTA)
        except ConanException:  # Setting os doesn't exist
            pass

        build_mode = BuildMode(build_modes, self._user_io.out)
        build_requires = BuildRequires(loader, graph_builder, registry, output,
                                       profile.build_requires)
        installer = ConanInstaller(self._client_cache, output, remote_proxy,
                                   build_mode, build_requires)

        # Apply build_requires to consumer conanfile
        if not isinstance(reference, ConanFileReference):
            build_requires.install("", conanfile, installer)

        installer.install(deps_graph)
        build_mode.report_matches()

        if install_folder:
            # Write generators
            if generators is not False:
                tmp = list(conanfile.generators
                           )  # Add the command line specified generators
                tmp.extend([g for g in generators if g not in tmp])
                conanfile.generators = tmp
                write_generators(conanfile, install_folder, output)
            # Write conaninfo
            content = normalize(conanfile.info.dumps())
            save(os.path.join(install_folder, CONANINFO), content)
            output.info("Generated %s" % CONANINFO)
            if not no_imports:
                run_imports(conanfile, install_folder, output)
            call_system_requirements(conanfile, output)

            if deploy:
                # The conanfile loaded is really a virtual one. The one with the deploy is the first level one
                deploy_conanfile = deps_graph.inverse_levels()[1][0].conanfile
                if hasattr(deploy_conanfile, "deploy") and callable(
                        deploy_conanfile.deploy):
                    run_deploy(deploy_conanfile, install_folder, output)

        if manifest_manager:
            manifest_manager.print_log()
Esempio n. 4
0
    def _build(self, nodes_by_level, skip_private_nodes, build_mode):
        """ The build assumes an input of conans ordered by degree, first level
        should be independent from each other, the next-second level should have
        dependencies only to first level conans.
        param nodes_by_level: list of lists [[nodeA, nodeB], [nodeC], [nodeD, ...], ...]

        build_mode => ["*"] if user wrote "--build"
                   => ["hello*", "bye*"] if user wrote "--build hello --build bye"
                   => False if user wrote "never"
                   => True if user wrote "missing"
                   => "outdated" if user wrote "--build outdated"

        """

        inverse = self._deps_graph.inverse_levels()
        flat = []

        for level in inverse:
            level = sorted(level, key=lambda x: x.conan_ref)
            flat.extend(level)

        # Get the nodes in order and if we have to build them
        nodes_to_process = self._get_nodes(nodes_by_level, skip_private_nodes,
                                           build_mode)

        for conan_ref, package_id, conan_file, build_needed in nodes_to_process:

            if build_needed:
                build_allowed = self._build_allowed(conan_ref, build_mode,
                                                    conan_file)
                if not build_allowed:
                    self._raise_package_not_found_error(conan_ref, conan_file)

                output = ScopedOutput(str(conan_ref), self._out)
                package_ref = PackageReference(conan_ref, package_id)
                package_folder = self._client_cache.package(
                    package_ref, conan_file.short_paths)
                if build_mode is True:
                    output.info(
                        "Building package from source as defined by build_policy='missing'"
                    )
                elif self._build_forced(conan_ref, build_mode, conan_file):
                    output.warn('Forced build from source')

                t1 = time.time()
                # Assign to node the propagated info
                self._propagate_info(conan_ref, conan_file, flat)

                self._remote_proxy.get_recipe_sources(conan_ref)
                # Call the conanfile's build method
                build_folder = self._build_conanfile(conan_ref, conan_file,
                                                     package_ref,
                                                     package_folder, output)

                # Call the conanfile's package method
                self._package_conanfile(conan_ref, conan_file, package_ref,
                                        build_folder, package_folder, output)

                # Call the info method
                self._package_info_conanfile(conan_ref, conan_file)

                duration = time.time() - t1
                log_file = os.path.join(build_folder, RUN_LOG_NAME)
                log_file = log_file if os.path.exists(log_file) else None
                log_package_built(package_ref, duration, log_file)
            else:
                # Get the package, we have a not outdated remote package
                if conan_ref:
                    self._get_package(conan_ref, conan_file)

                # Assign to the node the propagated info
                # (conan_ref could be None if user project, but of course assign the info
                self._propagate_info(conan_ref, conan_file, flat)

                # Call the info method
                self._package_info_conanfile(conan_ref, conan_file)
Esempio n. 5
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
            self._plugin_manager.execute("pre_build",
                                         conanfile=conan_file,
                                         conanfile_path=conanfile_path)
            with get_env_context_manager(conan_file):
                output.highlight("Running build()")
                with conanfile_exception_formatter(str(conan_file), "build"):
                    conan_file.build()
                self._plugin_manager.execute("post_build",
                                             conanfile=conan_file,
                                             conanfile_path=conanfile_path)
                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:]))
Esempio n. 6
0
    def _build(self, nodes_by_level, skip_private_nodes, deps_graph):
        """ The build assumes an input of conans ordered by degree, first level
        should be independent from each other, the next-second level should have
        dependencies only to first level conans.
        param nodes_by_level: list of lists [[nodeA, nodeB], [nodeC], [nodeD, ...], ...]

        build_mode => ["*"] if user wrote "--build"
                   => ["hello*", "bye*"] if user wrote "--build hello --build bye"
                   => False if user wrote "never"
                   => True if user wrote "missing"
                   => "outdated" if user wrote "--build outdated"

        """

        inverse = deps_graph.inverse_levels()
        flat = []

        for level in inverse:
            level = sorted(level, key=lambda x: x.conan_ref)
            flat.extend(level)

        # Get the nodes in order and if we have to build them
        nodes_to_process = self._get_nodes(nodes_by_level, skip_private_nodes)

        for conan_ref, package_id, conan_file, build_needed in nodes_to_process:
            output = ScopedOutput(str(conan_ref), self._out)
            package_ref = PackageReference(conan_ref, package_id)

            if build_needed and (conan_ref,
                                 package_id) not in self._built_packages:
                build_allowed = self._build_mode.allowed(conan_file, conan_ref)
                if not build_allowed:
                    _raise_package_not_found_error(conan_file, conan_ref,
                                                   output)

                if conan_file.build_policy_missing:
                    output.info(
                        "Building package from source as defined by build_policy='missing'"
                    )
                elif self._build_mode.forced(conan_file, conan_ref):
                    output.warn('Forced build from source')

                self._build_requires.install(conan_ref, conan_file, self)

                t1 = time.time()
                # Assign to node the propagated info
                self._propagate_info(conan_file, conan_ref, flat, deps_graph)

                self._remote_proxy.get_recipe_sources(conan_ref,
                                                      conan_file.short_paths)
                builder = _ConanPackageBuilder(conan_file, package_ref,
                                               self._client_cache, output)
                builder.build()
                builder.package()

                self._remote_proxy.handle_package_manifest(package_ref,
                                                           installed=True)

                # Call the info method
                call_package_info(conan_file)

                # Log build
                self._log_built_package(conan_file, package_ref,
                                        time.time() - t1)
                self._built_packages.add((conan_ref, package_id))
            else:
                # Get the package, we have a not outdated remote package
                if conan_ref:
                    self.get_remote_package(conan_file, package_ref, output)

                # Assign to the node the propagated info
                # (conan_ref could be None if user project, but of course assign the info
                self._propagate_info(conan_file, conan_ref, flat, deps_graph)

                # Call the info method
                call_package_info(conan_file)
Esempio n. 7
0
    def _evaluate_node(self, node, build_mode, update, evaluated_references,
                       remote_name):
        assert node.binary is None

        conan_ref, conanfile = node.conan_ref, node.conanfile
        package_id = conanfile.info.package_id()
        package_ref = PackageReference(conan_ref, package_id)
        # Check that this same reference hasn't already been checked
        previous_node = evaluated_references.get(package_ref)
        if previous_node:
            node.binary = previous_node.binary
            node.binary_remote = previous_node.binary_remote
            return
        evaluated_references[package_ref] = node

        output = ScopedOutput(str(conan_ref), self._out)
        if build_mode.forced(conanfile, conan_ref):
            output.warn('Forced build from source')
            node.binary = BINARY_BUILD
            return

        package_folder = self._client_cache.package(
            package_ref, short_paths=conanfile.short_paths)

        # Check if dirty, to remove it
        local_project = self._workspace[conan_ref] if self._workspace else None
        if local_project:
            node.binary = BINARY_WORKSPACE
            return

        with self._client_cache.package_lock(package_ref):
            if is_dirty(package_folder):
                output.warn("Package is corrupted, removing folder: %s" %
                            package_folder)
                rmdir(package_folder)

        if remote_name:
            remote = self._registry.remote(remote_name)
        else:
            remote = self._registry.get_ref(conan_ref)
        remotes = self._registry.remotes

        if os.path.exists(package_folder):
            if update:
                if remote:
                    if self._check_update(package_folder, package_ref, remote,
                                          output):
                        node.binary = BINARY_UPDATE
                        if build_mode.outdated:
                            package_hash = self._get_package_info(
                                package_ref, remote).recipe_hash
                elif remotes:
                    pass
                else:
                    output.warn("Can't update, no remote defined")
            if not node.binary:
                node.binary = BINARY_CACHE
                package_hash = ConanInfo.load_file(
                    os.path.join(package_folder, CONANINFO)).recipe_hash
        else:  # Binary does NOT exist locally
            remote_info = None
            if remote:
                remote_info = self._get_package_info(package_ref, remote)
            elif remotes:  # Iterate all remotes to get this binary
                for r in remotes:
                    remote_info = self._get_package_info(package_ref, r)
                    if remote_info:
                        remote = r
                        break
            if remote_info:
                node.binary = BINARY_DOWNLOAD
                package_hash = remote_info.recipe_hash
            else:
                if build_mode.allowed(conanfile, conan_ref):
                    node.binary = BINARY_BUILD
                else:
                    node.binary = BINARY_MISSING

        if build_mode.outdated:
            if node.binary in (BINARY_CACHE, BINARY_DOWNLOAD, BINARY_UPDATE):
                local_recipe_hash = self._client_cache.load_manifest(
                    package_ref.conan).summary_hash
                if local_recipe_hash != package_hash:
                    output.info("Outdated package!")
                    node.binary = BINARY_BUILD
                else:
                    output.info("Package is up to date")

        node.binary_remote = remote
Esempio n. 8
0
    def get_recipe(self, conan_reference):
        output = ScopedOutput(str(conan_reference), self._out)

        def _refresh():
            export_path = self._client_cache.export(conan_reference)
            rmdir(export_path)
            # It might need to remove shortpath
            rm_conandir(self._client_cache.source(conan_reference))
            current_remote, _ = self._get_remote(conan_reference)
            output.info("Retrieving from remote '%s'..." % current_remote.name)
            self._remote_manager.get_recipe(conan_reference, export_path,
                                            current_remote)
            if self._update:
                output.info("Updated!")
            else:
                output.info("Installed!")

        # check if it is in disk
        conanfile_path = self._client_cache.conanfile(conan_reference)
        path_exist = path_exists(conanfile_path, self._client_cache.store)

        if path_exist:
            if self._check_updates:
                ret = self.update_available(conan_reference)
                if ret != 0:  # Found and not equal
                    remote, ref_remote = self._get_remote(conan_reference)
                    if ret == 1:
                        if not self._update:
                            if remote != ref_remote:  # Forced new remote
                                output.warn(
                                    "There is a new conanfile in '%s' remote. "
                                    "Execute 'install -u -r %s' to update it."
                                    % (remote.name, remote.name))
                            else:
                                output.warn(
                                    "There is a new conanfile in '%s' remote. "
                                    "Execute 'install -u' to update it." %
                                    remote.name)
                            output.warn("Refused to install!")
                        else:
                            if remote != ref_remote:
                                # Delete packages, could be non coherent with new remote
                                DiskRemover(
                                    self._client_cache).remove_packages(
                                        conan_reference)
                            _refresh()
                    elif ret == -1:
                        if not self._update:
                            output.info("Current conanfile is newer "
                                        "than %s's one" % remote.name)
                        else:
                            output.error(
                                "Current conanfile is newer than %s's one. "
                                "Run 'conan remove %s' and run install again "
                                "to replace it." %
                                (remote.name, conan_reference))

        else:
            self._retrieve_recipe(conan_reference, output)

        if self._manifest_manager:
            remote = self._registry.get_ref(conan_reference)
            self._manifest_manager.check_recipe(conan_reference, remote)

        return conanfile_path
Esempio n. 9
0
    def load_graph(self, reference, create_reference, graph_info, build_mode,
                   check_updates, update, remote_name, recorder, workspace):
        def _inject_require(conanfile, reference):
            """ test_package functionality requires injecting the tested package as requirement
            before running the install
            """
            require = conanfile.requires.get(reference.name)
            if require:
                require.conan_reference = require.range_reference = reference
            else:
                conanfile.requires(str(reference))
            conanfile._conan_user = reference.user
            conanfile._conan_channel = reference.channel

        # Computing the full dependency graph
        profile = graph_info.profile
        cache_settings = profile.processed_settings
        processed_profile = ProcessedProfile(profile, create_reference)
        if isinstance(reference,
                      list):  # Install workspace with multiple root nodes
            conanfile = self._loader.load_virtual(reference, processed_profile)
        elif isinstance(reference, ConanFileReference):
            # create without test_package and install <ref>
            conanfile = self._loader.load_virtual([reference],
                                                  processed_profile)
        else:
            output = ScopedOutput("PROJECT", self._output)
            if reference.endswith(".py"):
                conanfile = self._loader.load_conanfile(reference,
                                                        output,
                                                        processed_profile,
                                                        consumer=True)
                if create_reference:  # create with test_package
                    _inject_require(conanfile, create_reference)
            else:
                conanfile = self._loader.load_conanfile_txt(
                    reference, output, processed_profile)

        build_mode = BuildMode(build_mode, self._output)
        root_node = Node(None, conanfile)
        deps_graph = self._load_graph(
            root_node,
            check_updates,
            update,
            build_mode=build_mode,
            remote_name=remote_name,
            profile_build_requires=profile.build_requires,
            recorder=recorder,
            workspace=workspace,
            processed_profile=processed_profile)

        # THIS IS NECESSARY to store dependencies options in profile, for consumer
        # FIXME: This is a hack. Might dissapear if the graph for local commands is always recomputed
        graph_info.options = root_node.conanfile.options.values

        version_ranges_output = self._resolver.output
        if version_ranges_output:
            self._output.success("Version ranges solved")
            for msg in version_ranges_output:
                self._output.info("    %s" % msg)
            self._output.writeln("")

        build_mode.report_matches()
        return deps_graph, conanfile, cache_settings
Esempio n. 10
0
    def package(self, reference, package_id):
        # Package paths
        conan_file_path = self._client_cache.conanfile(reference)
        if not os.path.exists(conan_file_path):
            raise ConanException("Package recipe '%s' does not exist" %
                                 str(reference))

        conanfile = load_conanfile_class(conan_file_path)
        if hasattr(conanfile, "build_id"):
            raise ConanException(
                "package command does not support recipes with 'build_id'\n"
                "To repackage them use 'conan install'")

        if not package_id:
            packages = [
                PackageReference(reference, packid)
                for packid in self._client_cache.conan_builds(reference)
            ]
            if not packages:
                raise NotFoundException(
                    "%s: Package has not been built in local cache\n"
                    "Please read the 'conan package' command help\n"
                    "Use 'conan install' or 'conan test_package' to build and "
                    "create binaries" % str(reference))
        else:
            packages = [PackageReference(reference, package_id)]

        package_source_folder = self._client_cache.source(
            reference, conanfile.short_paths)
        for package_reference in packages:
            build_folder = self._client_cache.build(package_reference,
                                                    short_paths=None)
            if not os.path.exists(build_folder):
                raise NotFoundException(
                    "%s: Package binary '%s' folder doesn't exist\n"
                    "Please read the 'conan package' command help\n"
                    "Use 'conan install' or 'conan test_package' to build and "
                    "create binaries" %
                    (str(reference), package_reference.package_id))
            # The package already exist, we can use short_paths if they were defined
            package_folder = self._client_cache.package(package_reference,
                                                        short_paths=None)
            # Will read current conaninfo with specified options and load conanfile with them
            output = ScopedOutput(str(reference), self._user_io.out)
            output.info("Re-packaging %s" % package_reference.package_id)
            conanfile = self.load_consumer_conanfile(conan_file_path,
                                                     build_folder,
                                                     output,
                                                     reference=reference)
            rmdir(package_folder)
            if getattr(conanfile, 'no_copy_source', False):
                source_folder = package_source_folder
            else:
                source_folder = build_folder
            with environment_append(conanfile.env):
                packager.create_package(conanfile,
                                        source_folder,
                                        build_folder,
                                        package_folder,
                                        output,
                                        copy_info=True)
Esempio n. 11
0
    def _create_new_node(self,
                         current_node,
                         dep_graph,
                         requirement,
                         public_deps,
                         name_req,
                         aliased,
                         check_updates,
                         update,
                         remote_name,
                         processed_profile,
                         alias_ref=None):
        """ creates and adds a new node to the dependency graph
        """
        output = ScopedOutput(str(requirement.conan_reference), self._output)
        workspace_package = self._workspace[
            requirement.conan_reference] if self._workspace else None

        if workspace_package:
            conanfile_path = workspace_package.conanfile_path
            recipe_status = RECIPE_WORKSPACE
            remote = WORKSPACE_FILE
            new_ref = requirement.conan_reference
        else:
            try:
                result = self._proxy.get_recipe(requirement.conan_reference,
                                                check_updates, update,
                                                remote_name, self._recorder)
            except ConanException as e:
                base_ref = str(current_node.conan_ref or "PROJECT")
                self._output.error("Failed requirement '%s' from '%s'" %
                                   (requirement.conan_reference, base_ref))
                raise e
            conanfile_path, recipe_status, remote, new_ref = result

        dep_conanfile = self._loader.load_conanfile(
            conanfile_path,
            output,
            processed_profile,
            reference=requirement.conan_reference)

        if workspace_package:
            workspace_package.conanfile = dep_conanfile
        if getattr(dep_conanfile, "alias", None):
            alias_reference = alias_ref or new_ref.copy_clear_rev()
            requirement.conan_reference = ConanFileReference.loads(
                dep_conanfile.alias)
            aliased[alias_reference] = requirement.conan_reference
            return self._create_new_node(current_node,
                                         dep_graph,
                                         requirement,
                                         public_deps,
                                         name_req,
                                         aliased,
                                         check_updates,
                                         update,
                                         remote_name,
                                         processed_profile,
                                         alias_ref=alias_reference)

        logger.debug("GRAPH: new_node: %s" % str(new_ref))
        new_node = Node(new_ref, dep_conanfile)
        new_node.revision_pinned = requirement.conan_reference.revision is not None
        new_node.recipe = recipe_status
        new_node.remote = remote
        dep_graph.add_node(new_node)
        dep_graph.add_edge(current_node, new_node, requirement.private)
        if not requirement.private:
            public_deps[name_req] = new_node, None
        return new_node
Esempio n. 12
0
    def _get_recipe(self, reference, check_updates, update, remote_name, recorder):
        output = ScopedOutput(str(reference), self._out)
        # check if it is in disk
        conanfile_path = self._client_cache.conanfile(reference)

        # NOT in disk, must be retrieved from remotes
        if not os.path.exists(conanfile_path):
            remote, new_ref = self._download_recipe(reference, output, remote_name, recorder)
            status = RECIPE_DOWNLOADED
            return conanfile_path, status, remote, new_ref

        metadata = self._client_cache.load_metadata(reference)
        cur_revision = metadata.recipe.revision
        remote = self._registry.refs.get(reference)
        named_remote = self._registry.remotes.get(remote_name) if remote_name else None
        update_remote = named_remote or remote

        # Check if we have a revision different from the requested one
        revisions_enabled = get_env("CONAN_CLIENT_REVISIONS_ENABLED", False)
        if revisions_enabled and reference.revision and cur_revision != reference.revision:
            output.info("Different revision requested, removing current local recipe...")
            DiskRemover(self._client_cache).remove_recipe(reference)

            output.info("Retrieving from remote '%s'..." % update_remote.name)
            new_ref = self._remote_manager.get_recipe(reference, update_remote)
            self._registry.refs.set(new_ref, update_remote.name)
            status = RECIPE_UPDATED
            return conanfile_path, status, update_remote, new_ref

        check_updates = check_updates or update
        # Recipe exists in disk, but no need to check updates
        if not check_updates:
            status = RECIPE_INCACHE
            ref = reference.copy_with_rev(cur_revision)
            return conanfile_path, status, remote, ref

        if not update_remote:
            status = RECIPE_NO_REMOTE
            ref = reference.copy_with_rev(cur_revision)
            return conanfile_path, status, None, ref

        try:  # get_conan_manifest can fail, not in server
            upstream_manifest = self._remote_manager.get_conan_manifest(reference, update_remote)
        except NotFoundException:
            status = RECIPE_NOT_IN_REMOTE
            ref = reference.copy_with_rev(cur_revision)
            return conanfile_path, status, update_remote, ref

        export = self._client_cache.export(reference)
        read_manifest = FileTreeManifest.load(export)
        if upstream_manifest != read_manifest:
            if upstream_manifest.time > read_manifest.time:
                if update:
                    DiskRemover(self._client_cache).remove_recipe(reference)
                    output.info("Retrieving from remote '%s'..." % update_remote.name)
                    new_ref = self._remote_manager.get_recipe(reference, update_remote)
                    self._registry.refs.set(new_ref, update_remote.name)
                    status = RECIPE_UPDATED
                    return conanfile_path, status, update_remote, new_ref
                else:
                    status = RECIPE_UPDATEABLE
            else:
                status = RECIPE_NEWER
        else:
            status = RECIPE_INCACHE

        ref = reference.copy_with_rev(cur_revision)
        return conanfile_path, status, update_remote, ref
Esempio n. 13
0
    def install(self,
                reference,
                current_path,
                profile,
                remote=None,
                build_mode=None,
                filename=None,
                update=False,
                check_updates=False,
                manifest_folder=None,
                manifest_verify=False,
                manifest_interactive=False,
                generators=None,
                no_imports=False):
        """ Fetch and build all dependencies for the given reference
        @param reference: ConanFileReference or path to user space conanfile
        @param current_path: where the output files will be saved
        @param remote: install only from that remote
        @param options: list of tuples: [(optionname, optionvalue), (optionname, optionvalue)...]
        @param settings: list of tuples: [(settingname, settingvalue), (settingname, value)...]
        @param package_settings: dict name=> settings: {"zlib": [(settingname, settingvalue), ...]}
        @param profile: name of the profile to use
        @param env: list of tuples for environment vars: [(var, value), (var2, value2)...]
        @param package_env: package dict of list of tuples: {"package_name": [(var, value), (var2, value2)...]}
        """
        generators = generators or []

        if manifest_folder:
            manifest_manager = ManifestManager(
                manifest_folder,
                user_io=self._user_io,
                client_cache=self._client_cache,
                verify=manifest_verify,
                interactive=manifest_interactive)
        else:
            manifest_manager = None

        objects = self._get_graph(reference, current_path, profile, remote,
                                  filename, update, check_updates,
                                  manifest_manager)
        (_, deps_graph, _, registry, conanfile, remote_proxy, loader) = objects

        Printer(self._user_io.out).print_graph(deps_graph, registry)

        try:
            if detected_os() != loader._settings.os:
                message = "Cross-platform from '%s' to '%s'" % (
                    detected_os(), loader._settings.os)
                self._user_io.out.writeln(message, Color.BRIGHT_MAGENTA)
        except ConanException:  # Setting os doesn't exist
            pass

        installer = ConanInstaller(self._client_cache, self._user_io,
                                   remote_proxy)
        installer.install(deps_graph, build_mode)

        prefix = "PROJECT" if not isinstance(
            reference, ConanFileReference) else str(reference)
        output = ScopedOutput(prefix, self._user_io.out)

        # Write generators
        tmp = list(
            conanfile.generators)  # Add the command line specified generators
        tmp.extend(generators)
        conanfile.generators = tmp
        write_generators(conanfile, current_path, output)

        if not isinstance(reference, ConanFileReference):
            content = normalize(conanfile.info.dumps())
            save(os.path.join(current_path, CONANINFO), content)
            output.info("Generated %s" % CONANINFO)
            if not no_imports:
                run_imports(conanfile, current_path, output)
            installer.call_system_requirements(conanfile, output)

        if manifest_manager:
            manifest_manager.print_log()
Esempio n. 14
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()")

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

    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)
    _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
Esempio n. 15
0
    def create(self,
               conanfile_path,
               name=None,
               version=None,
               user=None,
               channel=None,
               profile_name=None,
               settings=None,
               options=None,
               env=None,
               test_folder=None,
               not_export=False,
               build_modes=None,
               keep_source=False,
               keep_build=False,
               verify=None,
               manifests=None,
               manifests_interactive=None,
               remote=None,
               update=False,
               cwd=None,
               test_build_folder=None):
        """
        API method to create a conan package

        :param test_folder: default None   - looks for default 'test' or 'test_package' folder),
                                    string - test_folder path
                                    False  - disabling tests
        """
        settings = settings or []
        options = options or []
        env = env or []

        try:
            cwd = cwd or os.getcwd()
            recorder = ActionRecorder()
            conanfile_path = _get_conanfile_path(conanfile_path, cwd, py=True)

            if not name or not version:
                conanfile = load_conanfile_class(conanfile_path)
                name, version = conanfile.name, conanfile.version
                if not name or not version:
                    raise ConanException(
                        "conanfile.py doesn't declare package name or version")

            reference = ConanFileReference(name, version, user, channel)
            scoped_output = ScopedOutput(str(reference), self._user_io.out)
            # Make sure keep_source is set for keep_build
            if keep_build:
                keep_source = True
            # Forcing an export!
            if not not_export:
                scoped_output.highlight("Exporting package recipe")
                cmd_export(conanfile_path, name, version, user, channel,
                           keep_source, self._user_io.out, self._client_cache)

            if build_modes is None:  # Not specified, force build the tested library
                build_modes = [name]

            manifests = _parse_manifests_arguments(verify, manifests,
                                                   manifests_interactive, cwd)
            manifest_folder, manifest_interactive, manifest_verify = manifests
            profile = profile_from_args(profile_name, settings, options, env,
                                        cwd, self._client_cache)

            manager = self._init_manager(recorder)
            recorder.add_recipe_being_developed(reference)

            create(reference, manager, self._user_io, profile, remote, update,
                   build_modes, manifest_folder, manifest_verify,
                   manifest_interactive, keep_build, test_build_folder,
                   test_folder, conanfile_path)

            return recorder.get_info()

        except ConanException as exc:
            recorder.error = True
            exc.info = recorder.get_info()
            raise
Esempio n. 16
0
    def _build_package(self, export_folder, src_folder, build_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
        """
        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

        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))
        os.chdir(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 FileImporter
        local_installer = FileImporter(self._deps_graph, self._client_cache,
                                       build_folder)
        conan_file.copy = local_installer
        conan_file.imports()
        copied_files = local_installer.execute()
        import_output = ScopedOutput("%s imports()" % output.scope, output)
        report_copied_files(copied_files, import_output)

        try:
            # This is necessary because it is different for user projects
            # than for packages
            conan_file._conanfile_directory = build_folder
            logger.debug(
                "Call conanfile.build() with files in build folder: %s" %
                os.listdir(build_folder))
            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 e:
            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)
            raise ConanException("%s: %s" % (conan_file.name, str(e)))
        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)
Esempio n. 17
0
    def install(self, reference, current_path, remote=None, options=None, settings=None,
                build_mode=False, filename=None, update=False, check_updates=False,
                manifest_folder=None, manifest_verify=False, manifest_interactive=False,
                scopes=None, generators=None, profile_name=None, package_settings=None,
                env=None, package_env=None, no_imports=False):
        """ Fetch and build all dependencies for the given reference
        @param reference: ConanFileReference or path to user space conanfile
        @param current_path: where the output files will be saved
        @param remote: install only from that remote
        @param options: list of tuples: [(optionname, optionvalue), (optionname, optionvalue)...]
        @param settings: list of tuples: [(settingname, settingvalue), (settingname, value)...]
        @param package_settings: dict name=> settings: {"zlib": [(settingname, settingvalue), ...]}
        @param profile: name of the profile to use
        @param env: list of tuples for environment vars: [(var, value), (var2, value2)...]
        @param package_env: package dict of list of tuples: {"package_name": [(var, value), (var2, value2)...]}
        """
        generators = generators or []

        if manifest_folder:
            manifest_manager = ManifestManager(manifest_folder, user_io=self._user_io,
                                               client_cache=self._client_cache,
                                               verify=manifest_verify,
                                               interactive=manifest_interactive)
        else:
            manifest_manager = None

        profile = self.read_profile(profile_name, current_path)

        # Mix Settings, Env vars and scopes between profile and command line
        if profile:
            profile.update_settings(settings)
            profile.update_package_settings(package_settings)
            settings = profile.settings
            package_settings = profile.package_settings

            profile.update_env(env)
            profile.update_packages_env(package_env)
            env = profile.env
            package_env = profile.package_env

            profile.update_scopes(scopes)
            scopes = profile.scopes

        objects = self._get_graph(reference, current_path, remote, options, settings, filename,
                                  update, check_updates, manifest_manager, scopes, package_settings,
                                  env, package_env)
        (_, deps_graph, _, registry, conanfile, remote_proxy, loader) = objects

        Printer(self._user_io.out).print_graph(deps_graph, registry)
        # Warn if os doesn't match
        try:
            if detected_os() != loader._settings.os:
                message = '''You are building this package with settings.os='%s' on a '%s' system.
If this is your intention, you can ignore this message.
If not:
     - Check the passed settings (-s)
     - Check your global settings in ~/.conan/conan.conf
     - Remove conaninfo.txt to avoid bad cached settings
''' % (loader._settings.os, detected_os())
                self._user_io.out.warn(message)
        except ConanException:  # Setting os doesn't exist
            pass

        installer = ConanInstaller(self._client_cache, self._user_io, remote_proxy)
        installer.install(deps_graph, build_mode)

        prefix = "PROJECT" if not isinstance(reference, ConanFileReference) else str(reference)
        output = ScopedOutput(prefix, self._user_io.out)

        # Write generators
        tmp = list(conanfile.generators)  # Add the command line specified generators
        tmp.extend(generators)
        conanfile.generators = tmp
        write_generators(conanfile, current_path, output)

        if not isinstance(reference, ConanFileReference):
            content = normalize(conanfile.info.dumps())
            save(os.path.join(current_path, CONANINFO), content)
            output.info("Generated %s" % CONANINFO)
            if not no_imports:
                run_imports(conanfile, current_path, output)
            installer.call_system_requirements(conanfile, output)

        if manifest_manager:
            manifest_manager.print_log()
Esempio n. 18
0
    def _get_recipe(self, reference, check_updates, update, remote_name,
                    recorder):
        output = ScopedOutput(str(reference), self._out)
        # check if it is in disk
        conanfile_path = self._client_cache.conanfile(reference)

        # NOT in disk, must be retrieved from remotes
        if not os.path.exists(conanfile_path):
            remote, new_ref = self._download_recipe(reference, output,
                                                    remote_name, recorder)
            status = RECIPE_DOWNLOADED
            return conanfile_path, status, remote, new_ref

        remote = self._registry.get_recipe_remote(reference)
        check_updates = check_updates or update
        # Recipe exists in disk, but no need to check updates
        if not check_updates:
            status = RECIPE_INCACHE
            log_recipe_got_from_local_cache(reference)
            recorder.recipe_fetched_from_cache(reference)
            return conanfile_path, status, remote, reference

        named_remote = self._registry.remote(
            remote_name) if remote_name else None
        update_remote = named_remote or remote
        if not update_remote:
            status = RECIPE_NO_REMOTE
            log_recipe_got_from_local_cache(reference)
            recorder.recipe_fetched_from_cache(reference)
            return conanfile_path, status, None, reference

        try:  # get_conan_manifest can fail, not in server
            upstream_manifest = self._remote_manager.get_conan_manifest(
                reference, update_remote)
        except NotFoundException:
            status = RECIPE_NOT_IN_REMOTE
            log_recipe_got_from_local_cache(reference)
            recorder.recipe_fetched_from_cache(reference)
            return conanfile_path, status, update_remote, reference

        export = self._client_cache.export(reference)
        read_manifest = FileTreeManifest.load(export)
        if upstream_manifest != read_manifest:
            if upstream_manifest.time > read_manifest.time:
                if update:
                    DiskRemover(self._client_cache).remove_recipe(reference)
                    output.info("Retrieving from remote '%s'..." %
                                update_remote.name)
                    reference = self._remote_manager.get_recipe(
                        reference, update_remote)
                    self._registry.set_ref(reference, update_remote.name)
                    status = RECIPE_UPDATED
                else:
                    status = RECIPE_UPDATEABLE
            else:
                status = RECIPE_NEWER
        else:
            status = RECIPE_INCACHE

        log_recipe_got_from_local_cache(reference)
        recorder.recipe_fetched_from_cache(reference)
        return conanfile_path, status, update_remote, reference
Esempio n. 19
0
    def complete_test(self):
        """ basic installation of a new conans
        """
        client = TestClient()
        client.init_dynamic_vars()
        files = hello_source_files()

        conan_ref = ConanFileReference.loads("Hello/1.2.1/frodo/stable")
        reg_folder = client.paths.export(conan_ref)

        client.save(files, path=reg_folder)
        client.save(
            {
                CONANFILE: myconan1,
                "infos/%s" % CONANINFO: "//empty",
                "include/no_copy/lib0.h": "NO copy",
                "include/math/lib1.h": "copy",
                "include/math/lib2.h": "copy",
                "include/physics/lib.hpp": "copy",
                "my_lib/debug/libd.a": "copy",
                "my_data/readme.txt": "copy",
                "my_data/readme.md": "NO copy",
                "contrib/math/math.h": "copy",
                "contrib/physics/gravity.h": "copy",
                "contrib/contrib.h": "copy",
                "include/opencv/opencv.hpp": "copy",
                "include/opencv2/opencv2.hpp": "copy",
                "modules/simu/src/simu.cpp": "NO copy",
                "modules/simu/include/opencv2/simu/simu.hpp": "copy",
                "modules/3D/doc/readme.md": "NO copy",
                "modules/3D/include/opencv2/3D/3D.hpp": "copy",
                "modules/dev/src/dev.cpp": "NO copy",
                "modules/dev/include/opencv2/dev/dev.hpp": "copy",
                "modules/opencv_mod.hpp": "copy"
            },
            path=reg_folder)

        conanfile_path = os.path.join(reg_folder, CONANFILE)
        package_ref = PackageReference(conan_ref, "myfakeid")
        build_folder = client.paths.build(package_ref)
        package_folder = client.paths.package(package_ref)
        install_folder = os.path.join(build_folder, "infos")

        shutil.copytree(reg_folder, build_folder)

        output = ScopedOutput("", TestBufferConanOutput())
        loader = ConanFileLoader(None, None, ConanPythonRequire(None, None))
        conanfile = loader.load_conanfile(conanfile_path, None,
                                          ProcessedProfile())

        create_package(conanfile,
                       None,
                       build_folder,
                       build_folder,
                       package_folder,
                       install_folder,
                       output,
                       client.hook_manager,
                       conanfile_path,
                       conan_ref,
                       copy_info=True)

        # test build folder
        self.assertTrue(os.path.exists(build_folder))
        self.assertTrue(os.path.exists(os.path.join(package_folder,
                                                    CONANINFO)))

        # test pack folder
        self.assertTrue(os.path.exists(package_folder))

        def exist(rel_path):
            return os.path.exists(os.path.join(package_folder, rel_path))

        # Expected files
        self.assertTrue(exist("include/lib1.h"))
        self.assertTrue(exist("include/lib2.h"))
        self.assertTrue(exist("include/physics/lib.hpp"))
        self.assertTrue(exist("include/contrib/math/math.h"))
        self.assertTrue(exist("include/contrib/physics/gravity.h"))
        self.assertTrue(exist("include/contrib/contrib.h"))
        self.assertTrue(exist("include/opencv/opencv.hpp"))
        self.assertTrue(exist("include/opencv2/opencv2.hpp"))
        self.assertTrue(exist("include/opencv2/simu/simu.hpp"))
        self.assertTrue(exist("include/opencv2/3D/3D.hpp"))
        self.assertTrue(exist("include/opencv2/dev/dev.hpp"))
        self.assertTrue(exist("lib/my_lib/libd.a"))
        self.assertTrue(exist("res/shares/readme.txt"))

        # Not expected files
        self.assertFalse(exist("include/opencv2/opencv_mod.hpp"))
        self.assertFalse(exist("include/opencv2/simu.hpp"))
        self.assertFalse(exist("include/opencv2/3D.hpp"))
        self.assertFalse(exist("include/opencv2/dev.hpp"))
        self.assertFalse(exist("include/modules/simu/src/simu.cpp"))
        self.assertFalse(exist("include/modules/3D/doc/readme.md"))
        self.assertFalse(exist("include/modules/dev/src/dev.cpp"))
        self.assertFalse(exist("include/opencv2/opencv_mod.hpp"))
        self.assertFalse(exist("include/include/no_copy/lib0.h"))
        self.assertFalse(exist("res/my_data/readme.md"))
Esempio n. 20
0
    def get_conanfile(self, conan_reference):
        output = ScopedOutput(str(conan_reference), self._out)

        def _refresh():
            conan_dir_path = self._paths.export(conan_reference)
            rmdir(conan_dir_path)
            rmdir(self._paths.source(conan_reference))
            current_remote, _ = self._get_remote(conan_reference)
            output.info("Retrieving from remote '%s'..." % current_remote.name)
            self._remote_manager.get_conanfile(conan_reference, current_remote)
            if self._update:
                output.info("Updated!")
            else:
                output.info("Installed!")

        # check if it is in disk
        conanfile_path = self._paths.conanfile(conan_reference)
        if path_exists(conanfile_path, self._paths.store):
            # Check manifest integrity
            read_manifest, expected_manifest = self._paths.conan_manifests(
                conan_reference)
            if read_manifest.file_sums != expected_manifest.file_sums:
                output.warn(
                    "Bad conanfile detected! Removing export directory... ")
                _refresh()
            else:  # Check for updates
                if self._check_updates:
                    ret = self.update_available(conan_reference)
                    if ret != 0:  # Found and not equal
                        remote, ref_remote = self._get_remote(conan_reference)
                        if ret == 1:
                            if not self._update:
                                if remote != ref_remote:  # Forced new remote
                                    output.warn(
                                        "There is a new conanfile in '%s' remote. "
                                        "Execute 'install -u -r %s' to update it."
                                        % (remote.name, remote.name))
                                else:
                                    output.warn(
                                        "There is a new conanfile in '%s' remote. "
                                        "Execute 'install -u' to update it." %
                                        remote.name)
                                output.warn("Refused to install!")
                            else:
                                if remote != ref_remote:
                                    # Delete packages, could be non coherent with new remote
                                    rmdir(
                                        self._paths.packages(conan_reference))
                                _refresh()
                        elif ret == -1:
                            if not self._update:
                                output.info("Current conanfile is newer "
                                            "than %s's one" % remote.name)
                            else:
                                output.error(
                                    "Current conanfile is newer than %s's one. "
                                    "Run 'conan remove %s' and run install again "
                                    "to replace it." %
                                    (remote.name, conan_reference))

        else:
            self._retrieve_conanfile(conan_reference, output)
        return conanfile_path
Esempio n. 21
0
    def _build_node(self, conan_ref, conan_file, build_mode):
        # Compute conan_file package from local (already compiled) or from remote
        output = ScopedOutput(str(conan_ref), self._out)
        package_id = conan_file.info.package_id()
        package_reference = PackageReference(conan_ref, package_id)
        check_outdated = build_mode == "outdated"

        conan_ref = package_reference.conan
        package_folder = self._client_cache.package(package_reference,
                                                    conan_file.short_paths)
        build_folder = self._client_cache.build(package_reference,
                                                conan_file.short_paths)
        src_folder = self._client_cache.source(conan_ref,
                                               conan_file.short_paths)
        export_folder = self._client_cache.export(conan_ref)

        # If already exists do not dirt the output, the common situation
        # is that package is already installed and OK. If don't, the proxy
        # will print some other message about it
        if not os.path.exists(package_folder):
            output.info("Installing package %s" % package_id)

        self._handle_system_requirements(conan_ref, package_reference,
                                         conan_file, output)

        force_build = self._build_forced(conan_ref, build_mode, conan_file)
        if self._remote_proxy.get_package(package_reference,
                                          force_build,
                                          short_paths=conan_file.short_paths,
                                          check_outdated=check_outdated):
            return

        # we need and can build? Only if we are forced or build_mode missing and package not exists
        # Option "--build outdated" means: missing or outdated, so don't care if it's really oudated
        # just build it.
        build = force_build or build_mode is True or check_outdated or conan_file.build_policy_missing
        if build:
            if not force_build and not build_mode:
                output.info(
                    "Building package from source as defined by build_policy='missing'"
                )
            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))
            if force_build:
                output.warn('Forced build from source')

            with environment_append(conan_file.env):
                self._build_package(export_folder, src_folder, build_folder,
                                    conan_file, output)

            # FIXME: Is weak to assign here the recipe_hash
            conan_file.info.recipe_hash = self._client_cache.load_manifest(
                conan_ref).summary_hash

            # Creating ***info.txt files
            save(os.path.join(build_folder, CONANINFO),
                 conan_file.info.dumps())
            output.info("Generated %s" % CONANINFO)
            save(os.path.join(build_folder, BUILD_INFO),
                 TXTGenerator(conan_file).content)
            output.info("Generated %s" % BUILD_INFO)
            save(os.path.join(build_folder, CONANENV),
                 ConanEnvGenerator(conan_file).content)
            output.info("Generated %s" % CONANENV)

            os.chdir(build_folder)
            with environment_append(conan_file.env):
                create_package(conan_file, build_folder, package_folder,
                               output)

            self._remote_proxy.handle_package_manifest(package_reference,
                                                       installed=True)
        else:
            self._raise_package_not_found_error(conan_ref, conan_file)
Esempio n. 22
0
    def _get_recipe(self, conan_reference, check_updates, update):
        output = ScopedOutput(str(conan_reference), self._out)
        check_updates = check_updates or update
        # check if it is in disk
        conanfile_path = self._client_cache.conanfile(conan_reference)

        if os.path.exists(conanfile_path):
            if check_updates:
                ret = self.update_available(conan_reference)
                if ret != 0:  # Found and not equal
                    remote, ref_remote = self._get_remote(conan_reference)
                    if ret == 1:
                        if not update:
                            if remote != ref_remote:  # Forced new remote
                                output.warn(
                                    "There is a new conanfile in '%s' remote. "
                                    "Execute 'install -u -r %s' to update it."
                                    % (remote.name, remote.name))
                            else:
                                output.warn(
                                    "There is a new conanfile in '%s' remote. "
                                    "Execute 'install -u' to update it." %
                                    remote.name)
                            output.warn("Refused to install!")
                        else:
                            DiskRemover(
                                self._client_cache).remove(conan_reference)
                            output.info("Retrieving from remote '%s'..." %
                                        remote.name)
                            self._remote_manager.get_recipe(
                                conan_reference, remote)
                            self._registry.set_ref(conan_reference, remote)
                            output.info("Updated!")
                    elif ret == -1:
                        if not update:
                            output.info(
                                "Current conanfile is newer than %s's one" %
                                remote.name)
                        else:
                            output.error(
                                "Current conanfile is newer than %s's one. "
                                "Run 'conan remove %s' and run install again "
                                "to replace it." %
                                (remote.name, conan_reference))

            log_recipe_got_from_local_cache(conan_reference)
            self._recorder.recipe_fetched_from_cache(conan_reference)

        else:
            self._retrieve_recipe(conan_reference, output)

        if self._manifest_manager:
            # Just make sure that the recipe sources are there to check
            conanfile = load_conanfile_class(conanfile_path)
            complete_recipe_sources(self._remote_manager, self._client_cache,
                                    self._registry, conanfile, conan_reference)

            remote = self._registry.get_ref(conan_reference)
            self._manifest_manager.check_recipe(conan_reference, remote)

        return conanfile_path
Esempio n. 23
0
    def install(self,
                reference,
                install_folder,
                profile,
                remote_name=None,
                build_modes=None,
                update=False,
                manifest_folder=None,
                manifest_verify=False,
                manifest_interactive=False,
                generators=None,
                no_imports=False,
                create_reference=None,
                keep_build=False):
        """ Fetch and build all dependencies for the given reference
        @param reference: ConanFileReference or path to user space conanfile
        @param install_folder: where the output files will be saved
        @param remote: install only from that remote
        @param profile: Profile object with both the -s introduced options and profile read values
        @param build_modes: List of build_modes specified
        @param update: Check for updated in the upstream remotes (and update)
        @param manifest_folder: Folder to install the manifests
        @param manifest_verify: Verify dependencies manifests against stored ones
        @param manifest_interactive: Install deps manifests in folder for later verify, asking user
        for confirmation
        @param generators: List of generators from command line. If False, no generator will be
        written
        @param no_imports: Install specified packages but avoid running imports
        @param inject_require: Reference to add as a requirement to the conanfile
        """

        if generators is not False:
            generators = set(generators) if generators else set()
            generators.add("txt")  # Add txt generator by default

        self._user_io.out.info("Configuration:")
        self._user_io.out.writeln(profile.dumps())
        result = self._graph_manager.load_graph(reference, create_reference,
                                                profile, build_modes, False,
                                                update, remote_name,
                                                self._recorder, None)
        deps_graph, conanfile, cache_settings = result

        if not isinstance(reference, ConanFileReference):
            output = ScopedOutput(
                ("%s (test package)" %
                 str(create_reference)) if create_reference else "PROJECT",
                self._user_io.out)
            output.highlight("Installing %s" % reference)
        else:
            output = ScopedOutput(str(reference), self._user_io.out)
            output.highlight("Installing package")
        print_graph(deps_graph, self._user_io.out)

        try:
            if cross_building(cache_settings):
                b_os, b_arch, h_os, h_arch = get_cross_building_settings(
                    cache_settings)
                message = "Cross-build from '%s:%s' to '%s:%s'" % (
                    b_os, b_arch, h_os, h_arch)
                self._user_io.out.writeln(message, Color.BRIGHT_MAGENTA)
        except ConanException:  # Setting os doesn't exist
            pass

        installer = ConanInstaller(self._client_cache,
                                   output,
                                   self._remote_manager,
                                   self._registry,
                                   recorder=self._recorder,
                                   workspace=None,
                                   plugin_manager=self._plugin_manager)
        installer.install(deps_graph, keep_build)

        if manifest_folder:
            manifest_manager = ManifestManager(manifest_folder,
                                               user_io=self._user_io,
                                               client_cache=self._client_cache)
            for node in deps_graph.nodes:
                if not node.conan_ref:
                    continue
                complete_recipe_sources(self._remote_manager,
                                        self._client_cache, self._registry,
                                        node.conanfile, node.conan_ref)
            manifest_manager.check_graph(deps_graph,
                                         verify=manifest_verify,
                                         interactive=manifest_interactive)
            manifest_manager.print_log()

        if install_folder:
            # Write generators
            if generators is not False:
                tmp = list(conanfile.generators
                           )  # Add the command line specified generators
                tmp.extend([g for g in generators if g not in tmp])
                conanfile.generators = tmp
                write_generators(conanfile, install_folder, output)
            if not isinstance(reference, ConanFileReference):
                # Write conaninfo
                content = normalize(conanfile.info.dumps())
                save(os.path.join(install_folder, CONANINFO), content)
                output.info("Generated %s" % CONANINFO)
            if not no_imports:
                run_imports(conanfile, install_folder, output)
            call_system_requirements(conanfile, output)

            if not create_reference and isinstance(reference,
                                                   ConanFileReference):
                # The conanfile loaded is really a virtual one. The one with the deploy is the first level one
                neighbours = deps_graph.root.neighbors()
                deploy_conanfile = neighbours[0].conanfile
                if hasattr(deploy_conanfile, "deploy") and callable(
                        deploy_conanfile.deploy):
                    run_deploy(deploy_conanfile, install_folder, output)
Esempio n. 24
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))

    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()")
        conanfile.package_folder = package_folder
        conanfile.source_folder = source_folder
        conanfile.build_folder = build_folder

        if source_folder != build_folder:
            conanfile.copy = FileCopier(source_folder, package_folder,
                                        build_folder)
            with conanfile_exception_formatter(str(conanfile), "package"):
                with tools.chdir(build_folder):
                    conanfile.package()
            conanfile.copy.report(package_output, warn=True)
        conanfile.copy = FileCopier(build_folder, package_folder)

        with tools.chdir(build_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(install_folder, package_folder, conanfile, copy_info)
    output.success("Package '%s' created" % os.path.basename(package_folder))
Esempio n. 25
0
    def _config_node(self, node, down_reqs, down_ref, down_options, aliased):
        """ 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, "_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 aliased:
                    for req in conanfile.requires.values():
                        req.conan_reference = aliased.get(req.conan_reference,
                                                          req.conan_reference)
                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
Esempio n. 26
0
    def create(self,
               profile_name=None,
               settings=None,
               options=None,
               env=None,
               scope=None,
               test_folder=None,
               not_export=False,
               build=None,
               keep_source=False,
               verify=default_manifest_folder,
               manifests=default_manifest_folder,
               manifests_interactive=default_manifest_folder,
               remote=None,
               update=False,
               cwd=None,
               user=None,
               channel=None,
               name=None,
               version=None):

        settings = settings or []
        options = options or []
        env = env or []
        cwd = prepare_cwd(cwd)

        if not name or not version:
            conanfile_path = os.path.join(cwd, "conanfile.py")
            conanfile = load_conanfile_class(conanfile_path)
            try:
                name, version = conanfile.name, conanfile.version
            except:
                raise ConanException(
                    "conanfile.py doesn't declare package name or version")

        reference = ConanFileReference(name, version, user, channel)
        scoped_output = ScopedOutput(str(reference), self._user_io.out)
        # Forcing an export!
        if not not_export:
            scoped_output.highlight("Exporting package recipe")
            self._manager.export(user,
                                 channel,
                                 cwd,
                                 keep_source=keep_source,
                                 name=name,
                                 version=version)

        if build is None:  # Not specified, force build the tested library
            build = [name]

        manifests = _parse_manifests_arguments(verify, manifests,
                                               manifests_interactive, cwd)
        manifest_folder, manifest_interactive, manifest_verify = manifests
        profile = profile_from_args(profile_name, settings, options, env,
                                    scope, cwd,
                                    self._client_cache.profiles_path)
        self._manager.install(reference=reference,
                              current_path=cwd,
                              manifest_folder=manifest_folder,
                              manifest_verify=manifest_verify,
                              manifest_interactive=manifest_interactive,
                              remote=remote,
                              profile=profile,
                              build_modes=build,
                              update=update)

        test_folders = [test_folder
                        ] if test_folder else ["test_package", "test"]
        for test_folder_name in test_folders:
            test_folder = os.path.join(cwd, test_folder_name)
            test_conanfile_path = os.path.join(test_folder, "conanfile.py")
            if os.path.exists(test_conanfile_path):
                break
        else:
            self._user_io.out.warn(
                "test package folder not available, or it doesn't have "
                "a conanfile.py\nIt is recommended to set a 'test_package' "
                "while creating packages")
            return

        scoped_output.highlight("Testing with 'test_package'")
        sha = hashlib.sha1("".join(options + settings).encode()).hexdigest()
        build_folder = os.path.join(test_folder, "build", sha)
        rmdir(build_folder)

        test_conanfile = os.path.join(test_folder, CONANFILE)
        self._manager.install(inject_require=reference,
                              reference=test_folder,
                              current_path=build_folder,
                              manifest_folder=manifest_folder,
                              manifest_verify=manifest_verify,
                              manifest_interactive=manifest_interactive,
                              remote=remote,
                              profile=profile,
                              update=update,
                              generators=["txt"])
        self._manager.build(test_conanfile,
                            test_folder,
                            build_folder,
                            package_folder=None,
                            test=str(reference))
Esempio n. 27
0
def create_package(conanfile,
                   pkg_id,
                   source_folder,
                   build_folder,
                   package_folder,
                   install_folder,
                   output,
                   hook_manager,
                   conanfile_path,
                   reference,
                   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:
        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=reference,
                             package_id=pkg_id)

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

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

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

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

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

    _create_aux_files(install_folder, package_folder, conanfile, copy_info)
    pkg_id = pkg_id or os.path.basename(package_folder)
    output.success("Package '%s' created" % pkg_id)
    hook_manager.execute("post_package",
                         conanfile=conanfile,
                         conanfile_path=conanfile_path,
                         reference=reference,
                         package_id=pkg_id)
Esempio n. 28
0
    def build(self,
              conanfile_path,
              current_path,
              test=False,
              filename=None,
              profile_name=None,
              env=None,
              package_env=None):
        """ Call to build() method saved on the conanfile.py
        param conanfile_path: the original source directory of the user containing a
                            conanfile.py
        """
        logger.debug("Building in %s" % current_path)
        logger.debug("Conanfile in %s" % conanfile_path)

        if filename and filename.endswith(".txt"):
            raise ConanException(
                "A conanfile.py is needed to call 'conan build'")

        conanfile_file = os.path.join(conanfile_path, filename or CONANFILE)

        try:
            # Append env_vars to execution environment and clear when block code ends
            profile = self.read_profile(profile_name, current_path)
            output = ScopedOutput("Project", self._user_io.out)
            if profile:
                profile.update_env(env)
                profile.update_packages_env(package_env)

                env = profile.env
                package_env = profile.package_env

            package_env = profile.package_env if profile else None
            loader = self._loader(current_path,
                                  env=env,
                                  package_env=package_env)
            conan_file = loader.load_conan(conanfile_file,
                                           output,
                                           consumer=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))
        try:
            self._load_deps_info(current_path, conan_file, output)

            os.chdir(current_path)
            conan_file._conanfile_directory = conanfile_path
            with environment_append(conan_file.env):
                conan_file.build()

            if 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:]))
Esempio n. 29
0
    def _evaluate_node(self, node, build_mode, update, evaluated_references,
                       remote_name):
        assert node.binary is None

        conan_ref, conanfile = node.conan_ref, node.conanfile
        revisions_enabled = get_env("CONAN_CLIENT_REVISIONS_ENABLED", False)
        package_id = conanfile.info.package_id()
        package_ref = PackageReference(conan_ref, package_id)
        # Check that this same reference hasn't already been checked
        previous_node = evaluated_references.get(package_ref)
        if previous_node:
            node.binary = previous_node.binary
            node.binary_remote = previous_node.binary_remote
            return
        evaluated_references[package_ref] = node

        output = ScopedOutput(str(conan_ref), self._out)
        if build_mode.forced(conanfile, conan_ref):
            output.warn('Forced build from source')
            node.binary = BINARY_BUILD
            return

        package_folder = self._client_cache.package(
            package_ref, short_paths=conanfile.short_paths)

        # Check if dirty, to remove it
        local_project = self._workspace[conan_ref] if self._workspace else None
        if local_project:
            node.binary = BINARY_WORKSPACE
            return

        with self._client_cache.package_lock(package_ref):
            if is_dirty(package_folder):
                output.warn("Package is corrupted, removing folder: %s" %
                            package_folder)
                rmdir(package_folder)

        if remote_name:
            remote = self._registry.remotes.get(remote_name)
        else:
            # If the remote_name is not given, follow the binary remote, or
            # the recipe remote
            # If it is defined it won't iterate (might change in conan2.0)
            remote = self._registry.prefs.get(
                package_ref) or self._registry.refs.get(conan_ref)
        remotes = self._registry.remotes.list

        if os.path.exists(package_folder):
            if update:
                if remote:
                    if self._check_update(package_folder, package_ref, remote,
                                          output, node):
                        node.binary = BINARY_UPDATE
                        if build_mode.outdated:
                            package_hash = self._get_package_info(
                                package_ref, remote).recipe_hash
                elif remotes:
                    pass
                else:
                    output.warn("Can't update, no remote defined")
            if not node.binary:
                node.binary = BINARY_CACHE
                package_hash = ConanInfo.load_from_package(
                    package_folder).recipe_hash
        else:  # Binary does NOT exist locally
            if not revisions_enabled and not node.revision_pinned:
                # Do not search for packages for the specific resolved recipe revision but all
                package_ref = package_ref.copy_clear_rev()

            remote_info = None
            if remote:
                remote_info = self._get_package_info(package_ref, remote)

            # If the "remote" came from the registry but the user didn't specified the -r, with
            # revisions iterate all remotes
            if not remote or (not remote_info and revisions_enabled
                              and not remote_name):
                for r in remotes:
                    remote_info = self._get_package_info(package_ref, r)
                    if remote_info:
                        remote = r
                        break

            if remote_info:
                node.binary = BINARY_DOWNLOAD
                package_hash = remote_info.recipe_hash
            else:
                if build_mode.allowed(conanfile, conan_ref):
                    node.binary = BINARY_BUILD
                else:
                    node.binary = BINARY_MISSING

        if build_mode.outdated:
            if node.binary in (BINARY_CACHE, BINARY_DOWNLOAD, BINARY_UPDATE):
                local_recipe_hash = self._client_cache.load_manifest(
                    package_ref.conan).summary_hash
                if local_recipe_hash != package_hash:
                    output.info("Outdated package!")
                    node.binary = BINARY_BUILD
                else:
                    output.info("Package is up to date")

        node.binary_remote = remote
Esempio n. 30
0
    def install(self, reference, current_path, profile, remote=None,
                build_modes=None, filename=None, update=False,
                manifest_folder=None, manifest_verify=False, manifest_interactive=False,
                generators=None, no_imports=False):
        """ Fetch and build all dependencies for the given reference
        @param reference: ConanFileReference or path to user space conanfile
        @param current_path: where the output files will be saved
        @param remote: install only from that remote
        @param profile: Profile object with both the -s introduced options and profile readed values
        @param build_modes: List of build_modes specified
        @param filename: Optional filename of the conanfile
        @param update: Check for updated in the upstream remotes (and update)
        @param manifest_folder: Folder to install the manifests
        @param manifest_verify: Verify dependencies manifests against stored ones
        @param manifest_interactive: Install deps manifests in folder for later verify, asking user for confirmation
        @param generators: List of generators from command line
        @param no_imports: Install specified packages but avoid running imports
        """
        generators = generators or []
        manifest_manager = ManifestManager(manifest_folder, user_io=self._user_io,
                                           client_cache=self._client_cache,
                                           verify=manifest_verify,
                                           interactive=manifest_interactive) if manifest_folder else None
        remote_proxy = ConanProxy(self._client_cache, self._user_io, self._remote_manager, remote,
                                  update=update, check_updates=False, manifest_manager=manifest_manager)
        loader = ConanFileLoader(self._runner, self._client_cache.settings, profile)
        conanfile = self._get_conanfile_object(loader, reference, filename, current_path)
        graph_builder = self._get_graph_builder(loader, update, remote_proxy)
        deps_graph = graph_builder.load(conanfile)

        # This line is so the conaninfo stores the correct complete info
        conanfile.info.scope = profile.scopes

        registry = RemoteRegistry(self._client_cache.registry, self._user_io.out)

        Printer(self._user_io.out).print_graph(deps_graph, registry)

        try:
            if detected_os() != loader._settings.os:
                message = "Cross-platform from '%s' to '%s'" % (detected_os(), loader._settings.os)
                self._user_io.out.writeln(message, Color.BRIGHT_MAGENTA)
        except ConanException:  # Setting os doesn't exist
            pass

        build_mode = BuildMode(build_modes, self._user_io.out)
        build_requires = BuildRequires(loader, remote_proxy, self._user_io.out, self._client_cache,
                                       self._search_manager, profile.build_requires, current_path,
                                       build_mode)

        # Apply build_requires to consumer conanfile
        build_requires.install("", conanfile)
        installer = ConanInstaller(self._client_cache, self._user_io.out, remote_proxy,
                                   build_requires)

        installer.install(deps_graph, build_mode, current_path)
        build_mode.report_matches()

        prefix = "PROJECT" if not isinstance(reference, ConanFileReference) else str(reference)
        output = ScopedOutput(prefix, self._user_io.out)

        # Write generators
        tmp = list(conanfile.generators)  # Add the command line specified generators
        tmp.extend(generators)
        conanfile.generators = tmp
        write_generators(conanfile, current_path, output)

        if not isinstance(reference, ConanFileReference):
            content = normalize(conanfile.info.dumps())
            save(os.path.join(current_path, CONANINFO), content)
            output.info("Generated %s" % CONANINFO)
            if not no_imports:
                run_imports(conanfile, current_path, output)
            installer.call_system_requirements(conanfile, output)

        if manifest_manager:
            manifest_manager.print_log()