# -*- coding: utf-8 -*-
__copyright__ = """ This code is licensed under the 3-clause BSD license.
Copyright ETH Zurich, Laboratory of Physical Chemistry, Reiher Group.
See LICENSE.txt for details.
"""
from typing import List
import git
import os
import subprocess
import sys
from scine_puffin.config import Configuration
[docs]class Program:
"""
A common interface for all programs and their setups
Parameters
----------
settings :: dict
The settings for the particular program. This dictionary should be the
given program's block in the ``Configuration``.
"""
def __init__(self, settings: dict):
self.version = settings["version"]
self.root = settings["root"]
self.source = settings["source"]
self.settings = settings
[docs] def install(self, repo_dir: str, install_dir: str, ncores: int):
"""
Installs or loads the given program. After the install, the
``check_install`` function should run through with out exceptions.
The choice of installation/compilation or loading of the program is
based on the settings given in the constructor.
Parameters
----------
repo_dir :: str
The folder for all repositories, if a clone or download is required
for the installation, this folder will be used.
install_dir :: str
If the program is actually installed and not just loaded, this
folder will be used as target directory for the install process.
ncores :: int
The number of cores/threads to be used when compiling/installing
the program.
"""
raise NotImplementedError
[docs] def check_install(self):
"""
A small function checking if the program was installed/located correctly
and does provide the expected features.
"""
raise NotImplementedError
[docs] def setup_environment(self, config: Configuration, env_paths: dict, env_vars: dict):
"""
Appends the program specific environment variables to the given
dictionaries.
Parameters
----------
config :: scine_puffin.config.Configuration
The current global configuration.
env_paths :: dict
A dictionary for all the environment paths, such as ``PATH`` and
``LD_LIBRARY_PATH``. The added settings will be appended to the
existing paths, using ``export PATH=$PATH:...``.
env_vars :: dict
A dictionary for all fixed environment variables. All settings
will replace existing variables such as ``export OMP_NUM_THREADS=1``
"""
raise NotImplementedError
[docs] def available_models(self) -> List[str]:
"""
A small function returning the single point models available now with
the given program loaded/installed.
Returns
-------
models :: List[str]
A list of names of models that are available if the program is
avialable.
"""
raise NotImplementedError
def scine_module_install(self, repo_dir: str, install_dir: str, ncores: int,
add_lib: bool = False, add_bin: bool = False):
initial_dir = os.getcwd()
# Handle repository
if os.path.exists(repo_dir):
repository = git.Repo(repo_dir)
try:
repository.remotes.origin.pull()
repository.git.submodule("update", "--init")
except BaseException:
try:
repository.git.checkout("master")
except git.exc.GitCommandError:
repository.git.checkout("main")
repository.git.submodule("update", "--init")
repository.remotes.origin.pull()
repository.git.submodule("update", "--init")
finally:
repository.git.checkout(self.version)
repository.remotes.origin.pull()
repository.git.submodule("update", "--init")
else:
repository = git.Repo.clone_from(self.source, repo_dir)
repository.git.checkout(self.version)
repository.git.submodule("update", "--init")
# Build from sources into <repo>/build and install
build_dir = os.path.join(repo_dir, "build")
if build_dir and not os.path.exists(build_dir):
os.makedirs(build_dir)
os.chdir(build_dir)
env = os.environ.copy()
if add_bin:
env["PATH"] = env["PATH"] + ":" + os.path.join(install_dir, "bin")
if add_lib:
if "LD_LIBRARY_PATH" in env.keys():
env["LD_LIBRARY_PATH"] = (
env["LD_LIBRARY_PATH"] + ":" + os.path.join(install_dir, "lib")
)
else:
env["LD_LIBRARY_PATH"] = os.path.join(install_dir, "lib")
env["LD_LIBRARY_PATH"] = (
env["LD_LIBRARY_PATH"] + ":" + os.path.join(install_dir, "lib64")
)
args = ["cmake"]
args.append("-DCMAKE_BUILD_TYPE=Release")
args.append("-DSCINE_BUILD_TESTS=OFF")
args.append("-DSCINE_BUILD_PYTHON_BINDINGS=ON")
args.append("-DSCINE_MARCH=" + self.settings["march"])
if self.settings["cxx_compiler_flags"]:
args.append("-DCMAKE_CXX_FLAGS=" + self.settings["cxx_compiler_flags"])
args.append("-DCMAKE_INSTALL_PREFIX=" + install_dir)
args.append("-DPYTHON_EXECUTABLE=" + sys.executable)
if self.settings["cmake_flags"]:
args += self.settings["cmake_flags"].split(" ")
args.append("..")
subprocess.run(args, env=env, check=True)
subprocess.run(["make", "-j" + str(ncores), "install"], env=env, check=True)
os.chdir(initial_dir)