import conda_build.conda_interface import networkx as nx import conda_build.api from compute_build_graph import construct_graph import argparse import os from collections import OrderedDict import sys try: from ruamel_yaml import safe_load, safe_dump except ImportError: from yaml import safe_load, safe_dump def get_host_platform(): from sys import platform if platform == "linux" or platform == "linux2": return "linux" elif platform == "darwin": return "osx" elif platform == "win32": return "win" def build_all(recipes_dir, arch): folders = os.listdir(recipes_dir) old_comp_folders = [] new_comp_folders = [] if not folders: print("Found no recipes to build") return for folder in folders: built = False cbc = os.path.join(recipes_dir, folder, "conda_build_config.yaml") if os.path.exists(cbc): with open(cbc, "r") as f: text = ''.join(f.readlines()) if 'channel_sources' in text: specific_config = safe_load(text) if "channel_targets" not in specific_config: raise RuntimeError("channel_targets not found in {}".format(folder)) if "channel_sources" in specific_config: for row in specific_config["channel_sources"]: channels = [c.strip() for c in row.split(",")] if channels != ['conda-forge', 'defaults'] and \ channels != ['conda-forge/label/cf201901', 'defaults']: print("Not a standard configuration of channel_sources. Building {} individually.".format(folder)) conda_build.api.build([os.path.join(recipes_dir, folder)], config=get_config(arch, channels)) built = True break if not built: old_comp_folders.append(folder) continue if not built: new_comp_folders.append(folder) if old_comp_folders: print("Building {} with conda-forge/label/cf201901".format(','.join(old_comp_folders))) channel_urls = ['local', 'conda-forge/label/cf201901', 'defaults'] build_folders(recipes_dir, old_comp_folders, arch, channel_urls) if new_comp_folders: print("Building {} with conda-forge/label/main".format(','.join(new_comp_folders))) channel_urls = ['local', 'conda-forge', 'defaults'] build_folders(recipes_dir, new_comp_folders, arch, channel_urls) def get_config(arch, channel_urls): exclusive_config_file = os.path.join(conda_build.conda_interface.root_dir, 'conda_build_config.yaml') platform = get_host_platform() script_dir = os.path.dirname(os.path.realpath(__file__)) variant_config_files = [] variant_config_file = os.path.join(script_dir, '{}{}.yaml'.format( platform, arch)) if os.path.exists(variant_config_file): variant_config_files.append(variant_config_file) error_overlinking = (get_host_platform() != "win") config = conda_build.api.Config( variant_config_files=variant_config_files, arch=arch, exclusive_config_file=exclusive_config_file, channel_urls=channel_urls, error_overlinking=error_overlinking) return config def build_folders(recipes_dir, folders, arch, channel_urls): index_path = os.path.join(sys.exec_prefix, 'conda-bld') os.makedirs(index_path, exist_ok=True) conda_build.api.update_index(index_path) index = conda_build.conda_interface.get_index(channel_urls=channel_urls) conda_resolve = conda_build.conda_interface.Resolve(index) config = get_config(arch, channel_urls) platform = get_host_platform() worker = {'platform': platform, 'arch': arch, 'label': '{}-{}'.format(platform, arch)} G = construct_graph(recipes_dir, worker=worker, run='build', conda_resolve=conda_resolve, folders=folders, config=config, finalize=False) order = list(nx.topological_sort(G)) order.reverse() print('Computed that there are {} distributions to build from {} recipes' .format(len(order), len(folders))) if not order: print('Nothing to do') return print("Resolved dependencies, will be built in the following order:") print(' '+'\n '.join(order)) d = OrderedDict() for node in order: d[G.node[node]['meta'].meta_path] = 1 for recipe in d.keys(): conda_build.api.build([recipe], config=get_config(arch, channel_urls)) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('recipes_dir', default=os.getcwd(), help='Directory where the recipes are') parser.add_argument('--arch', default='64', help='target architecture (64 or 32)') args = parser.parse_args() build_all(args.recipes_dir, args.arch)