def _config_node(self, conanfile, conanref, down_reqs, down_ref, down_options): """ update settings and option in the current ConanFile, computing actual requirement values, cause they can be overriden by downstream requires param settings: dict of settings values => {"os": "windows"} """ try: conanfile.requires.output = self._output if hasattr(conanfile, "config"): if not conanref: self._output.warn("config() has been deprecated." " Use config_options and configure") conanfile.config() conanfile.config_options() conanfile.options.propagate_upstream(down_options, down_ref, conanref, self._output) if hasattr(conanfile, "config"): conanfile.config() conanfile.configure() conanfile.settings.validate() # All has to be ok! conanfile.options.validate() # Update requirements (overwrites), computing new upstream conanfile.requirements() new_options = conanfile.options.values new_down_reqs = conanfile.requires.update(down_reqs, self._output, conanref, down_ref) except ConanException as e: raise ConanException("%s: %s" % (conanref or "Conanfile", str(e))) except Exception as e: msg = format_conanfile_exception(str(conanref or "Conanfile"), "config, config_options or configure", e) raise ConanException(msg) return new_down_reqs, new_options
def _package_info_conanfile(self, conan_ref, conan_file): # Once the node is build, execute package info, so it has access to the # package folder and artifacts try: conan_file.package_info() except Exception as e: msg = format_conanfile_exception(str(conan_ref), "package_info", e) raise ConanException(msg)
def _config_node(self, conanfile, conanref, down_reqs, down_ref, down_options): """ update settings and option in the current ConanFile, computing actual requirement values, cause they can be overriden by downstream requires param settings: dict of settings values => {"os": "windows"} """ try: if hasattr(conanfile, "config"): if not conanref: output = ScopedOutput(str("PROJECT"), self._output) output.warn("config() has been deprecated." " Use config_options and configure") conanfile.config() conanfile.config_options() conanfile.options.propagate_upstream(down_options, down_ref, conanref, self._output) if hasattr(conanfile, "config"): conanfile.config() 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() conanfile.requirements() new_options = conanfile.options.deps_package_values new_down_reqs = conanfile.requires.update(down_reqs, self._output, conanref, down_ref) except ConanException as e: raise ConanException("%s: %s" % (conanref or "Conanfile", str(e))) except Exception as e: msg = format_conanfile_exception( str(conanref or "Conanfile"), "config, config_options or configure", e) raise ConanException(msg) return new_down_reqs, new_options
def config_source(export_folder, src_folder, conan_file, output, force=False): """ creates src folder and retrieve, calling source() from conanfile the necessary source code """ dirty = os.path.join(src_folder, DIRTY_FILE) def remove_source(raise_error=True): output.warn("This can take a while for big packages") try: rmdir(src_folder) except BaseException as e_rm: save(dirty, "") # Creation of DIRTY flag msg = str(e_rm) if six.PY2: msg = str(e_rm).decode( "latin1") # Windows prints some chars in latin1 output.error("Unable to remove source folder %s\n%s" % (src_folder, msg)) output.warn("**** Please delete it manually ****") if raise_error or isinstance(e_rm, KeyboardInterrupt): raise ConanException("Unable to remove source folder") if force: output.warn("Forced removal of source folder") remove_source() elif os.path.exists(dirty): output.warn("Trying to remove dirty source folder") remove_source() elif conan_file.build_policy_always: output.warn( "Detected build_policy 'always', trying to remove source folder") remove_source() if not os.path.exists(src_folder): output.info('Configuring sources in %s' % src_folder) shutil.copytree(export_folder, src_folder) save(dirty, "") # Creation of DIRTY flag os.chdir(src_folder) try: conan_file.source() os.remove(dirty) # Everything went well, remove DIRTY flag except Exception as e: os.chdir(export_folder) # in case source() fails (user error, typically), remove the src_folder # and raise to interrupt any other processes (build, package) output.warn("Trying to remove dirty source folder") remove_source(raise_error=False) msg = format_conanfile_exception(output.scope, "source", e) raise ConanException(msg)
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 indpendent 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) # Now build each level, starting from the most independent one for level in nodes_by_level: for node in level: if node in skip_private_nodes: continue conan_ref, conan_file = node # Get deps_cpp_info from upstream nodes node_order = self._deps_graph.ordered_closure(node, flat) for n in node_order: conan_file.deps_cpp_info.update(n.conanfile.cpp_info, n.conan_ref) conan_file.deps_env_info.update(n.conanfile.env_info, n.conan_ref) # it is possible that the root conans # is not inside the storage but in a user folder, and thus its # treatment is different if conan_ref: logger.debug("Building node %s" % repr(conan_ref)) self._build_node(conan_ref, conan_file, build_mode) # Once the node is build, execute package info, so it has access to the # package folder and artifacts try: conan_file.package_info() except Exception as e: msg = format_conanfile_exception(str(conan_ref), "package_info", e) raise ConanException(msg)
def config_source(export_folder, src_folder, conan_file, output, force=False): """ creates src folder and retrieve, calling source() from conanfile the necessary source code """ dirty = os.path.join(src_folder, DIRTY_FILE) def remove_source(raise_error=True): output.warn("This can take a while for big packages") try: rmdir(src_folder) except BaseException as e_rm: save(dirty, "") # Creation of DIRTY flag msg = str(e_rm) if six.PY2: msg = str(e_rm).decode("latin1") # Windows prints some chars in latin1 output.error("Unable to remove source folder %s\n%s" % (src_folder, msg)) output.warn("**** Please delete it manually ****") if raise_error or isinstance(e_rm, KeyboardInterrupt): raise ConanException("Unable to remove source folder") if force: output.warn("Forced removal of source folder") remove_source() elif os.path.exists(dirty): output.warn("Trying to remove dirty source folder") remove_source() elif conan_file.build_policy_always: output.warn("Detected build_policy 'always', trying to remove source folder") remove_source() if not os.path.exists(src_folder): output.info('Configuring sources in %s' % src_folder) shutil.copytree(export_folder, src_folder) save(dirty, "") # Creation of DIRTY flag os.chdir(src_folder) try: conan_file.source() os.remove(dirty) # Everything went well, remove DIRTY flag except Exception as e: os.chdir(export_folder) # in case source() fails (user error, typically), remove the src_folder # and raise to interrupt any other processes (build, package) output.warn("Trying to remove dirty source folder") remove_source(raise_error=False) msg = format_conanfile_exception(output.scope, "source", e) raise ConanException(msg)
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 indpendent 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) # Now build each level, starting from the most independent one for level in nodes_by_level: for node in level: if node in skip_private_nodes: continue conan_ref, conan_file = node # Get deps_cpp_info from upstream nodes node_order = self._deps_graph.ordered_closure(node, flat) conan_file.cpp_info.deps = [n.conan_ref.name for n in node_order] for n in node_order: conan_file.deps_cpp_info.update(n.conanfile.cpp_info, n.conan_ref) conan_file.deps_env_info.update(n.conanfile.env_info, n.conan_ref) # it is possible that the root conans # is not inside the storage but in a user folder, and thus its # treatment is different if conan_ref: logger.debug("Building node %s" % repr(conan_ref)) self._build_node(conan_ref, conan_file, build_mode) # Once the node is build, execute package info, so it has access to the # package folder and artifacts try: conan_file.package_info() except Exception as e: msg = format_conanfile_exception(str(conan_ref), "package_info", e) raise ConanException(msg)
def config_source_local(export_folder, current_path, conan_file, output): output.info('Configuring sources in %s' % current_path) dirty = os.path.join(current_path, DIRTY_FILE) if os.path.exists(dirty): output.warn("Your previous source command failed") if current_path != export_folder: execute_export(conan_file, export_folder, current_path, output) save(dirty, "") # Creation of DIRTY flag try: with tools.environment_append(conan_file.env): conan_file.source() os.remove(dirty) # Everything went well, remove DIRTY flag except Exception as e: msg = format_conanfile_exception(output.scope, "source", e) raise ConanException(msg)
def create_package(conanfile, build_folder, package_folder, output, local=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)) conanfile.copy = FileCopier(build_folder, package_folder) def wrap(dst_folder): def new_method(pattern, src=""): conanfile.copy(pattern, dst_folder, src) return new_method 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: conanfile.package() package_output = ScopedOutput("%s package()" % output.scope, output) 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 ****") msg = format_conanfile_exception(output.scope, "package", e) raise ConanException(msg) _create_aux_files(build_folder, package_folder) output.success("Package '%s' created" % os.path.basename(package_folder))
def init_info_objects(deps_graph, paths): """ Made external so it is independent of installer and can called in testing too """ # Assign export root folders for node in deps_graph.nodes: conan_ref, conan_file = node if conan_ref: package_id = conan_file.info.package_id() package_reference = PackageReference(conan_ref, package_id) package_folder = paths.package(package_reference) conan_file.package_folder = package_folder conan_file.cpp_info = CppInfo(package_folder) conan_file.env_info = EnvInfo(package_folder) try: conan_file.package_info() except Exception as e: msg = format_conanfile_exception(str(conan_ref), "package_info", e) raise ConanException(msg)
def config_source_local(export_folder, current_path, conan_file, output): output.info('Configuring sources in %s' % current_path) dirty = os.path.join(current_path, DIRTY_FILE) if os.path.exists(dirty): output.warn("Your previous source command failed") if current_path != export_folder: for item in os.listdir(export_folder): origin = os.path.join(export_folder, item) if os.path.isdir(origin): shutil.copytree(origin, os.path.join(current_path, item)) else: shutil.copy2(origin, os.path.join(current_path, item)) save(dirty, "") # Creation of DIRTY flag try: conan_file.source() os.remove(dirty) # Everything went well, remove DIRTY flag except Exception as e: msg = format_conanfile_exception(output.scope, "source", e) raise ConanException(msg)
def config_source(export_folder, src_folder, conan_file, output, force=False): """ creates src folder and retrieve, calling source() from conanfile the necessary source code """ dirty = os.path.join(src_folder, DIRTY_FILE) def remove_source(raise_error=True): output.warn("This can take a while for big packages") try: rmdir(src_folder) except BaseException as e_rm: save(dirty, "") # Creation of DIRTY flag msg = str(e_rm) if six.PY2: msg = str(e_rm).decode( "latin1") # Windows prints some chars in latin1 output.error("Unable to remove source folder %s\n%s" % (src_folder, msg)) output.warn("**** Please delete it manually ****") if raise_error or isinstance(e_rm, KeyboardInterrupt): raise ConanException("Unable to remove source folder") if force: output.warn("Forced removal of source folder") remove_source() elif os.path.exists(dirty): output.warn("Trying to remove dirty source folder") remove_source() elif conan_file.build_policy_always: output.warn( "Detected build_policy 'always', trying to remove source folder") remove_source() if not os.path.exists(src_folder): output.info('Configuring sources in %s' % src_folder) shutil.copytree(export_folder, src_folder, symlinks=True) # Now move the export-sources to the right location source_sources_folder = os.path.join(src_folder, EXPORT_SOURCES_DIR) if os.path.exists(source_sources_folder): _merge_directories(source_sources_folder, src_folder) # finally remove copied folder shutil.rmtree(source_sources_folder) for f in (EXPORT_TGZ_NAME, EXPORT_SOURCES_TGZ_NAME, CONANFILE + "c", CONANFILE + "o"): try: os.remove(os.path.join(src_folder, f)) except OSError: pass try: shutil.rmtree(os.path.join(src_folder, "__pycache__")) except OSError: pass save(dirty, "") # Creation of DIRTY flag os.chdir(src_folder) try: with tools.environment_append(conan_file.env): conan_file.source() os.remove(dirty) # Everything went well, remove DIRTY flag except Exception as e: os.chdir(export_folder) # in case source() fails (user error, typically), remove the src_folder # and raise to interrupt any other processes (build, package) output.warn("Trying to remove dirty source folder") remove_source(raise_error=False) msg = format_conanfile_exception(output.scope, "source", e) raise ConanException(msg)