def package(self): """Generate the info txt files and calls the conanfile package method. """ # FIXME: Is weak to assign here the recipe_hash manifest = self._client_cache.load_manifest(self._conan_ref) self._conan_file.info.recipe_hash = manifest.summary_hash # Creating ***info.txt files save(os.path.join(self.build_folder, CONANINFO), self._conan_file.info.dumps()) self._out.info("Generated %s" % CONANINFO) save(os.path.join(self.build_folder, BUILD_INFO), TXTGenerator(self._conan_file).content) self._out.info("Generated %s" % BUILD_INFO) os.chdir(self.build_folder) if getattr(self._conan_file, 'no_copy_source', False): source_folder = self.source_folder else: source_folder = self.build_folder with get_env_context_manager(self._conan_file): install_folder = self.build_folder # While installing, the infos goes to build folder create_package(self._conan_file, source_folder, self.build_folder, self.package_folder, install_folder, self._out) if get_env("CONAN_READ_ONLY_CACHE", False): make_read_only(self.package_folder)
def _get_recipe_build_requires(conanfile): conanfile.build_requires = _RecipeBuildRequires(conanfile) if hasattr(conanfile, "build_requirements"): with get_env_context_manager(conanfile): with conanfile_exception_formatter(str(conanfile), "build_requirements"): conanfile.build_requirements() return conanfile.build_requires
def _config_node(self, node, down_reqs, down_ref, down_options): """ update settings and option in the current ConanFile, computing actual requirement values, cause they can be overriden by downstream requires param settings: dict of settings values => {"os": "windows"} """ try: conanfile, conanref = node.conanfile, node.conan_ref # Avoid extra time manipulating the sys.path for python with get_env_context_manager(conanfile, without_python=True): if hasattr(conanfile, "config"): if not conanref: output = ScopedOutput(str("PROJECT"), self._output) output.warn("config() has been deprecated." " Use config_options and configure") with conanfile_exception_formatter(str(conanfile), "config"): conanfile.config() with conanfile_exception_formatter(str(conanfile), "config_options"): conanfile.config_options() conanfile.options.propagate_upstream(down_options, down_ref, conanref) if hasattr(conanfile, "config"): with conanfile_exception_formatter(str(conanfile), "config"): conanfile.config() with conanfile_exception_formatter(str(conanfile), "configure"): conanfile.configure() conanfile.settings.validate() # All has to be ok! conanfile.options.validate() # Update requirements (overwrites), computing new upstream if hasattr(conanfile, "requirements"): # If re-evaluating the recipe, in a diamond graph, with different options, # it could happen that one execution path of requirements() defines a package # and another one a different package raising Duplicate dependency error # Or the two consecutive calls, adding 2 different dependencies for the two paths # So it is necessary to save the "requires" state and restore it before a second # execution of requirements(). It is a shallow copy, if first iteration is # RequireResolve'd or overridden, the inner requirements are modified if not hasattr(conanfile, "_original_requires"): conanfile._original_requires = conanfile.requires.copy() else: conanfile.requires = conanfile._original_requires.copy() with conanfile_exception_formatter(str(conanfile), "requirements"): conanfile.requirements() new_options = conanfile.options.deps_package_values new_down_reqs = conanfile.requires.update(down_reqs, self._output, conanref, down_ref) except ConanExceptionInUserConanfileMethod: raise except ConanException as e: raise ConanException("%s: %s" % (conanref or "Conanfile", str(e))) except Exception as e: raise ConanException(e) return new_down_reqs, new_options
def build(self, conanfile_path, source_folder, build_folder, package_folder, install_folder, test=False, should_configure=True, should_build=True, should_install=True): """ Call to build() method saved on the conanfile.py param conanfile_path: path to a conanfile.py """ logger.debug("Building in %s" % build_folder) logger.debug("Conanfile in %s" % conanfile_path) try: # Append env_vars to execution environment and clear when block code ends output = ScopedOutput(("%s (test package)" % test) if test else "Project", self._user_io.out) conan_file = self._load_consumer_conanfile(conanfile_path, install_folder, output, deps_info_required=True) except NotFoundException: # TODO: Auto generate conanfile from requirements file raise ConanException("'%s' file is needed for build.\n" "Create a '%s' and move manually the " "requirements and generators from '%s' file" % (CONANFILE, CONANFILE, CONANFILE_TXT)) if test: try: conan_file.requires.add(test) except ConanException: pass conan_file.should_configure = should_configure conan_file.should_build = should_build conan_file.should_install = should_install try: mkdir(build_folder) os.chdir(build_folder) conan_file.build_folder = build_folder conan_file.source_folder = source_folder conan_file.package_folder = package_folder conan_file.install_folder = install_folder with get_env_context_manager(conan_file): output.highlight("Running build()") with conanfile_exception_formatter(str(conan_file), "build"): conan_file.build() if test: output.highlight("Running test()") with conanfile_exception_formatter(str(conan_file), "test"): conan_file.test() except ConanException: raise # Raise but not let to reach the Exception except (not print traceback) except Exception: import traceback trace = traceback.format_exc().split('\n') raise ConanException("Unable to build it successfully\n%s" % '\n'.join(trace[3:]))
def run_imports(conanfile, dest_folder, output): if not hasattr(conanfile, "imports"): return [] file_importer = _FileImporter(conanfile, dest_folder) conanfile.copy = file_importer conanfile.imports_folder = dest_folder with get_env_context_manager(conanfile): with tools.chdir(dest_folder): conanfile.imports() copied_files = file_importer.copied_files _make_files_writable(copied_files) import_output = ScopedOutput("%s imports()" % output.scope, output) _report_save_manifest(copied_files, import_output, dest_folder, IMPORTS_MANIFESTS) return copied_files
def config_source_local(dest_dir, conan_file, output): output.info('Configuring sources in %s' % dest_dir) conan_file.source_folder = dest_dir with tools.chdir(dest_dir): try: with conanfile_exception_formatter(str(conan_file), "source"): with get_env_context_manager(conan_file): conan_file.build_folder = None conan_file.package_folder = None conan_file.source() except ConanExceptionInUserConanfileMethod: raise except Exception as e: raise ConanException(e)
def _get_cmake_definitions(self): """ Detect all definitions conan sends to cmake by command line and convert them to cmake commands. Removes the CONAN_EXPORTED definition, so that users may check if conan has been invoked or not. :return: string to print into a cmake file """ with get_env_context_manager(self.conanfile): ret = [] build_type = self.conanfile.settings.get_safe("build_type") generator = get_generator(self.conanfile.settings) def_builder = CMakeDefinitionsBuilder(self.conanfile, generator=generator, forced_build_type=build_type) cmake_version = self.get_version() definitions = def_builder.get_definitions(cmake_version) if "CONAN_EXPORTED" in definitions: del definitions["CONAN_EXPORTED"] for name, value in definitions.items(): value = _cmake_escape_backslash(value) ret.append("set({name} {value})".format(name=name, value=value)) return os.linesep.join(ret)
def _get_cmake_environment_setters(self): """ Detect all environment changes made by conan and convert them to cmake commands :return: List of lines to print into a cmake file """ old_env = dict(os.environ) with get_env_context_manager(self.conanfile): ret = ["\t\t\"environmentVariables\": {"] for name, value in self.conanfile.env.items(): if isinstance(value, list): if name in old_env: value = str(get_env(name)).replace( old_env[name], "${{env:{name}}}").format(name=name) else: value = str(value) value = _cmake_escape_backslash(value) ret.append("\t\t\t\"{name}\": \"{value}\"".format(name=name, value=value)) ret[1:-1] = [line + "," for line in ret[1:-1]] return ret
def _run_source(conanfile, conanfile_path, src_folder, hook_manager, reference, cache, get_sources_from_exports): """Execute the source core functionality, both for local cache and user space, in order: - Calling pre_source hook - Getting sources from SCM - Getting sources from exported folders in the local cache - Clean potential TGZ and other files in the local cache - Executing the recipe source() method - Calling post_source hook """ conanfile.source_folder = src_folder conanfile.build_folder = None conanfile.package_folder = None with tools.chdir(src_folder): try: with get_env_context_manager(conanfile): hook_manager.execute("pre_source", conanfile=conanfile, conanfile_path=conanfile_path, reference=reference) output = conanfile.output output.info('Configuring sources in %s' % src_folder) get_sources_from_exports() if cache: _clean_source_folder( src_folder) # TODO: Why is it needed in cache? with conanfile_exception_formatter(conanfile.display_name, "source"): conanfile.source() hook_manager.execute("post_source", conanfile=conanfile, conanfile_path=conanfile_path, reference=reference) except ConanExceptionInUserConanfileMethod: raise except Exception as e: raise ConanException(e)
def config_source_local(dest_dir, conanfile, conanfile_folder, output): output.info('Configuring sources in %s' % dest_dir) conanfile.source_folder = dest_dir with tools.chdir(dest_dir): try: with conanfile_exception_formatter(str(conanfile), "source"): with get_env_context_manager(conanfile): conanfile.build_folder = None conanfile.package_folder = None scm_data = get_scm_data(conanfile) if scm_data: dest_dir = os.path.join(dest_dir, scm_data.subfolder) capture = scm_data.capture_origin or scm_data.capture_revision local_sources_path = conanfile_folder if capture else None _fetch_scm(scm_data, dest_dir, local_sources_path, output) conanfile.source() except ConanExceptionInUserConanfileMethod: raise except Exception as e: raise ConanException(e)
def _config_node(node, down_ref, down_options): """ update settings and option in the current ConanFile, computing actual requirement values, cause they can be overridden by downstream requires param settings: dict of settings values => {"os": "windows"} """ conanfile, ref = node.conanfile, node.ref try: run_configure_method(conanfile, down_options, down_ref, ref) with get_env_context_manager(conanfile, without_python=True): # Update requirements (overwrites), computing new upstream if hasattr(conanfile, "requirements"): # If re-evaluating the recipe, in a diamond graph, with different options, # it could happen that one execution path of requirements() defines a package # and another one a different package raising Duplicate dependency error # Or the two consecutive calls, adding 2 different dependencies for the 2 paths # So it is necessary to save the "requires" state and restore it before a second # execution of requirements(). It is a shallow copy, if first iteration is # RequireResolve'd or overridden, the inner requirements are modified if not hasattr(conanfile, "_conan_original_requires"): conanfile._conan_original_requires = conanfile.requires.copy( ) else: conanfile.requires = conanfile._conan_original_requires.copy( ) with conanfile_exception_formatter(str(conanfile), "requirements"): conanfile.requirements() new_options = conanfile.options.deps_package_values except ConanExceptionInUserConanfileMethod: raise except ConanException as e: raise ConanException("%s: %s" % (ref or "Conanfile", str(e))) except Exception as e: raise ConanException(e) return new_options
def package(self): """Generate the info txt files and calls the conanfile package method. """ # FIXME: Is weak to assign here the recipe_hash manifest = self._client_cache.load_manifest(self._conan_ref) self._conan_file.info.recipe_hash = manifest.summary_hash # Creating ***info.txt files save(os.path.join(self.build_folder, CONANINFO), self._conan_file.info.dumps()) self._out.info("Generated %s" % CONANINFO) save(os.path.join(self.build_folder, BUILD_INFO), TXTGenerator(self._conan_file).content) self._out.info("Generated %s" % BUILD_INFO) os.chdir(self.build_folder) if getattr(self._conan_file, 'no_copy_source', False): source_folder = self.source_folder else: source_folder = self.build_folder with get_env_context_manager(self._conan_file): install_folder = self.build_folder # While installing, the infos goes to build folder pkg_id = self._conan_file.info.package_id() conanfile_path = self._client_cache.conanfile(self._conan_ref) create_package(self._conan_file, pkg_id, source_folder, self.build_folder, self.package_folder, install_folder, self._out, self._hook_manager, conanfile_path, self._conan_ref) p_hash = self._client_cache.package_summary_hash(self._package_reference) p_id = self._package_reference.package_id with self._client_cache.update_metadata(self._conan_ref) as metadata: metadata.packages[p_id].revision = p_hash metadata.packages[p_id].recipe_revision = self._conan_ref.revision if get_env("CONAN_READ_ONLY_CACHE", False): make_read_only(self.package_folder)
def run_configure_method(conanfile, down_options, down_ref, ref): """ Run all the config-related functions for the given conanfile object """ # Avoid extra time manipulating the sys.path for python with get_env_context_manager(conanfile, without_python=True): if hasattr(conanfile, "config"): conan_v2_error("config() has been deprecated. Use config_options() and configure()") with conanfile_exception_formatter(str(conanfile), "config"): conanfile.config() with conanfile_exception_formatter(str(conanfile), "config_options"): conanfile.config_options() conanfile.options.propagate_upstream(down_options, down_ref, ref) if hasattr(conanfile, "config"): with conanfile_exception_formatter(str(conanfile), "config"): conanfile.config() with conanfile_exception_formatter(str(conanfile), "configure"): conanfile.configure() conanfile.settings.validate() # All has to be ok! conanfile.options.validate() # Recipe provides its own name if nothing else is defined conanfile.provides = make_tuple(conanfile.provides or conanfile.name) if conanfile.deprecated: from six import string_types message = "Recipe '%s' is deprecated" % conanfile.display_name if isinstance(conanfile.deprecated, string_types): message += " in favor of '%s'" % conanfile.deprecated message += ". Please, consider changing your requirements." conanfile.output.warn(message) # Once the node is configured call the layout() if hasattr(conanfile, "layout"): conanfile.layout()
def run_deploy(conanfile, install_folder, output): deploy_output = ScopedOutput("%s deploy()" % output.scope, output) file_importer = _FileImporter(conanfile, install_folder) package_copied = set() # This is necessary to capture FileCopier full destination paths # Maybe could be improved in FileCopier def file_copier(*args, **kwargs): file_copy = FileCopier(conanfile.package_folder, install_folder) copied = file_copy(*args, **kwargs) _make_files_writable(copied) package_copied.update(copied) conanfile.copy_deps = file_importer conanfile.copy = file_copier conanfile.install_folder = install_folder with get_env_context_manager(conanfile): with tools.chdir(install_folder): conanfile.deploy() copied_files = file_importer.copied_files copied_files.update(package_copied) _report_save_manifest(copied_files, deploy_output, install_folder, "deploy_manifest.txt")
def run_deploy(conanfile, install_folder): deploy_output = ScopedOutput("%s deploy()" % conanfile.display_name, conanfile.output) file_importer = _FileImporter(conanfile, install_folder) package_copied = set() # This is necessary to capture FileCopier full destination paths # Maybe could be improved in FileCopier def file_copier(*args, **kwargs): file_copy = FileCopier(conanfile.package_folder, install_folder) copied = file_copy(*args, **kwargs) _make_files_writable(copied) package_copied.update(copied) conanfile.copy_deps = file_importer conanfile.copy = file_copier conanfile.install_folder = install_folder with get_env_context_manager(conanfile): with tools.chdir(install_folder): conanfile.deploy() copied_files = file_importer.copied_files copied_files.update(package_copied) _report_save_manifest(copied_files, deploy_output, install_folder, "deploy_manifest.txt")
def load_consumer_conanfile(self, conanfile_path, info_folder, deps_info_required=False, test=None): """loads a conanfile for local flow: source, imports, package, build """ try: graph_info = GraphInfo.load(info_folder) except IOError: # Only if file is missing # This is very dirty, should be removed for Conan 2.0 (source() method only) profile = self._cache.default_profile profile.process_settings(self._cache) name, version, user, channel = None, None, None, None else: name, version, user, channel, _ = graph_info.root profile = graph_info.profile profile.process_settings(self._cache, preprocess=False) # This is the hack of recovering the options from the graph_info profile.options.update(graph_info.options) processed_profile = ProcessedProfile(profile, None) if conanfile_path.endswith(".py"): conanfile = self._loader.load_consumer(conanfile_path, processed_profile=processed_profile, test=test, name=name, version=version, user=user, channel=channel) with get_env_context_manager(conanfile, without_python=True): with conanfile_exception_formatter(str(conanfile), "config_options"): conanfile.config_options() with conanfile_exception_formatter(str(conanfile), "configure"): conanfile.configure() conanfile.settings.validate() # All has to be ok! conanfile.options.validate() else: conanfile = self._loader.load_conanfile_txt(conanfile_path, processed_profile) load_deps_info(info_folder, conanfile, required=deps_info_required) return conanfile
def export_pkg(cache, graph_manager, hook_manager, recorder, output, ref, source_folder, build_folder, package_folder, install_folder, graph_info, force): conan_file_path = cache.conanfile(ref) if not os.path.exists(conan_file_path): raise ConanException("Package recipe '%s' does not exist" % str(ref)) # The graph has to be loaded with build_mode=[ref.name], so that node is not tried # to be downloaded from remotes deps_graph, _ = graph_manager.load_graph(ref, None, graph_info=graph_info, build_mode=[ref.name], check_updates=False, update=False, remote_name=None, recorder=recorder, apply_build_requires=False) # this is a bit tricky, but works. The root (virtual), has only 1 neighbor, # which is the exported pkg nodes = deps_graph.root.neighbors() conanfile = nodes[0].conanfile from conans.client.conan_api import existing_info_files if install_folder and existing_info_files(install_folder): load_deps_info(install_folder, conanfile, required=True) package_id = nodes[0].package_id output.info("Packaging to %s" % package_id) pref = PackageReference(ref, package_id) dest_package_folder = cache.package(pref, short_paths=conanfile.short_paths) if os.path.exists(dest_package_folder): if force: rmdir(dest_package_folder) else: raise ConanException( "Package already exists. Please use --force, -f to " "overwrite it") recipe_hash = cache.package_layout(ref).recipe_manifest().summary_hash conanfile.info.recipe_hash = recipe_hash conanfile.develop = True if package_folder: packager.export_pkg(conanfile, package_id, package_folder, dest_package_folder, hook_manager, conan_file_path, ref) else: with get_env_context_manager(conanfile): packager.create_package(conanfile, package_id, source_folder, build_folder, dest_package_folder, install_folder, hook_manager, conan_file_path, ref, local=True) readed_manifest = FileTreeManifest.load(dest_package_folder) pref = PackageReference(pref.ref, pref.id, readed_manifest.summary_hash) output.info("Package revision %s" % pref.revision) with cache.package_layout(ref).update_metadata() as metadata: metadata.packages[package_id].revision = pref.revision metadata.packages[ package_id].recipe_revision = metadata.recipe.revision recorder.package_exported(pref)
def config_source(export_folder, export_source_folder, local_sources_path, src_folder, conanfile, output, conanfile_path, reference, hook_manager, client_cache): """ creates src folder and retrieve, calling source() from conanfile the necessary source code """ def remove_source(raise_error=True): output.warn("This can take a while for big packages") try: rmdir(src_folder) except BaseException as e_rm: set_dirty(src_folder) msg = str(e_rm) if six.PY2: msg = str(e_rm).decode( "latin1") # Windows prints some chars in latin1 output.error("Unable to remove source folder %s\n%s" % (src_folder, msg)) output.warn("**** Please delete it manually ****") if raise_error or isinstance(e_rm, KeyboardInterrupt): raise ConanException("Unable to remove source folder") if is_dirty(src_folder): output.warn("Trying to remove corrupted source folder") remove_source() elif conanfile.build_policy_always: output.warn( "Detected build_policy 'always', trying to remove source folder") remove_source() elif local_sources_path and os.path.exists(local_sources_path): output.warn( "Detected 'scm' auto in conanfile, trying to remove source folder") remove_source() if not os.path.exists(src_folder): set_dirty(src_folder) mkdir(src_folder) os.chdir(src_folder) conanfile.source_folder = src_folder try: with conanfile_exception_formatter(str(conanfile), "source"): with get_env_context_manager(conanfile): conanfile.build_folder = None conanfile.package_folder = None hook_manager.execute("pre_source", conanfile=conanfile, conanfile_path=conanfile_path, reference=reference) output.info('Configuring sources in %s' % src_folder) scm_data = get_scm_data(conanfile) if scm_data: dest_dir = os.path.normpath( os.path.join(src_folder, scm_data.subfolder)) captured = local_sources_path and os.path.exists( local_sources_path) local_sources_path = local_sources_path if captured else None _fetch_scm(scm_data, dest_dir, local_sources_path, output) # Files from python requires are obtained before the self files from conans.client.cmd.export import export_source for python_require in conanfile.python_requires: src = client_cache.export_sources( python_require.conan_ref) export_source(conanfile, src, src_folder, output) # so self exported files have precedence over python_requires ones merge_directories(export_folder, src_folder) # Now move the export-sources to the right location merge_directories(export_source_folder, src_folder) _clean_source_folder(src_folder) try: shutil.rmtree(os.path.join(src_folder, "__pycache__")) except OSError: pass conanfile.source() hook_manager.execute("post_source", conanfile=conanfile, conanfile_path=conanfile_path, reference=reference) clean_dirty(src_folder) # Everything went well, remove DIRTY flag except Exception as e: os.chdir(export_folder) # in case source() fails (user error, typically), remove the src_folder # and raise to interrupt any other processes (build, package) output.warn("Trying to remove corrupted source folder") remove_source(raise_error=False) if isinstance(e, ConanExceptionInUserConanfileMethod): raise e raise ConanException(e)
def build(self, conanfile_path, source_folder, build_folder, package_folder, install_folder, test=False, should_configure=True, should_build=True, should_install=True, should_test=True): """ Call to build() method saved on the conanfile.py param conanfile_path: path to a conanfile.py """ logger.debug("Building in %s" % build_folder) logger.debug("Conanfile in %s" % conanfile_path) try: # Append env_vars to execution environment and clear when block code ends output = ScopedOutput( ("%s (test package)" % test) if test else "Project", self._user_io.out) conan_file = self._graph_manager.load_consumer_conanfile( conanfile_path, install_folder, output, deps_info_required=True) except NotFoundException: # TODO: Auto generate conanfile from requirements file raise ConanException("'%s' file is needed for build.\n" "Create a '%s' and move manually the " "requirements and generators from '%s' file" % (CONANFILE, CONANFILE, CONANFILE_TXT)) if test: try: conan_file.requires.add(test) except ConanException: pass conan_file.should_configure = should_configure conan_file.should_build = should_build conan_file.should_install = should_install conan_file.should_test = should_test try: mkdir(build_folder) os.chdir(build_folder) conan_file.build_folder = build_folder conan_file.source_folder = source_folder conan_file.package_folder = package_folder conan_file.install_folder = install_folder with get_env_context_manager(conan_file): output.highlight("Running build()") with conanfile_exception_formatter(str(conan_file), "build"): conan_file.build() if test: output.highlight("Running test()") with conanfile_exception_formatter(str(conan_file), "test"): conan_file.test() except ConanException: raise # Raise but not let to reach the Exception except (not print traceback) except Exception: import traceback trace = traceback.format_exc().split('\n') raise ConanException("Unable to build it successfully\n%s" % '\n'.join(trace[3:]))
def _config_node(self, node, down_reqs, down_ref, down_options): """ update settings and option in the current ConanFile, computing actual requirement values, cause they can be overridden by downstream requires param settings: dict of settings values => {"os": "windows"} """ try: conanfile, conanref = node.conanfile, node.conan_ref # Avoid extra time manipulating the sys.path for python with get_env_context_manager(conanfile, without_python=True): if hasattr(conanfile, "config"): if not conanref: output = ScopedOutput(str("PROJECT"), self._output) output.warn("config() has been deprecated." " Use config_options and configure") with conanfile_exception_formatter(str(conanfile), "config"): conanfile.config() with conanfile_exception_formatter(str(conanfile), "config_options"): conanfile.config_options() conanfile.options.propagate_upstream(down_options, down_ref, conanref) if hasattr(conanfile, "config"): with conanfile_exception_formatter(str(conanfile), "config"): conanfile.config() with conanfile_exception_formatter(str(conanfile), "configure"): conanfile.configure() conanfile.settings.validate() # All has to be ok! conanfile.options.validate() # Update requirements (overwrites), computing new upstream if hasattr(conanfile, "requirements"): # If re-evaluating the recipe, in a diamond graph, with different options, # it could happen that one execution path of requirements() defines a package # and another one a different package raising Duplicate dependency error # Or the two consecutive calls, adding 2 different dependencies for the two paths # So it is necessary to save the "requires" state and restore it before a second # execution of requirements(). It is a shallow copy, if first iteration is # RequireResolve'd or overridden, the inner requirements are modified if not hasattr(conanfile, "_original_requires"): conanfile._original_requires = conanfile.requires.copy( ) else: conanfile.requires = conanfile._original_requires.copy( ) with conanfile_exception_formatter(str(conanfile), "requirements"): conanfile.requirements() new_options = conanfile.options.deps_package_values new_down_reqs = conanfile.requires.update( down_reqs, self._output, conanref, down_ref) except ConanExceptionInUserConanfileMethod: raise except ConanException as e: raise ConanException("%s: %s" % (conanref or "Conanfile", str(e))) except Exception as e: raise ConanException(e) return new_down_reqs, new_options
def config_source(export_folder, export_source_folder, local_sources_path, src_folder, conan_file, output, force=False): """ creates src folder and retrieve, calling source() from conanfile the necessary source code """ def remove_source(raise_error=True): output.warn("This can take a while for big packages") try: rmdir(src_folder) except BaseException as e_rm: set_dirty(src_folder) msg = str(e_rm) if six.PY2: msg = str(e_rm).decode( "latin1") # Windows prints some chars in latin1 output.error("Unable to remove source folder %s\n%s" % (src_folder, msg)) output.warn("**** Please delete it manually ****") if raise_error or isinstance(e_rm, KeyboardInterrupt): raise ConanException("Unable to remove source folder") if force: output.warn("Forced removal of source folder") remove_source() elif is_dirty(src_folder): output.warn("Trying to remove corrupted source folder") remove_source() elif conan_file.build_policy_always: output.warn( "Detected build_policy 'always', trying to remove source folder") remove_source() if not os.path.exists(src_folder): output.info('Configuring sources in %s' % src_folder) shutil.copytree(export_folder, src_folder, symlinks=True) # Now move the export-sources to the right location merge_directories(export_source_folder, src_folder) _clean_source_folder(src_folder) try: shutil.rmtree(os.path.join(src_folder, "__pycache__")) except OSError: pass set_dirty(src_folder) os.chdir(src_folder) conan_file.source_folder = src_folder try: with get_env_context_manager(conan_file): with conanfile_exception_formatter(str(conan_file), "source"): conan_file.build_folder = None conan_file.package_folder = None scm = get_scm(conan_file, src_folder) if scm: # scm.capture_origin before exporting if local_sources_path and os.path.exists( local_sources_path): output.info("Getting sources from folder: %s" % local_sources_path) merge_directories(local_sources_path, src_folder) _clean_source_folder(src_folder) else: output.info("Getting sources from url: '%s'" % scm.url) scm.clone() scm.checkout() conan_file.source() clean_dirty(src_folder) # Everything went well, remove DIRTY flag except Exception as e: os.chdir(export_folder) # in case source() fails (user error, typically), remove the src_folder # and raise to interrupt any other processes (build, package) output.warn("Trying to remove corrupted source folder") remove_source(raise_error=False) if isinstance(e, ConanExceptionInUserConanfileMethod): raise e raise ConanException(e)
def cmd_build(app, conanfile_path, base_path, source_folder, build_folder, package_folder, install_folder, test=False, should_configure=True, should_build=True, should_install=True, should_test=True): """ Call to build() method saved on the conanfile.py param conanfile_path: path to a conanfile.py """ logger.debug("BUILD: folder '%s'" % build_folder) logger.debug("BUILD: Conanfile at '%s'" % conanfile_path) try: conan_file = app.graph_manager.load_consumer_conanfile( conanfile_path, install_folder, deps_info_required=True, test=test) except NotFoundException: # TODO: Auto generate conanfile from requirements file raise ConanException("'%s' file is needed for build.\n" "Create a '%s' and move manually the " "requirements and generators from '%s' file" % (CONANFILE, CONANFILE, CONANFILE_TXT)) if test: try: conan_file.requires.add_ref(test) except ConanException: pass conan_file.should_configure = should_configure conan_file.should_build = should_build conan_file.should_install = should_install conan_file.should_test = should_test try: # FIXME: Conan 2.0 all these build_folder, source_folder will disappear # Only base_path and conanfile_path will remain if hasattr(conan_file, "layout"): conanfile_folder = os.path.dirname(conanfile_path) conan_file.folders.set_base_build(conanfile_folder) conan_file.folders.set_base_source(conanfile_folder) conan_file.folders.set_base_package(conanfile_folder) conan_file.folders.set_base_generators(conanfile_folder) conan_file.folders.set_base_install(conanfile_folder) else: conan_file.folders.set_base_build(build_folder) conan_file.folders.set_base_source(source_folder) conan_file.folders.set_base_package(package_folder) conan_file.folders.set_base_generators(base_path) conan_file.folders.set_base_install(install_folder) mkdir(conan_file.build_folder) with chdir(conan_file.build_folder): run_build_method(conan_file, app.hook_manager, conanfile_path=conanfile_path) if test: with get_env_context_manager(conan_file): conan_file.output.highlight("Running test()") with conanfile_exception_formatter(str(conan_file), "test"): with chdir(conan_file.build_folder): conan_file.test() except ConanException: raise # Raise but not let to reach the Exception except (not print traceback) except Exception: import traceback trace = traceback.format_exc().split('\n') raise ConanException("Unable to build it successfully\n%s" % '\n'.join(trace[3:]))
def export_pkg(app, recorder, full_ref, source_folder, build_folder, package_folder, install_folder, graph_info, force, remotes): ref = full_ref.copy_clear_rev() cache, output, hook_manager = app.cache, app.out, app.hook_manager graph_manager = app.graph_manager conan_file_path = cache.package_layout(ref).conanfile() if not os.path.exists(conan_file_path): raise ConanException("Package recipe '%s' does not exist" % str(ref)) # The graph has to be loaded with build_mode=[ref.name], so that node is not tried # to be downloaded from remotes deps_graph, _ = graph_manager.load_graph(ref, None, graph_info=graph_info, build_mode=[ref.name], check_updates=False, update=False, remotes=remotes, recorder=recorder, apply_build_requires=False) # this is a bit tricky, but works. The root (virtual), has only 1 neighbor, # which is the exported pkg nodes = deps_graph.root.neighbors() conanfile = nodes[0].conanfile from conans.client.conan_api import existing_info_files if install_folder and existing_info_files(install_folder): load_deps_info(install_folder, conanfile, required=True) package_id = nodes[0].package_id output.info("Packaging to %s" % package_id) pref = PackageReference(ref, package_id) layout = cache.package_layout(ref, short_paths=conanfile.short_paths) dest_package_folder = layout.package(pref) if os.path.exists(dest_package_folder): if force: rmdir(dest_package_folder) else: raise ConanException( "Package already exists. Please use --force, -f to " "overwrite it") recipe_hash = layout.recipe_manifest().summary_hash conanfile.info.recipe_hash = recipe_hash conanfile.develop = True if package_folder: prev = packager.export_pkg(conanfile, package_id, package_folder, dest_package_folder, hook_manager, conan_file_path, ref) else: with get_env_context_manager(conanfile): prev = packager.create_package(conanfile, package_id, source_folder, build_folder, dest_package_folder, install_folder, hook_manager, conan_file_path, ref, local=True) packager.update_package_metadata(prev, layout, package_id, full_ref.revision) pref = PackageReference(pref.ref, pref.id, prev) if graph_info.graph_lock: # after the package has been created we need to update the node PREV nodes[0].prev = pref.revision graph_info.graph_lock.update_check_graph(deps_graph, output) recorder.package_exported(pref)
def config_source(export_folder, export_source_folder, src_folder, conan_file, output, force=False): """ creates src folder and retrieve, calling source() from conanfile the necessary source code """ def remove_source(raise_error=True): output.warn("This can take a while for big packages") try: rmdir(src_folder) except BaseException as e_rm: set_dirty(src_folder) msg = str(e_rm) if six.PY2: msg = str(e_rm).decode("latin1") # Windows prints some chars in latin1 output.error("Unable to remove source folder %s\n%s" % (src_folder, msg)) output.warn("**** Please delete it manually ****") if raise_error or isinstance(e_rm, KeyboardInterrupt): raise ConanException("Unable to remove source folder") if force: output.warn("Forced removal of source folder") remove_source() elif is_dirty(src_folder): output.warn("Trying to remove corrupted source folder") remove_source() elif conan_file.build_policy_always: output.warn("Detected build_policy 'always', trying to remove source folder") remove_source() if not os.path.exists(src_folder): output.info('Configuring sources in %s' % src_folder) shutil.copytree(export_folder, src_folder, symlinks=True) # Now move the export-sources to the right location merge_directories(export_source_folder, src_folder) for f in (EXPORT_TGZ_NAME, EXPORT_SOURCES_TGZ_NAME, CONANFILE+"c", CONANFILE+"o", CONANFILE, CONAN_MANIFEST): try: os.remove(os.path.join(src_folder, f)) except OSError: pass try: shutil.rmtree(os.path.join(src_folder, "__pycache__")) except OSError: pass set_dirty(src_folder) os.chdir(src_folder) conan_file.source_folder = src_folder try: with get_env_context_manager(conan_file): with conanfile_exception_formatter(str(conan_file), "source"): conan_file.build_folder = None conan_file.package_folder = None conan_file.source() clean_dirty(src_folder) # Everything went well, remove DIRTY flag except Exception as e: os.chdir(export_folder) # in case source() fails (user error, typically), remove the src_folder # and raise to interrupt any other processes (build, package) output.warn("Trying to remove corrupted source folder") remove_source(raise_error=False) if isinstance(e, ConanExceptionInUserConanfileMethod): raise e raise ConanException(e)
def build(self): """Calls the conanfile's build method""" if self._skip_build: return with get_env_context_manager(self._conan_file): self._build_package()
def build(self): """Calls the conanfile's build method""" if self._skip_build: return with get_env_context_manager(self._conan_file): self._build_package()
def cmd_build(app, conanfile_path, source_folder, build_folder, package_folder, install_folder, test=False, should_configure=True, should_build=True, should_install=True, should_test=True): """ Call to build() method saved on the conanfile.py param conanfile_path: path to a conanfile.py """ logger.debug("BUILD: folder '%s'" % build_folder) logger.debug("BUILD: Conanfile at '%s'" % conanfile_path) try: conan_file = app.graph_manager.load_consumer_conanfile( conanfile_path, install_folder, deps_info_required=True, test=test) except NotFoundException: # TODO: Auto generate conanfile from requirements file raise ConanException("'%s' file is needed for build.\n" "Create a '%s' and move manually the " "requirements and generators from '%s' file" % (CONANFILE, CONANFILE, CONANFILE_TXT)) if test: try: conan_file.requires.add_ref(test) except ConanException: pass conan_file.should_configure = should_configure conan_file.should_build = should_build conan_file.should_install = should_install conan_file.should_test = should_test try: mkdir(build_folder) os.chdir(build_folder) conan_file.build_folder = build_folder conan_file.source_folder = source_folder conan_file.package_folder = package_folder conan_file.install_folder = install_folder app.hook_manager.execute("pre_build", conanfile=conan_file, conanfile_path=conanfile_path) with get_env_context_manager(conan_file): conan_file.output.highlight("Running build()") with conanfile_exception_formatter(str(conan_file), "build"): conan_file.build() app.hook_manager.execute("post_build", conanfile=conan_file, conanfile_path=conanfile_path) if test: conan_file.output.highlight("Running test()") with conanfile_exception_formatter(str(conan_file), "test"): conan_file.test() except ConanException: raise # Raise but not let to reach the Exception except (not print traceback) except Exception: import traceback trace = traceback.format_exc().split('\n') raise ConanException("Unable to build it successfully\n%s" % '\n'.join(trace[3:]))