abinit/config/scripts/make-macros-triggers

400 lines
12 KiB
Python
Executable File

#!/usr/bin/env python
#
# Copyright (C) 2014-2025 ABINIT Group (Yann Pouillon)
#
# This file is part of the ABINIT software package. For license information,
# please see the COPYING file in the top-level directory of the ABINIT source
# distribution.
#
from __future__ import print_function, division, absolute_import
from time import gmtime,strftime
try:
from commands import getoutput
except ImportError:
from subprocess import getoutput
try:
from ConfigParser import ConfigParser,NoOptionError
except ImportError:
from configparser import ConfigParser,NoOptionError
import os
import re
import sys
class MyConfigParser(ConfigParser):
def optionxform(self,option):
return str(option)
# ---------------------------------------------------------------------------- #
#
# Subroutines
#
# File template
def macros_triggers(name,stamp,m4_changed,m4_init,m4_summary):
ret = """# Generated by %s on %s
#
# Display information about feature triggers status
#
#
# IMPORTANT NOTE
#
# This file has been automatically generated by the %s
# script. If you try to edit it, your changes will systematically be
# overwritten.
#
@M4_CHANGED@
@M4_INIT@
@M4_SUMMARY@
""" % (name,stamp,name)
ret = re.sub("@M4_CHANGED@",m4_changed,ret)
ret = re.sub("@M4_INIT@",m4_init,ret)
ret = re.sub("@M4_SUMMARY@",m4_summary,ret)
return ret
# Changed macro
def macro_changed(trig_params):
ret = """\
# ABI_INFO_TRIGGERS_CHANGED()
# ----------------------
#
# Initializes parameters and command-line options related to feature triggers.
#
AC_DEFUN([ABI_INFO_TRIGGERS_CHANGED],[
@CHANGES@
]) # ABI_INFO_TRIGGERS_CHANGED"""
trig_chgs = ""
trig_list = sorted(trig_params.keys())
for pkg in trig_list:
opt_name = re.sub("_","-",pkg)
if ( trig_params[pkg]["status"] == "new" ):
trig_chgs += " AC_MSG_NOTICE([ * new feature trigger for %s available])\n" % pkg
trig_chgs += " AC_MSG_NOTICE([ >>> --with-%s, %s_*FLAGS])\n" % (opt_name,pkg.upper())
if ( "default_flavor" in trig_params[pkg] ):
trig_chgs += " AC_MSG_NOTICE([ >>> --with-%s-flavor (default: %s)])\n" % (pkg,trig_params[pkg]["default_flavor"])
elif ( trig_params[pkg]["status"] == "removed" ):
trig_chgs += " AC_MSG_NOTICE([ * removed feature trigger for %s])\n" % pkg
if ( trig_chgs == "" ):
trig_chgs = """\
AC_MSG_NOTICE([])
AC_MSG_NOTICE([no change in feature triggers to report])"""
else:
trig_chgs = """\
AC_MSG_NOTICE([])
AC_MSG_NOTICE([reporting changes in feature triggers:])
AC_MSG_NOTICE([])\n""" + trig_chgs
ret = re.sub("@CHANGES@",trig_chgs,ret)
return ret
# Init macro
def macro_init(trig_params):
ret = """\
# ABI_TRIGGERS_INIT()
# -------------------
#
# Initializes parameters and command-line options related to feature triggers.
#
AC_DEFUN([ABI_TRIGGERS_INIT],[
@DEFINITIONS@
]) # ABI_TRIGGERS_INIT"""
trig_template = """\
# Init default parameters for @package@
abi_@package@_enable="@default@"
abi_@package@_init="def"
abi_@package@_prefix=""
# Command-line options for @package@
AC_ARG_WITH([@package@],
AS_HELP_STRING([--with-@package@],
[Install prefix to look for @package@, or automatic configuration if set to 'yes' or 'no' (default: @default@)]),
[ if test "${withval}" = "no" -o "${withval}" = "yes"; then
abi_@package@_enable="${withval}"
abi_@package@_init="yon"
abi_@package@_prefix=""
else
abi_@package@_enable="yes"
abi_@package@_init="dir"
abi_@package@_cppflags="@includes@"
abi_@package@_libs="@libraries@"
abi_@package@_prefix="${withval}"
fi])@with_flavor@
AC_ARG_VAR([@PACKAGE@_CPPFLAGS],
[C preprocessing flags for @package@ (default: empty)])
AC_ARG_VAR([@PACKAGE@_FCFLAGS],
[Fortran flags for @package@ (default: empty)])
AC_ARG_VAR([@PACKAGE@_LIBS],
[Library flags for @package@ (default: empty)])
if test "${@PACKAGE@_FCFLAGS}${@PACKAGE@_LIBS}" != ""; then
abi_@package@_enable="yes"
abi_@package@_init="env"
fi
# Set up trigger-related variables for @package@
abi_@package@_ok="unknown"
if test "${abi_fbk_enable}" = "yes"; then
abi_fbk_@package@_ok="@fbk_status@"
else
abi_fbk_@package@_ok="@nofbk_status@"
fi@test_flavor@
# Substitute trigger-related variables for @package@
AC_SUBST(abi_@package@_enable)@subst_flavor@
AC_SUBST(abi_@package@_init)
AC_SUBST(abi_@package@_ok)
AC_SUBST(abi_@package@_cppflags)
AC_SUBST(abi_@package@_fcflags)
AC_SUBST(abi_@package@_ldflags)
AC_SUBST(abi_@package@_libs)
AC_SUBST(abi_@package@_prefix)
AC_SUBST(abi_fbk_@package@_ok)"""
trig_sd_template = """\
# Set up trigger-related variables for @package@
if test "${abi_fbk_enable}" = "yes"; then
abi_fbk_@package@_ok="@fbk_status@"
else
abi_fbk_@package@_ok="@nofbk_status@"
fi
# Substitute trigger-related variables for @package@
AC_SUBST(abi_fbk_@package@_ok)"""
trig_defs = ""
trig_list = sorted(trig_params.keys())
for pkg in trig_list:
trig_substs= {
"PACKAGE":pkg.upper(),
"package":pkg,
"name":trig_params[pkg]["name"],
}
if ( trig_params[pkg]["fallback"] == "yes" ):
trig_substs["fbk_status"] = "avail"
trig_substs["nofbk_status"] = "disabled"
else:
trig_substs["fbk_status"] = "no"
trig_substs["nofbk_status"] = "no"
if ( trig_params[pkg]["optional"] == "yes" ):
trig_substs["default"] = "no"
else:
trig_substs["default"] = "yes"
if ( "headers" in trig_params[pkg] or \
"modules" in trig_params[pkg] ):
trig_substs["includes"] = "-I${withval}/include"
else:
trig_substs["includes"] = ""
if ( "libraries" in trig_params[pkg] ):
trig_substs["libraries"] = \
"-L${withval}/lib -l" + " -l".join(trig_params[pkg]["libraries"])
else:
trig_substs["libraries"] = ""
if ( "flavors" in trig_params[pkg] ):
flavors_list = [re.sub("^[+a-z0-9_]*:","",item) \
for item in trig_params[pkg]["flavors"]]
trig_substs["flavors"] = " ".join(flavors_list)
trig_substs["default_flavor"] = trig_params[pkg]["flavors"][0]
trig_substs["with_flavor"] = """
AC_ARG_WITH([@package@-flavor],
AS_HELP_STRING([--with-@package@-flavor],
[Flavor of @name@ to use (default: @default_flavor@),
see ~abinit/doc/build/config-template.ac9 for details]),
[abi_@package@_flavor="${withval}"],
[abi_@package@_flavor="@default_flavor@"])"""
trig_substs["subst_flavor"] = "\n AC_SUBST(abi_@package@_flavor)"
trig_substs["test_flavor"] = """
# Check that a permitted flavor value has been specified
if test "${abi_@package@_enable}" = "yes"; then
flavor_values=`echo "${abi_@package@_flavor}" | sed -e 's/+/ /g'`
tmp_flavor_ok="no"
AC_MSG_CHECKING([whether the '${abi_@package@_flavor}' @name@ flavor is valid])
for chk_flavor in @flavors@; do
for set_flavor in ${flavor_values}; do
if test "${set_flavor}" = "${chk_flavor}"; then
tmp_flavor_ok="yes"
break
fi
done
test "${tmp_flavor_ok}" = "yes" && break
done
AC_MSG_RESULT([${tmp_flavor_ok}])
if test "${tmp_flavor_ok}" = "no"; then
AC_MSG_ERROR([invalid @name@ flavor: '${abi_@package@_flavor}'])
fi
else
abi_@package@_flavor="none"
fi"""
else:
trig_substs["flavors"] = ""
trig_substs["default_flavor"] = ""
trig_substs["with_flavor"] = ""
trig_substs["subst_flavor"] = ""
trig_substs["test_flavor"] = ""
# Make 2 passes of substitutions, since some substitutions contain
# patterns themselves
if ( trig_params[pkg]["detector"] == "steredeg" ):
new_def = trig_sd_template
else:
new_def = trig_template
for subst in trig_substs:
new_def = re.sub("@%s@" % subst,trig_substs[subst],new_def)
for subst in trig_substs:
new_def = re.sub("@%s@" % subst,trig_substs[subst],new_def)
if ( trig_defs != "" ):
trig_defs += "\n\n"
trig_defs += new_def
ret = re.sub("@DEFINITIONS@",trig_defs,ret)
return ret
# Summary macro
def macro_summary(trig_params):
ret = """\
# ABI_TRIGGERS_SUMMARY()
# ----------------------
#
# Reports about the current feature triggers status.
#
AC_DEFUN([ABI_TRIGGERS_SUMMARY],[
@TRIG_FORMAT@
# Display configuration
cat <<EOF
Abinit feature triggers status
==============================
The following summary table indicates the status of the feature triggers,
whether they are available and working, how they have been initialized
and whether there are fallbacks to substitute broken ones.
@TRIG_STATUS@
EOF
]) # ABI_TRIGGERS_SUMMARY"""
# Report status of each package
trig_form = ""
trig_stat = " +----------------+--------+--------+--------+--------+\n"
trig_stat += " |Feature |Enabled |Init |Working |Fallback|\n"
trig_stat += " +----------------+--------+--------+--------+--------+\n"
for pkg in sorted(trig_params.keys()):
if ( trig_params[pkg]["detector"] == "steredeg" ):
pfx = "sd"
else:
pfx = "abi"
trig_form += " tmp_e_%s=`echo \"${%s_%s_enable}\" | awk '{printf(\"%%-8s\",[$]1);}'`\n" % (pkg,pfx,pkg)
trig_form += " tmp_i_%s=`echo \"${%s_%s_init}\" | awk '{printf(\"%%-8s\",[$]1);}'`\n" % (pkg,pfx,pkg)
trig_form += " tmp_w_%s=`echo \"${%s_%s_ok}\" | awk '{printf(\"%%-8s\",[$]1);}'`\n" % (pkg,pfx,pkg)
trig_form += " tmp_f_%s=`echo \"${abi_fbk_%s_ok}\" | awk '{printf(\"%%-8s\",[$]1);}'`\n" % (pkg,pkg)
trig_stat += " |%-16s|${tmp_e_%s}|${tmp_i_%s}|${tmp_w_%s}|${tmp_f_%s}|\n" % \
(pkg,pkg,pkg,pkg,pkg)
trig_stat += " +----------------+--------+--------+--------+--------+"
# Substitute macro
ret = re.sub("@TRIG_FORMAT@",trig_form,ret)
ret = re.sub("@TRIG_STATUS@",trig_stat,ret)
return ret
# ---------------------------------------------------------------------------- #
#
# Main program
#
# Initial setup
my_name = "make-macros-triggers"
my_configs = ["config/specs/dependencies.conf"]
my_output = "config/m4/auto-triggers.m4"
# Check if we are in the top of the ABINIT source tree
if ( not os.path.exists("configure.ac") or
not os.path.exists("src/98_main/abinit.F90") ):
print("%s: You must be in the top of an ABINIT source tree." % my_name)
print("%s: Aborting now." % my_name)
sys.exit(1)
# Read config file(s)
for cnf_file in my_configs:
if ( os.path.exists(cnf_file) ):
if ( re.search(r"\.cf$",cnf_file) ):
execfile(cnf_file)
else:
print("%s: Could not find config file (%s)." % (my_name,cnf_file))
print("%s: Aborting now." % my_name)
sys.exit(2)
# What time is it?
now = strftime("%Y/%m/%d %H:%M:%S +0000",gmtime())
# Init
cnf = MyConfigParser()
cnf.read(my_configs[0])
abinit_triggers = []
abinit_fallbacks = []
triggers_params = {}
for pkg in cnf.sections():
triggers_params[pkg] = {}
triggers_params[pkg]["compounds"] = cnf.get(pkg,"compounds").split()
triggers_params[pkg]["detector"] = cnf.get(pkg,"detector")
triggers_params[pkg]["fallback"] = cnf.get(pkg,"fallback")
triggers_params[pkg]["name"] = cnf.get(pkg,"name")
triggers_params[pkg]["optional"] = cnf.get(pkg,"optional")
triggers_params[pkg]["status"] = cnf.get(pkg,"status")
abinit_triggers.append(pkg)
if ( cnf.get(pkg,"fallback") == "yes" ):
abinit_fallbacks.append(pkg)
if ( cnf.has_option(pkg,"flavors") ):
triggers_params[pkg]["flavors"] = cnf.get(pkg,"flavors").split()
abinit_triggers.sort()
abinit_fallbacks.sort()
# Write down macro
m4_changed = macro_changed(triggers_params)
m4_init = macro_init(triggers_params)
m4_summary = macro_summary(triggers_params)
with open(my_output, "w") as m4_file:
m4_file.write(macros_triggers(my_name,now,m4_changed,m4_init,m4_summary))