def _build_graph(self, profile_host, profile_build, install=False): path = temp_folder() path = os.path.join(path, "conanfile.txt") save(path, textwrap.dedent(""" [requires] app/testing@user/channel """)) ref = ConanFileReference(None, None, None, None, validate=False) options = OptionsValues() graph_info = GraphInfo(profile_host=profile_host, profile_build=profile_build, options=options, root_ref=ref) recorder = ActionRecorder() app = self._get_app() deps_graph = app.graph_manager.load_graph(path, create_reference=None, graph_info=graph_info, build_mode=[], check_updates=False, update=False, remotes=Remotes(), recorder=recorder) if install: build_mode = [] # Means build all binary_installer = BinaryInstaller(app, recorder) build_mode = BuildMode(build_mode, app.out) binary_installer.install(deps_graph, None, build_mode, update=False, profile_host=profile_host, profile_build=profile_build, graph_lock=None, keep_build=False) return deps_graph
def build_consumer(self, path, profile_build_requires=None, ref=None, create_ref=None, install=True): profile = Profile() if profile_build_requires: profile.build_requires = profile_build_requires profile.process_settings(self.cache) update = check_updates = False recorder = ActionRecorder() remotes = Remotes() build_mode = [] # Means build all ref = ref or ConanFileReference(None, None, None, None, validate=False) options = OptionsValues() graph_info = GraphInfo(profile, options, root_ref=ref) app = self._get_app() deps_graph = app.graph_manager.load_graph(path, create_ref, graph_info, build_mode, check_updates, update, remotes, recorder) if install: binary_installer = BinaryInstaller(app, recorder) build_mode = BuildMode(build_mode, app.out) binary_installer.install(deps_graph, None, build_mode, update, False, graph_info) return deps_graph
def workspace_install(self, path, settings=None, options=None, env=None, remote_name=None, build=None, profile_name=None, update=False, cwd=None, install_folder=None): cwd = cwd or get_cwd() abs_path = os.path.normpath(os.path.join(cwd, path)) remotes = self.app.load_remotes(remote_name=remote_name, update=update) # remotes = self.app.cache.registry.load_remotes() # remotes.select(remote_name) # self.app.python_requires.enable_remotes(update=update, remotes=remotes) workspace = Workspace(abs_path, self.app.cache) graph_info = get_graph_info(profile_name, settings, options, env, cwd, None, self.app.cache, self.app.out) self.app.out.info("Configuration:") self.app.out.writeln(graph_info.profile_host.dumps()) self.app.cache.editable_packages.override(workspace.get_editable_dict()) recorder = ActionRecorder() deps_graph = self.app.graph_manager.load_graph(workspace.root, None, graph_info, build, False, update, remotes, recorder) print_graph(deps_graph, self.app.out) # Inject the generators before installing for node in deps_graph.nodes: if node.recipe == RECIPE_EDITABLE: generators = workspace[node.ref].generators if generators is not None: tmp = list(node.conanfile.generators) tmp.extend([g for g in generators if g not in tmp]) node.conanfile.generators = tmp installer = BinaryInstaller(self.app, recorder) installer.install(deps_graph, remotes, build, update, keep_build=False, graph_info=graph_info) install_folder = install_folder or cwd workspace.generate(install_folder, deps_graph, self.app.out) workspace.build(install_folder, deps_graph, self.app.out, self.app)
def setUp(self): self.output = TestBufferConanOutput() cache_folder = temp_folder() cache = ClientCache(cache_folder, self.output) self.cache = cache self.remote_manager = MockRemoteManager() self.resolver = RangeResolver(cache, self.remote_manager) proxy = ConanProxy(cache, self.output, self.remote_manager) self.loader = ConanFileLoader(None, self.output, ConanPythonRequire(None, None)) self.manager = GraphManager(self.output, cache, self.remote_manager, self.loader, proxy, self.resolver) hook_manager = Mock() recorder = Mock() self.binary_installer = BinaryInstaller(cache, self.output, self.remote_manager, recorder, hook_manager)
def install_workspace(self, graph_info, workspace, remote_name, build_modes, update): refs = [ ConanFileReference(v, "root", "project", "develop") for v in workspace.root ] deps_graph, _ = self._graph_manager.load_graph(refs, None, graph_info, build_modes, False, update, remote_name, self._recorder, workspace) output = ScopedOutput(str("Workspace"), self._user_io.out) output.highlight("Installing...") print_graph(deps_graph, self._user_io.out) installer = BinaryInstaller(self._cache, output, self._remote_manager, recorder=self._recorder, workspace=workspace, hook_manager=self._hook_manager) installer.install(deps_graph, keep_build=False, graph_info=graph_info) workspace.generate()
def deps_install(app, ref_or_path, install_folder, base_folder, graph_info, remotes=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, recorder=None, lockfile_node_id=None, is_build_require=False, add_txt_generator=True, require_overrides=None, conanfile_path=None, test=None, source_folder=None, output_folder=None): """ Fetch and build all dependencies for the given reference @param app: The ConanApp instance with all collaborators @param ref_or_path: ConanFileReference or path to user space conanfile @param install_folder: where the output files will be saved @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. @param no_imports: Install specified packages but avoid running imports @param add_txt_generator: Add the txt to the list of generators """ out, user_io, graph_manager, cache = app.out, app.user_io, app.graph_manager, app.cache remote_manager, hook_manager = app.remote_manager, app.hook_manager profile_host, profile_build = graph_info.profile_host, graph_info.profile_build if profile_build: out.info("Configuration (profile_host):") out.writeln(profile_host.dumps()) out.info("Configuration (profile_build):") out.writeln(profile_build.dumps()) else: out.info("Configuration:") out.writeln(profile_host.dumps()) deps_graph = graph_manager.load_graph(ref_or_path, create_reference, graph_info, build_modes, False, update, remotes, recorder, lockfile_node_id=lockfile_node_id, is_build_require=is_build_require, require_overrides=require_overrides) graph_lock = graph_info.graph_lock # After the graph is loaded it is defined root_node = deps_graph.root conanfile = root_node.conanfile if root_node.recipe == RECIPE_VIRTUAL: out.highlight("Installing package: %s" % str(ref_or_path)) else: conanfile.output.highlight("Installing package") print_graph(deps_graph, out) try: if cross_building(conanfile): settings = get_cross_building_settings(conanfile) message = "Cross-build from '%s:%s' to '%s:%s'" % settings out.writeln(message, Color.BRIGHT_MAGENTA) except ConanException: # Setting os doesn't exist pass installer = BinaryInstaller(app, recorder=recorder) # TODO: Extract this from the GraphManager, reuse same object, check args earlier build_modes = BuildMode(build_modes, out) installer.install(deps_graph, remotes, build_modes, update, profile_host, profile_build, graph_lock, keep_build=keep_build) graph_lock.complete_matching_prevs() if manifest_folder: manifest_manager = ManifestManager(manifest_folder, user_io=user_io, cache=cache) for node in deps_graph.nodes: if node.recipe in (RECIPE_CONSUMER, RECIPE_VIRTUAL): continue retrieve_exports_sources(remote_manager, cache, node.conanfile, node.ref, remotes) manifest_manager.check_graph(deps_graph, verify=manifest_verify, interactive=manifest_interactive) manifest_manager.print_log() if hasattr(conanfile, "layout") and not test: conanfile.folders.set_base_source(source_folder or conanfile_path) conanfile.folders.set_base_install(output_folder or conanfile_path) conanfile.folders.set_base_imports(output_folder or conanfile_path) conanfile.folders.set_base_generators(output_folder or conanfile_path) else: conanfile.folders.set_base_install(install_folder) conanfile.folders.set_base_imports(install_folder) conanfile.folders.set_base_generators(base_folder) output = conanfile.output if root_node.recipe != RECIPE_VIRTUAL else out if install_folder: # Write generators tmp = list( conanfile.generators) # Add the command line specified generators generators = set(generators) if generators else set() tmp.extend([g for g in generators if g not in tmp]) if add_txt_generator: tmp.append("txt") conanfile.generators = tmp app.generator_manager.write_generators(conanfile, install_folder, conanfile.generators_folder, output) write_toolchain(conanfile, conanfile.generators_folder, output) if not isinstance(ref_or_path, ConanFileReference): # Write conaninfo content = normalize(conanfile.info.dumps()) save(os.path.join(install_folder, CONANINFO), content) output.info("Generated %s" % CONANINFO) graph_info.save(install_folder) output.info("Generated graphinfo") graph_lock_file = GraphLockFile(profile_host, profile_build, graph_lock) graph_lock_file.save(os.path.join(install_folder, "conan.lock")) if not no_imports: run_imports(conanfile) if type(conanfile ).system_requirements != ConanFile.system_requirements: call_system_requirements(conanfile, conanfile.output) if not create_reference and isinstance(ref_or_path, ConanFileReference): # The conanfile loaded is a virtual one. The one w 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)
def install(self, ref_or_path, install_folder, graph_info, remotes=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 ref_or_path: ConanFileReference or path to user space conanfile @param install_folder: where the output files will be saved @param remote_name: 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 """ 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(graph_info.profile.dumps()) result = self._graph_manager.load_graph(ref_or_path, create_reference, graph_info, build_modes, False, update, remotes, self._recorder) deps_graph, conanfile = result if conanfile.display_name == "virtual": self._user_io.out.highlight("Installing package: %s" % str(ref_or_path)) else: conanfile.output.highlight("Installing package") print_graph(deps_graph, self._user_io.out) try: if cross_building(graph_info.profile.processed_settings): settings = get_cross_building_settings(graph_info.profile.processed_settings) message = "Cross-build from '%s:%s' to '%s:%s'" % settings self._user_io.out.writeln(message, Color.BRIGHT_MAGENTA) except ConanException: # Setting os doesn't exist pass installer = BinaryInstaller(self._cache, self._user_io.out, self._remote_manager, recorder=self._recorder, hook_manager=self._hook_manager) installer.install(deps_graph, remotes, keep_build=keep_build, graph_info=graph_info) if manifest_folder: manifest_manager = ManifestManager(manifest_folder, user_io=self._user_io, cache=self._cache) for node in deps_graph.nodes: if node.recipe in (RECIPE_CONSUMER, RECIPE_VIRTUAL): continue complete_recipe_sources(self._remote_manager, self._cache, node.conanfile, node.ref, remotes) manifest_manager.check_graph(deps_graph, verify=manifest_verify, interactive=manifest_interactive) manifest_manager.print_log() if install_folder: # Write generators output = conanfile.output if conanfile.display_name != "virtual" else self._user_io.out 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(ref_or_path, ConanFileReference): # Write conaninfo content = normalize(conanfile.info.dumps()) save(os.path.join(install_folder, CONANINFO), content) output.info("Generated %s" % CONANINFO) graph_info.save(install_folder) output.info("Generated graphinfo") if not no_imports: run_imports(conanfile, install_folder) call_system_requirements(conanfile, conanfile.output) if not create_reference and isinstance(ref_or_path, ConanFileReference): # The conanfile loaded is a virtual one. The one w 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)
class GraphManagerTest(unittest.TestCase): def setUp(self): self.output = TestBufferConanOutput() cache_folder = temp_folder() cache = ClientCache(cache_folder, self.output) self.cache = cache self.remote_manager = MockRemoteManager() self.resolver = RangeResolver(cache, self.remote_manager) proxy = ConanProxy(cache, self.output, self.remote_manager) self.loader = ConanFileLoader(None, self.output, ConanPythonRequire(None, None)) self.manager = GraphManager(self.output, cache, self.remote_manager, self.loader, proxy, self.resolver) hook_manager = Mock() recorder = Mock() self.binary_installer = BinaryInstaller(cache, self.output, self.remote_manager, recorder, hook_manager) def _cache_recipe(self, reference, test_conanfile, revision=None): if isinstance(test_conanfile, TestConanFile): test_conanfile.info = True ref = ConanFileReference.loads(reference) save(self.cache.package_layout(ref).conanfile(), str(test_conanfile)) with self.cache.package_layout(ref).update_metadata() as metadata: metadata.recipe.revision = revision or "123" manifest = FileTreeManifest.create(self.cache.package_layout(ref).export()) manifest.save(self.cache.package_layout(ref).export()) def build_graph(self, content, profile_build_requires=None, ref=None, create_ref=None): path = temp_folder() path = os.path.join(path, "conanfile.py") save(path, str(content)) self.loader.cached_conanfiles = {} profile = Profile() if profile_build_requires: profile.build_requires = profile_build_requires profile.process_settings(self.cache) update = check_updates = False recorder = ActionRecorder() remotes = Remotes() build_mode = [] ref = ref or ConanFileReference(None, None, None, None, validate=False) options = OptionsValues() graph_info = GraphInfo(profile, options, root_ref=ref) deps_graph, _ = self.manager.load_graph(path, create_ref, graph_info, build_mode, check_updates, update, remotes, recorder) self.binary_installer.install(deps_graph, False, graph_info) return deps_graph def _check_node(self, node, ref, deps, build_deps, dependents, closure): conanfile = node.conanfile ref = ConanFileReference.loads(str(ref)) self.assertEqual(node.ref.full_repr(), ref.full_repr()) self.assertEqual(conanfile.name, ref.name) self.assertEqual(len(node.dependencies), len(deps) + len(build_deps)) dependants = node.inverse_neighbors() self.assertEqual(len(dependants), len(dependents)) for d in dependents: self.assertIn(d, dependants) # The recipe requires is resolved to the reference WITH revision! self.assertEqual(len(deps), len(conanfile.requires)) for dep in deps: self.assertEqual(conanfile.requires[dep.name].ref, dep.ref) self.assertEqual(closure, node.public_closure) libs = [] envs = [] for n in closure: libs.append("mylib%s%slib" % (n.ref.name, n.ref.version)) envs.append("myenv%s%senv" % (n.ref.name, n.ref.version)) self.assertEqual(conanfile.deps_cpp_info.libs, libs) env = {"MYENV": envs} if envs else {} self.assertEqual(conanfile.deps_env_info.vars, env)
def deps_install(app, ref_or_path, install_folder, graph_info, remotes=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, use_lock=False, recorder=None): """ Fetch and build all dependencies for the given reference :param app: The ConanApp instance with all collaborators @param ref_or_path: ConanFileReference or path to user space conanfile @param install_folder: where the output files will be saved @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 """ out, user_io, graph_manager, cache = app.out, app.user_io, app.graph_manager, app.cache remote_manager, hook_manager = app.remote_manager, app.hook_manager if generators is not False: generators = set(generators) if generators else set() generators.add("txt") # Add txt generator by default out.info("Configuration:") out.writeln(graph_info.profile_host.dumps()) deps_graph = graph_manager.load_graph(ref_or_path, create_reference, graph_info, build_modes, False, update, remotes, recorder) root_node = deps_graph.root conanfile = root_node.conanfile if root_node.recipe == RECIPE_VIRTUAL: out.highlight("Installing package: %s" % str(ref_or_path)) else: conanfile.output.highlight("Installing package") print_graph(deps_graph, out) try: if cross_building(graph_info.profile_host.processed_settings): settings = get_cross_building_settings(graph_info.profile_host.processed_settings) message = "Cross-build from '%s:%s' to '%s:%s'" % settings out.writeln(message, Color.BRIGHT_MAGENTA) except ConanException: # Setting os doesn't exist pass installer = BinaryInstaller(app, recorder=recorder) # TODO: Extract this from the GraphManager, reuse same object, check args earlier build_modes = BuildMode(build_modes, out) installer.install(deps_graph, remotes, build_modes, update, keep_build=keep_build, graph_info=graph_info) # GraphLock always != None here (because of graph_manager.load_graph) graph_info.graph_lock.update_check_graph(deps_graph, out) if manifest_folder: manifest_manager = ManifestManager(manifest_folder, user_io=user_io, cache=cache) for node in deps_graph.nodes: if node.recipe in (RECIPE_CONSUMER, RECIPE_VIRTUAL): continue complete_recipe_sources(remote_manager, cache, node.conanfile, node.ref, remotes) manifest_manager.check_graph(deps_graph, verify=manifest_verify, interactive=manifest_interactive) manifest_manager.print_log() if install_folder: conanfile.install_folder = install_folder # Write generators output = conanfile.output if root_node.recipe != RECIPE_VIRTUAL else out 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(ref_or_path, ConanFileReference) or use_lock: # Write conaninfo content = normalize(conanfile.info.dumps()) save(os.path.join(install_folder, CONANINFO), content) output.info("Generated %s" % CONANINFO) graph_info.save(install_folder) output.info("Generated graphinfo") if not no_imports: run_imports(conanfile, install_folder) call_system_requirements(conanfile, conanfile.output) if not create_reference and isinstance(ref_or_path, ConanFileReference): # The conanfile loaded is a virtual one. The one w 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)