## # Copyright 2009-2019 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), # with support of Ghent University (http://ugent.be/hpc), # the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be), # Flemish Research Foundation (FWO) (http://www.fwo.be/en) # and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en). # # https://github.com/easybuilders/easybuild # # EasyBuild is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation v2. # # EasyBuild is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with EasyBuild. If not, see <http://www.gnu.org/licenses/>. ## """ EasyBuild support for building and installing Julia packages, implemented as an easyblock @author: Victor Holanda (CSCS) @author: Samuel Omlin (CSCS) minor adjustments by Jens Henrik Goebbert (JSC) """ import os import socket from easybuild.tools.config import build_option from easybuild.framework.easyconfig import CUSTOM from easybuild.easyblocks.generic.configuremake import ConfigureMake from easybuild.tools import systemtools class EB_Julia(ConfigureMake): """ Install an Julia package as a separate module, or as an extension. """ @staticmethod def extra_options(extra_vars=None): extra_vars = { 'system_name': [None, "Change julia's Project.toml pathname", CUSTOM], 'arch_name': [None, "Change julia's Project.toml pathname", CUSTOM], } return ConfigureMake.extra_options(extra_vars) def get_environment_folder(self): env_path = '' systemname = 'default' if self.cfg['system_name']: systemname = self.cfg['system_name'] if self.cfg['arch_name']: env_path = '-'.join([systemname, self.cfg['arch_name']]) return env_path arch = systemtools.get_cpu_architecture() cpu_family = systemtools.get_cpu_family() env_path = '-'.join([systemname, cpu_family, arch]) return env_path def get_user_depot_path(self): user_depot_path = '' arch = systemtools.get_cpu_architecture() cpu_family = systemtools.get_cpu_family() user_depot_path = os.path.join('~', '.julia', self.version, self.get_environment_folder()) return user_depot_path def __init__(self, *args, **kwargs): super(EB_Julia, self).__init__(*args, **kwargs) self.user_depot = self.get_user_depot_path() local_share_depot = os.path.join(self.installdir, 'local', 'share', 'julia') share_depot = os.path.join(self.installdir, 'share', 'julia') self.std_depots = ':'.join([local_share_depot, share_depot]) self.julia_depot_path = ':'.join([self.user_depot, self.std_depots]) self.admin_depots = os.path.join(self.installdir, 'extensions') self.julia_project = os.path.join(self.user_depot, "environments", '-'.join([self.version, self.get_environment_folder()])) self.user_load_path = '@:@#.#.#-%s' % self.get_environment_folder() self.std_load_paths = '@stdlib' self.julia_load_path = ':'.join([self.user_load_path, self.std_load_paths]) self.admin_load_path = os.path.join(self.admin_depots, "environments", '-'.join([self.version, self.get_environment_folder()])) def sanity_check_step(self): """Custom sanity check for Julia.""" custom_paths = { 'files': [os.path.join('bin', 'julia'), 'LICENSE.md'], 'dirs': ['bin', 'include', 'lib', 'share'], } custom_commands = [ "julia --version", "julia --eval '1+2'", ] super(EB_Julia, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) def install_step(self, *args, **kwargs): """Install procedure for Julia""" super(EB_Julia, self).install_step(*args, **kwargs) txt = """ ## Read EB environment variables if haskey(ENV, "EBJULIA_ADMIN_LOAD_PATH") ADMIN_LOAD_PATH = split(ENV["EBJULIA_ADMIN_LOAD_PATH"],':') else ADMIN_LOAD_PATH = [] end if haskey(ENV, "EBJULIA_STD_LOAD_PATH") STD_LOAD_PATH = split(ENV["EBJULIA_STD_LOAD_PATH"],':') else STD_LOAD_PATH = [] end if haskey(ENV, "EBJULIA_ADMIN_DEPOT_PATH") ADMIN_DEPOT_PATH = split(ENV["EBJULIA_ADMIN_DEPOT_PATH"],':') else ADMIN_DEPOT_PATH = [] end if haskey(ENV, "EBJULIA_STD_DEPOT_PATH") STD_DEPOT_PATH = split(ENV["EBJULIA_STD_DEPOT_PATH"],':') else STD_DEPOT_PATH = [] end ## Inject the admin paths, except if paths empty (or only "@" for LOAD_PATH) or all entries in std path. if !( isempty(LOAD_PATH) || isempty(DEPOT_PATH) || (length(LOAD_PATH)==1 && LOAD_PATH[1]=="@") || all([entry in STD_LOAD_PATH for entry in LOAD_PATH]) || all([entry in STD_DEPOT_PATH for entry in DEPOT_PATH]) ) ## Inject the admin load path into the LOAD_PATH # Empty the LOAD_PATH, separating load path into user and std load path. user_load_path = [] std_load_path = [] while !isempty(LOAD_PATH) entry = popfirst!(LOAD_PATH) if entry in STD_LOAD_PATH push!(std_load_path, entry) else push!(user_load_path, entry) end end # Add user load path to LOAD_PATH while !isempty(user_load_path) entry = popfirst!(user_load_path) push!(LOAD_PATH, entry) end # Add admin load path to LOAD_PATH while !isempty(ADMIN_LOAD_PATH) entry = popfirst!(ADMIN_LOAD_PATH) push!(LOAD_PATH, entry) end # Add std load path to LOAD_PATH while !isempty(std_load_path) entry = popfirst!(std_load_path) push!(LOAD_PATH, entry) end ## Inject the admin depot path into the DEPOT_PATH # Empty the DEPOT_PATH, separating depots into user and std depots. user_depot_path = [] std_depot_path = [] while !isempty(DEPOT_PATH) depot = popfirst!(DEPOT_PATH) if depot in STD_DEPOT_PATH push!(std_depot_path, depot) else push!(user_depot_path, depot) end end # Add user depots to DEPOT_PATH while !isempty(user_depot_path) depot = popfirst!(user_depot_path) push!(DEPOT_PATH, depot) end # Add admin depots to DEPOT_PATH while !isempty(ADMIN_DEPOT_PATH) depot = popfirst!(ADMIN_DEPOT_PATH) push!(DEPOT_PATH, depot) end # Add std depots to DEPOT_PATH while !isempty(std_depot_path) depot = popfirst!(std_depot_path) push!(DEPOT_PATH, depot) end end """ with open(os.path.join(self.installdir, 'etc', 'julia', 'startup.jl'), 'w') as startup_file: startup_file.write(txt) startup_file.close() def make_module_extra(self, *args, **kwargs): txt = super(EB_Julia, self).make_module_extra(*args, **kwargs) txt += self.module_generator.set_environment('JULIA_INSTALL_FOLDER', self.installdir) txt += self.module_generator.set_environment('JULIA_PROJECT', self.julia_project) txt += self.module_generator.set_environment('JULIA_DEPOT_PATH', self.julia_depot_path) txt += self.module_generator.set_environment('EBJULIA_USER_DEPOT_PATH', self.user_depot) txt += self.module_generator.set_environment('EBJULIA_ADMIN_DEPOT_PATH', self.admin_depots) txt += self.module_generator.set_environment('EBJULIA_STD_DEPOT_PATH', self.std_depots) txt += self.module_generator.set_environment('JULIA_LOAD_PATH', self.julia_load_path) txt += self.module_generator.set_environment('EBJULIA_USER_LOAD_PATH', self.user_load_path) txt += self.module_generator.set_environment('EBJULIA_ADMIN_LOAD_PATH', self.admin_load_path) txt += self.module_generator.set_environment('EBJULIA_STD_LOAD_PATH', self.std_load_paths) txt += self.module_generator.set_environment('EBJULIA_ENV_NAME', '-'.join([self.version, self.get_environment_folder()])) return txt