quantum_package/configure

586 lines
17 KiB
Plaintext
Raw Normal View History

2019-02-05 21:59:26 +01:00
#!/usr/bin/env python2
2015-06-11 11:58:26 +02:00
# -*- coding: utf-8 -*-
"""configure
2017-05-23 18:37:41 +02:00
Usage: configure <config_file>
2015-06-11 11:58:26 +02:00
2015-06-11 16:25:35 +02:00
2015-06-11 11:58:26 +02:00
Options:
2015-06-11 16:25:35 +02:00
2015-09-19 01:37:44 +02:00
config_file A config file with all the information for compiling.
2015-06-11 16:25:35 +02:00
Example config_files are given in config/
Examples:
2015-06-11 16:25:35 +02:00
2017-05-23 18:37:41 +02:00
./configure config/gfortran.cfg
./configure config/ifort.cfg
2015-06-11 11:58:26 +02:00
"""
2016-01-05 01:04:46 +01:00
OK="✓"
FAIL="✗"
2015-06-11 11:58:26 +02:00
import subprocess
import os
import sys
from os.path import join
2017-05-23 18:37:41 +02:00
if len(sys.argv) != 2:
2015-06-11 11:58:26 +02:00
print __doc__
sys.exit()
# __ _
# /__ | _ |_ _. | o ._ _|_ _
# \_| |_ (_) |_) (_| | | | | | (_)
#
2016-04-16 21:18:38 +02:00
try:
QP_ROOT = os.environ["QP_ROOT"]
except KeyError:
QP_ROOT = os.getcwd()
os.environ["QP_ROOT"] = QP_ROOT
2015-06-11 11:58:26 +02:00
QP_ROOT_BIN = join(QP_ROOT, "bin")
2015-11-25 13:57:40 +01:00
QP_ROOT_LIB = join(QP_ROOT, "lib")
2017-07-21 03:34:07 +02:00
QP_ROOT_LIB64 = join(QP_ROOT, "lib64")
2015-06-11 11:58:26 +02:00
QP_ROOT_INSTALL = join(QP_ROOT, "install")
os.environ["PATH"] = os.environ["PATH"] + ":" + QP_ROOT_BIN
2015-06-16 14:43:24 +02:00
2015-06-11 11:58:26 +02:00
d_dependency = {
"ocaml": ["m4", "curl", "zlib", "patch", "gcc", "zeromq", "gmp"],
2015-06-11 11:58:26 +02:00
"m4": ["make"],
"curl": ["make"],
"zlib": ["gcc", "make"],
"patch": ["make"],
"ezfio": ["irpf90"],
"irpf90": ["python"],
"docopt": ["python"],
"resultsFile": ["python"],
"emsl": ["python"],
"gcc": [],
"g++": [],
2016-12-02 11:53:56 +01:00
"zeromq" : [ "g++", "make" ],
"f77zmq" : [ "zeromq", "python", "make" ],
2015-06-11 11:58:26 +02:00
"python": [],
"ninja": ["g++", "python"],
2015-07-16 10:40:57 +02:00
"make": [],
2015-10-28 14:46:19 +01:00
"p_graphviz": ["python"],
"bats": [],
"gmp" : ["make", "g++"]
2015-06-11 11:58:26 +02:00
}
from collections import namedtuple
Info = namedtuple("Info", ["url", "description", "default_path"])
2015-09-08 16:41:26 +02:00
path_github = {"head": "http://github.com", "tail": "archive/master.tar.gz"}
2018-06-07 10:02:25 +02:00
def path_gitlab(user,project,branch):
"""For example,
https://gitlab.com/scemama/resultsFile/-/archive/master/resultsFile-master.tar.gz
"""
return "http://gitlab.com/%(user)s/%(project)s/-/archive/%(branch)s/%(project)s-%(branch)s.tar.gz"%locals()
2015-06-11 11:58:26 +02:00
ocaml = Info(
url='http://raw.github.com/ocaml/opam/master/shell/opam_installer.sh',
2017-07-11 07:18:59 +02:00
description=' OCaml, Opam and the Core library (it will take some time roughly 20min)',
2015-06-11 11:58:26 +02:00
default_path=join(QP_ROOT_BIN, "opam"))
m4 = Info(
url="http://ftp.gnu.org/gnu/m4/m4-latest.tar.gz",
description=" m4",
default_path=join(QP_ROOT_BIN, "m4"))
curl = Info(
url="http://qmcchem.ups-tlse.fr/files/scemama/curl-7.30.0.ermine.tar.bz2",
description=" curl",
default_path=join(QP_ROOT_BIN, "curl"))
zlib = Info(
2017-04-20 19:00:28 +02:00
url='http://www.zlib.net/zlib-1.2.11.tar.gz',
2015-06-11 11:58:26 +02:00
description=' zlib',
2015-11-25 13:57:40 +01:00
default_path=join(QP_ROOT_LIB, "libz.a"))
2015-06-11 11:58:26 +02:00
2015-11-25 13:57:40 +01:00
patch = Info(
2015-06-11 11:58:26 +02:00
url='ftp://ftp.gnu.org/gnu/patch/patch-2.7.5.tar.gz',
2015-11-25 13:57:40 +01:00
description=' patch',
default_path=join(QP_ROOT_BIN, "patch"))
2015-06-11 11:58:26 +02:00
irpf90 = Info(
url='{head}/LCPQ/irpf90/{tail}'.format(**path_github),
2015-06-11 17:26:05 +02:00
description=' IRPF90',
2015-06-11 11:58:26 +02:00
default_path=join(QP_ROOT_BIN, "irpf90"))
docopt = Info(
url='{head}/docopt/docopt/{tail}'.format(**path_github),
2015-06-11 17:26:05 +02:00
description=' docopt',
2015-06-11 11:58:26 +02:00
default_path=join(QP_ROOT_INSTALL, "docopt"))
resultsFile = Info(
2018-06-07 10:02:25 +02:00
url=path_gitlab("scemama","resultsFile","master"),
2015-06-11 11:58:26 +02:00
description=' resultsFile',
default_path=join(QP_ROOT_INSTALL, "resultsFile"))
ninja = Info(
url='{head}/martine/ninja/{tail}'.format(**path_github),
2015-11-25 13:57:40 +01:00
description=' ninja',
2015-06-11 11:58:26 +02:00
default_path=join(QP_ROOT_BIN, "ninja"))
emsl = Info(
2015-11-25 11:49:42 +01:00
url='{head}/LCPQ/EMSL_Basis_Set_Exchange_Local/{tail}'.format(**path_github),
2015-06-11 17:26:05 +02:00
description=' EMSL basis set library',
2015-06-11 11:58:26 +02:00
default_path=join(QP_ROOT_INSTALL, "emsl"))
ezfio = Info(
2019-02-05 21:59:26 +01:00
url='https://gitlab.com/scemama/EZFIO/-/archive/v1.3.5/EZFIO-v1.3.5.tar.gz',
2015-06-11 11:58:26 +02:00
description=' EZFIO',
default_path=join(QP_ROOT_INSTALL, "EZFIO"))
2015-11-25 11:49:42 +01:00
zeromq = Info(
2016-07-13 18:12:25 +02:00
url='https://github.com/zeromq/zeromq4-1/releases/download/v4.1.5/zeromq-4.1.5.tar.gz',
2015-11-25 11:49:42 +01:00
description=' ZeroMQ',
2015-11-25 13:57:40 +01:00
default_path=join(QP_ROOT_LIB, "libzmq.a"))
2015-11-25 11:49:42 +01:00
gmp= Info(
url='ftp://ftp.gnu.org/gnu/gmp/gmp-6.1.2.tar.bz2',
description=' The GNU Multiple Precision Arithmetic Library',
default_path=join(QP_ROOT_LIB, "libgmp.a"))
2015-11-25 11:49:42 +01:00
f77zmq = Info(
2015-11-25 13:57:40 +01:00
url='{head}/zeromq/f77_zmq/{tail}'.format(**path_github),
2015-11-25 11:49:42 +01:00
description=' F77-ZeroMQ',
2016-02-19 00:20:28 +01:00
default_path=join(QP_ROOT_LIB, "libf77zmq.a") )
2015-11-25 11:49:42 +01:00
2015-07-16 10:40:57 +02:00
p_graphviz = Info(
2015-07-16 10:53:40 +02:00
url='https://github.com/xflr6/graphviz/archive/master.tar.gz',
2015-07-16 10:40:57 +02:00
description=' Python library for graphviz',
default_path=join(QP_ROOT_INSTALL, "p_graphviz"))
2015-10-28 14:46:19 +01:00
bats = Info(
url='https://github.com/sstephenson/bats/archive/master.tar.gz',
description=' Bash Automated Testing System',
default_path=join(QP_ROOT_INSTALL, "bats"))
2015-06-11 11:58:26 +02:00
d_info = dict()
2015-11-25 13:57:40 +01:00
for m in ["ocaml", "m4", "curl", "zlib", "patch", "irpf90", "docopt",
2015-11-25 11:49:42 +01:00
"resultsFile", "ninja", "emsl", "ezfio", "p_graphviz",
"zeromq", "f77zmq", "bats", "gmp"]:
2015-06-11 11:58:26 +02:00
exec ("d_info['{0}']={0}".format(m))
def find_path(bin_, l_installed, var_for_qp_root=False):
2015-06-11 11:58:26 +02:00
"""Use the global variable
* l_installed
* d_info
"""
try:
locate = l_installed[bin_]
except KeyError:
locate = d_info[bin_].default_path
if var_for_qp_root:
locate = locate.replace(QP_ROOT, "${QP_ROOT}")
2015-06-11 11:58:26 +02:00
return locate
# _
# |_ ._ _ _|_ o _ ._
# | |_| | | (_ |_ | (_) | |
#
def check_output(*popenargs, **kwargs):
2015-09-18 22:19:15 +02:00
"""Run command with arguments and return its output as a string.
2015-06-11 11:58:26 +02:00
Backported from Python 2.7 as it's implemented as pure python on stdlib.
>>> check_output(['/usr/bin/python', '--version'])
Python 2.6.2
"""
process = subprocess.Popen(stdout=subprocess.PIPE,
stderr=subprocess.PIPE, *popenargs, **kwargs)
2015-06-11 11:58:26 +02:00
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
error = subprocess.CalledProcessError(retcode, cmd)
error.output = output
2015-12-11 15:11:43 +01:00
# print output
# print unused_err
2015-06-11 11:58:26 +02:00
raise error
return output
def checking(d_dependency):
"""
2015-11-25 11:49:42 +01:00
For each key in d_dependency check if it is avalabie
2015-06-11 11:58:26 +02:00
"""
def check_python():
req_version = (2, 6)
cur_version = sys.version_info
# Check python
if cur_version >= req_version:
return 1
else:
print "To old version (need >2.5). Abort"
sys.exit(1)
2015-06-16 14:52:20 +02:00
def check_availability(binary):
2015-06-11 11:58:26 +02:00
"""
2015-09-18 22:19:15 +02:00
If avalable return the path where the binary
can be found, else return 0
2015-06-11 11:58:26 +02:00
"""
if binary == "python":
check_python()
try:
2015-06-23 15:23:45 +02:00
a = check_output(["which", binary])
if binary == "irpf90":
2015-06-24 11:58:21 +02:00
version = check_output("irpf90 -v".split()).strip()
2015-06-23 16:04:37 +02:00
from distutils.version import LooseVersion
2015-06-23 16:01:44 +02:00
if LooseVersion(version) < LooseVersion("1.6.7"):
return 0
2015-06-23 15:23:45 +02:00
else:
return a
return a
2015-09-08 16:41:26 +02:00
except (OSError,subprocess.CalledProcessError):
2015-06-11 11:58:26 +02:00
default_path = d_info[binary].default_path
if os.path.exists(default_path):
return default_path
else:
return 0
def get_list_descendant(d_dependency, l_installed, l_needed):
"""
2015-06-23 16:01:44 +02:00
Descendant : a node reachable by repeated proceeding from parent to child.
2015-06-11 11:58:26 +02:00
"""
d_need_genealogy = dict()
for need in l_needed:
d_need_genealogy[need] = None
for childen in d_dependency[need]:
if childen not in l_installed:
d_need_genealogy[childen] = None
return d_need_genealogy.keys()
return d_need_genealogy.keys()
print """
_
|_) _ o _
| \ (/_ \/ | (/_ \/\/
"""
2015-09-18 22:19:15 +02:00
print "Checking what you need to install and what is avalaible"
2015-06-11 11:58:26 +02:00
print ""
l_installed = dict()
l_needed = []
2015-11-25 11:49:42 +01:00
# Check all the others
2015-06-11 11:58:26 +02:00
length = max(map(len, d_dependency))
for i in d_dependency.keys():
print "Checking {0:>{1}}...".format(i, length),
2015-06-16 14:52:20 +02:00
r = check_availability(i)
2015-06-11 11:58:26 +02:00
if r:
2016-01-05 01:04:46 +01:00
print OK+" ( {0} )".format(r.strip())
2015-06-11 11:58:26 +02:00
l_installed[i] = r.strip()
else:
2016-01-05 01:04:46 +01:00
print FAIL
2015-06-11 11:58:26 +02:00
l_needed.append(i)
print ""
2015-11-25 11:49:42 +01:00
# Expand the needed stuff for all the genealogy
2015-06-11 11:58:26 +02:00
l_install_descendant = get_list_descendant(d_dependency, l_installed,
l_needed)
return l_installed, l_install_descendant
def installation(l_install_descendant):
"""
Installing all the list
0 install ninja
1 create ninja
2 run ninja
"""
def create_rule_ninja():
l_rules = [
"rule download",
" command = wget --no-check-certificate ${url} -O ${out} -o /dev/null",
2015-06-11 11:58:26 +02:00
" description = Downloading ${descr}", ""
]
l_rules += [
"rule install",
" command = ./scripts/install_${target}.sh > _build/${target}.log 2>&1",
" description = Installing ${descr}", ""
]
l_rules += [
"rule install_verbose",
2016-02-19 00:20:28 +01:00
' command = bash -o pipefail -c "./scripts/install_${target}.sh | tee _build/${target}.log 2>&1" ',
2015-06-11 11:58:26 +02:00
" description = Installing ${descr}", " pool = console", ""
]
return l_rules
def splitext(path):
for ext in ['.tar.gz', '.tar.bz2']:
if path.endswith(ext):
return path[:-len(ext)], path[-len(ext):]
return os.path.splitext(path)
print """
___
| ._ _ _|_ _. | | _. _|_ o _ ._
_|_ | | _> |_ (_| | | (_| |_ | (_) | |
"""
d_print = {
"install_ninja": "Install ninja...",
"build": "Creating build.ninja...",
2015-11-25 11:49:42 +01:00
"install": "Installing the dependencies using Ninja..."
2015-06-11 11:58:26 +02:00
}
length = max(map(len, d_print.values()))
def str_info(key):
return "{0:<{1}}".format(d_print[key], length)
if "ninja" in l_install_descendant:
print str_info("install_ninja"),
url = d_info["ninja"].url
extension = splitext(url)[1]
path_archive = "Downloads/{0}{1}".format("ninja", extension)
2015-09-08 16:41:26 +02:00
l_cmd = ["set -x ;", "cd install &&",
"wget {0} -O {1} &&".format(url, path_archive),
"./scripts/install_ninja.sh &&", "cd -"]
2015-06-11 11:58:26 +02:00
try:
check_output(" ".join(l_cmd), shell=True)
except:
2015-06-11 16:03:05 +02:00
raise
else:
2016-01-05 01:04:46 +01:00
print OK
2015-06-11 11:58:26 +02:00
l_install_descendant.remove("ninja")
print str_info("build"),
l_string = create_rule_ninja()
l_build = []
for need in l_install_descendant:
url = d_info[need].url
extension = splitext(url)[1]
archive_path = "Downloads/{0}{1}".format(need, extension)
descr = d_info[need].description
default_path = d_info[need].default_path
2015-11-25 11:49:42 +01:00
# Build to download
2015-06-11 11:58:26 +02:00
l_build += ["build {0}: download".format(archive_path),
" url = {0}".format(url), " descr = {0}".format(descr),
""]
# Build to install
2015-06-16 14:35:16 +02:00
l_dependency = [d_info[i].default_path for i in d_dependency[need]
2015-06-11 11:58:26 +02:00
if i in l_install_descendant]
2015-06-16 14:35:16 +02:00
str_dependency = " ".join(l_dependency)
2015-06-11 11:58:26 +02:00
rule = "install" if need != "ocaml" else "install_verbose"
l_build += ["build {0}: {1} {2} {3}".format(default_path, rule,
archive_path,
2015-06-16 14:35:16 +02:00
str_dependency),
2015-06-11 11:58:26 +02:00
" target = {0}".format(need),
" descr = {0}".format(descr), ""]
l_string += l_build
path = join(QP_ROOT_INSTALL, "build.ninja")
with open(path, "w+") as f:
f.write("\n".join(l_string))
2016-01-05 01:04:46 +01:00
print OK+" ({0})".format(path)
2015-06-11 11:58:26 +02:00
print str_info("install"),
2016-01-05 01:04:46 +01:00
print "Running"
2015-06-11 11:58:26 +02:00
try:
path_ninja = find_path("ninja", l_installed)
subprocess.check_call("cd install ;{0}".format(path_ninja), shell=True)
except:
2015-11-25 18:55:06 +01:00
prefix = os.path.join('install', '_build')
for filename in os.listdir(prefix):
if filename.endswith(".log"):
with open( os.path.join(prefix,filename) ,'r') as f:
print "\n\n"
print "=-=-=-=-=-=- %s =-=-=-=-=-=-" %(filename)
print f.read()
print "=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n"
print "Error in installation of dependencies"
sys.exit(1)
2015-06-11 11:58:26 +02:00
else:
print r"""
_________
< Success >
---------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
"""
def create_ninja_and_rc(l_installed):
print """
_
|_ o ._ _. | o _ _
| | | | (_| | | /_ (/_
"""
2015-07-03 12:18:02 +02:00
d_print = {"qp_root": "Creating quantum_package.rc...",
"build": "Creating build.ninja..."}
2015-06-11 11:58:26 +02:00
length = max(map(len, d_print.values()))
def str_info(key):
return "{0:<{1}}".format(d_print[key], length)
print str_info("qp_root"),
python_path = [join(QP_ROOT, "scripts"), join(QP_ROOT, "install")]
2015-11-19 15:56:46 +01:00
l_python = [join("${QP_ROOT}", "scripts")]
2015-06-11 11:58:26 +02:00
for dir_ in python_path:
for folder in os.listdir(dir_):
path = join(dir_, folder)
if os.path.isdir(path):
2015-11-19 15:56:46 +01:00
path = path.replace(QP_ROOT,"${QP_ROOT}")
2015-06-11 11:58:26 +02:00
l_python.append(path)
path_ezfio = find_path('ezfio', l_installed, var_for_qp_root=True)
path_irpf90 = find_path("irpf90", l_installed, var_for_qp_root=True)
path_ninja = find_path("ninja", l_installed, var_for_qp_root=True)
l_rc = [
'export QP_ROOT={0}'.format(QP_ROOT),
2015-11-19 15:56:46 +01:00
'export QP_EZFIO={0}'.format(path_ezfio.replace(QP_ROOT,"${QP_ROOT}")),
2016-02-19 00:20:28 +01:00
'export QP_PYTHON={0}'.format(":".join(l_python)), "",
2015-11-19 15:56:46 +01:00
'export IRPF90={0}'.format(path_irpf90.replace(QP_ROOT,"${QP_ROOT}")),
'export NINJA={0}'.format(path_ninja.replace(QP_ROOT,"${QP_ROOT}")),
'function qp_prepend_export () {',
' #Prepend path $2:${!1}. Add the semicolon only if ${!1} is defined',
2017-12-21 22:59:27 +01:00
' eval "value_1=\"\${$1}\""',
' echo ${value_1:+${value_1}:}${2}',
'}',
'export PYTHONPATH=$(qp_prepend_export "PYTHONPATH" "${QP_EZFIO}/Python":"${QP_PYTHON}")',
'export PATH=$(qp_prepend_export "PATH" "${QP_PYTHON}":"${QP_ROOT}"/bin:"${QP_ROOT}"/ocaml)',
'export LD_LIBRARY_PATH=$(qp_prepend_export "LD_LIBRARY_PATH" "${QP_ROOT}"/lib:"${QP_ROOT}"/lib64)',
'export LIBRARY_PATH=$(qp_prepend_export "LIBRARY_PATH" "${QP_ROOT}"/lib:"${QP_ROOT}"/lib64)',
'export C_INCLUDE_PATH=$(qp_prepend_export "C_INCLUDE_PATH" "${QP_ROOT}"/include)',
2016-12-02 12:07:19 +01:00
'',
2017-12-21 22:59:27 +01:00
'if [[ $SHELL == "bash" ]] ; then',
' source ${QP_ROOT}/install/EZFIO/Bash/ezfio.sh',
'fi',
2016-10-28 17:10:49 +02:00
'',
'# Choose the correct network interface',
'# export QP_NIC=ib0',
'# export QP_NIC=eth0',
''
]
2015-06-11 11:58:26 +02:00
2017-01-04 01:39:31 +01:00
qp_opam_root = os.getenv('OPAMROOT')
if not qp_opam_root:
2017-01-04 02:29:09 +01:00
qp_opam_root = '${HOME}/.opam'
2017-01-04 01:39:31 +01:00
l_rc.append('export QP_OPAM={0}'.format(qp_opam_root))
l_rc.append('source ${QP_OPAM}/opam-init/init.sh > /dev/null 2> /dev/null || true')
l_rc.append('')
2015-06-11 11:58:26 +02:00
path = join(QP_ROOT, "quantum_package.rc")
with open(path, "w+") as f:
f.write("\n".join(l_rc))
2016-01-05 01:04:46 +01:00
print OK+" ({0})".format(path)
2015-06-11 11:58:26 +02:00
command = ['bash', '-c', 'source {0} && env'.format(path)]
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
for line in proc.stdout:
(key, _, value) = line.partition("=")
os.environ[key] = value.strip()
print str_info("build"),
2015-06-11 11:58:26 +02:00
qp_create_ninja = os.path.join(QP_ROOT, "scripts", "compilation",
"qp_create_ninja.py")
2017-05-23 18:37:41 +02:00
l = [qp_create_ninja, "create", "--development"] + sys.argv[1:]
2015-07-03 12:35:24 +02:00
2015-06-11 11:58:26 +02:00
try:
2015-07-03 12:35:24 +02:00
with open('/dev/null', 'w') as dnull:
2017-11-23 12:17:47 +01:00
subprocess.check_call(" ".join(l), shell=True, stderr=dnull)
2015-06-11 11:58:26 +02:00
except:
2015-07-03 12:18:02 +02:00
print "[ FAIL ]"
2015-09-18 22:19:15 +02:00
print "Check the validity of the config file provided ({0})".format(sys.argv[1])
2015-07-03 12:18:02 +02:00
print "Exit..."
2017-11-23 12:17:47 +01:00
raise
2015-07-03 12:18:02 +02:00
sys.exit(1)
2015-06-11 11:58:26 +02:00
else:
2016-01-05 01:04:46 +01:00
print OK
2015-06-11 11:58:26 +02:00
def recommendation():
path = join(QP_ROOT, "quantum_package.rc")
print "Now :"
print " source {0}".format(path)
2015-09-18 22:19:15 +02:00
print ""
print "Then, install the modules you want to install using :"
2016-01-27 17:15:57 +01:00
print " qp_module.py"
2015-09-18 22:19:15 +02:00
print ""
print "Finally :"
2015-06-11 11:58:26 +02:00
print " ninja"
print ""
2016-02-03 18:01:28 +01:00
print "You can install more plugin with the qp_module.py install command"
2015-09-30 13:47:22 +02:00
print "PS : For more info on compiling the code, read the README.md"
2015-06-11 11:58:26 +02:00
if __name__ == '__main__':
l_installed, l_install_descendant = checking(d_dependency)
if l_install_descendant:
print "You will need to install:"
for i in l_install_descendant:
print "* {0}".format(i)
installation(l_install_descendant)
else:
print "Perfect, nothing to install"
create_ninja_and_rc(l_installed)
recommendation()
2015-11-25 11:49:42 +01:00