mirror of https://github.com/abinit/abinit.git
356 lines
10 KiB
Python
Executable File
356 lines
10 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# Copyright (C) 2005-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 #, unicode_literals
|
|
|
|
try:
|
|
from ConfigParser import ConfigParser,NoOptionError
|
|
except ImportError:
|
|
from configparser import ConfigParser,NoOptionError
|
|
from time import gmtime,strftime
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
class MyConfigParser(ConfigParser):
|
|
|
|
def optionxform(self,option):
|
|
return str(option)
|
|
|
|
# ---------------------------------------------------------------------------- #
|
|
|
|
#
|
|
# Subroutines
|
|
#
|
|
|
|
# Makefile header
|
|
def makefile_header(name,stamp):
|
|
|
|
return """#
|
|
# Makefile for ABINIT -*- Automake -*-
|
|
# Generated by %s on %s
|
|
|
|
#
|
|
# IMPORTANT NOTE
|
|
#
|
|
# Any manual change to this file will systematically be overwritten.
|
|
# Please modify the %s script or its config file instead.
|
|
#
|
|
|
|
""" % (name,stamp,name)
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- #
|
|
|
|
#
|
|
# Main program
|
|
#
|
|
|
|
# Initial setup
|
|
my_name = "make-makefiles-corelibs"
|
|
my_configs = ["config/specs/corelibs.conf", "config/specs/dependencies.conf"]
|
|
|
|
# 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) ):
|
|
exec(compile(open(cnf_file).read(), cnf_file, 'exec'))
|
|
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_corelibs = cnf.sections()
|
|
abinit_corelibs.sort()
|
|
dep_cnf = MyConfigParser()
|
|
dep_cnf.read(my_configs[1])
|
|
|
|
# Hard-coded libraries for check programs
|
|
hard_chklibs = [
|
|
"16_hideleave",
|
|
"14_hidewrite",
|
|
"12_hide_mpi",
|
|
"11_memory_mpi",
|
|
"10_defs",
|
|
"02_clib",
|
|
]
|
|
|
|
# Prepare recognition of extensions
|
|
re_src = dict()
|
|
re_src["c"] = re.compile(r"\.c$")
|
|
re_src["cu"] = re.compile(r"\.cu$")
|
|
re_src["F90"] = re.compile(r"\.F90$")
|
|
|
|
# Process each library
|
|
for lib in abinit_corelibs:
|
|
|
|
# Init
|
|
lib_opt = cnf.get(lib,"optional")
|
|
lib_rul = cnf.get(lib,"abirules")
|
|
lib_par = cnf.get(lib,"parent")
|
|
try:
|
|
lib_deps = cnf.get(lib,"dependencies").split()
|
|
except NoOptionError:
|
|
lib_deps = None
|
|
|
|
# Reset variables
|
|
makefile = makefile_header(my_name,now)
|
|
sources = list()
|
|
optional_sources = list()
|
|
modules = list()
|
|
headers = list()
|
|
cudas = list()
|
|
sources_specs = dict()
|
|
checkers = None
|
|
|
|
# Select parent dir
|
|
if ( lib_par == "common" ):
|
|
par_dir = os.path.join("shared", "common", "src", lib)
|
|
elif ( lib_par == "libpaw" ):
|
|
par_dir = os.path.join("shared", "libpaw", "src")
|
|
else:
|
|
par_dir = os.path.join("src", lib)
|
|
|
|
# Import source configuration
|
|
src_cnf = os.path.join(par_dir, "abinit.src")
|
|
if ( os.path.exists(src_cnf) ):
|
|
exec(compile(open(src_cnf).read(), src_cnf, 'exec'))
|
|
else:
|
|
print("%s: Could not find config file (%s)." % (my_name,src_cnf))
|
|
print("%s: Aborting now." % my_name)
|
|
sys.exit(3)
|
|
|
|
# Import inter-directory dependency configuration
|
|
dir_cnf = os.path.join(par_dir, "abinit.dir")
|
|
if ( os.path.exists(dir_cnf) ):
|
|
exec(compile(open(dir_cnf).read(), dir_cnf, 'exec'))
|
|
else:
|
|
include_dirs = []
|
|
|
|
# FIXME: abisrc.py glitches
|
|
if ( lib in ["57_iovars", "66_nonlocal", "70_gw"] ):
|
|
include_dirs.append("33_xc_lowlevel")
|
|
|
|
# Add special dirs to include list
|
|
include_dirs += ["common", "core", "libpaw"]
|
|
|
|
# Initialize internal variables
|
|
dd_srcs = "lib%s_srcs =" % (lib)
|
|
nd_srcs = "lib%s_srcs_built =" % (lib)
|
|
ed_srcs = ""
|
|
ob_srcs = ""
|
|
|
|
cleans = ""
|
|
distcleans = ""
|
|
|
|
nds_print = False
|
|
obs_print = False
|
|
|
|
# Initialize build flags
|
|
# FIXME: hard-coded TRIQS C++ flags
|
|
makefile += "AM_CFLAGS = @ABI_CPPFLAGS@\n"
|
|
makefile += "AM_CXXFLAGS = $(sd_triqs_cxxflags)\n"
|
|
makefile += "AM_FCFLAGS = @FPPFLAGS@ @FCFLAGS_FREEFORM@ @FCFLAGS_MODDIR@ @sd_sys_fcflags@ @fcflags_opt_%s@\n\n" % (lib)
|
|
|
|
# Initialize includes
|
|
inc = ""
|
|
for dep in include_dirs:
|
|
inc += " \\\n\t@src_%s_fcflags@" % (dep)
|
|
|
|
# Dependencies
|
|
if ( cnf.has_option(lib,"dependencies") ):
|
|
for dep in cnf.get(lib,"dependencies").split():
|
|
if ( dep in dep_cnf.sections() ):
|
|
if ( dep_cnf.get(dep, "detector") == "steredeg" ):
|
|
dep_pfx = "sd"
|
|
else:
|
|
dep_pfx = "abi"
|
|
dep_lngs = dep_cnf.get(dep, "languages").split()
|
|
if ( ("c" in dep_lngs) or ("c++" in dep_lngs) ):
|
|
inc += " \\\n\t@%s_%s_cppflags@" % (dep_pfx, dep)
|
|
if ( "fortran" in dep_lngs ):
|
|
inc += " \\\n\t@%s_%s_fcflags@" % (dep_pfx, dep)
|
|
else:
|
|
raise ValueError("invalid external dependency: '%s'" % dep)
|
|
|
|
# Required basic Fortran includes (must be last!)
|
|
inc += " \\\n\t@fc_mod_fcflags@"
|
|
|
|
if ( inc != "" ):
|
|
makefile += "AM_CPPFLAGS =%s\n\n" % (inc)
|
|
|
|
# Generate lists of source files
|
|
for src in sources:
|
|
if ( src in sources_specs ):
|
|
src_specs = sources_specs[src]
|
|
else:
|
|
src_specs = ABI_SRC_NIL
|
|
|
|
# Check whether the file is built by the configure script
|
|
if ( (src_specs & ABI_SRC_BLT) != 0 ):
|
|
distcleans += " \\\n\t%s" % (src)
|
|
nd_srcs += " \\\n\t%s" % (src)
|
|
ed_srcs += " \\\n\t%s.in" % (src)
|
|
nds_print = True
|
|
else:
|
|
dd_srcs += " \\\n\t%s" % (src)
|
|
if ( not os.path.exists("%s/%s" % (par_dir,src)) ):
|
|
sys.stderr.write("Error: No such file or directory: '%s/%s'\n" % (par_dir,src))
|
|
sys.exit(4)
|
|
|
|
# Check whether to clean the preprocessed source file
|
|
for (ext,reg) in re_src.items():
|
|
if ( reg.search(src) ):
|
|
cleans += " \\\n\t%s" % (re.sub(r"\.%s" % (ext), \
|
|
"_cpp.%s" % (ext.lower()),src))
|
|
|
|
# Find CUDA source files
|
|
if ( re_src["cu"].search(src) ):
|
|
cudas.append(src)
|
|
|
|
# Optional source files
|
|
try:
|
|
for cnd in optional_sources:
|
|
ob_srcs += "if DO_BUILD_%s\n lib%s_srcs += \\\n %s\nendif" % \
|
|
(cnd,lib," \\\n ".join(optional_sources[cnd]))
|
|
obs_print = True
|
|
except NameError:
|
|
pass
|
|
|
|
dd_srcs += "\n\n"
|
|
nd_srcs += "\n\n"
|
|
ob_srcs += "\n\n"
|
|
|
|
makefile += "# Regular source files\n"+dd_srcs
|
|
if ( obs_print ):
|
|
makefile += "# Source files depending on conditionals\n"+ob_srcs
|
|
if ( nds_print ):
|
|
makefile += "# Source files built by scripts\n"+nd_srcs
|
|
|
|
# Library description
|
|
makefile += "# Library description\n"
|
|
makefile += "noinst_LIBRARIES = lib%s.a\n\n" % (lib)
|
|
|
|
makefile += "lib%s_a_SOURCES= $(lib%s_srcs)\n" % (lib,lib)
|
|
if ( nds_print ):
|
|
makefile += "nodist_lib%s_a_SOURCES = $(lib%s_srcs_built)\n" % (lib,lib)
|
|
|
|
# Write header list
|
|
if ( len(headers) > 0 ):
|
|
sep = " \\\n\t"
|
|
makefile += "\nnoinst_HEADERS = \\\n\t%s\n" % (sep.join(headers))
|
|
|
|
# Fix list of files to clean
|
|
if ( len(modules) > 0 ):
|
|
sep = ".mod \\\n\t"
|
|
cleans += " \\\n\t%s.mod\n" % (sep.join(modules))
|
|
elif ( cleans != "" ):
|
|
cleans += "\n"
|
|
|
|
# Write list of files to clean (must be set before adding abilint output)
|
|
if ( cleans == "" ):
|
|
cleans = "\n"
|
|
makefile += "\nCLEANFILES ="+cleans
|
|
|
|
# Write list of files to distclean
|
|
if ( distcleans != "" ):
|
|
makefile += "\nDISTCLEANFILES =%s\n" % (distcleans)
|
|
|
|
# Add "abinit.src" to the list of dist files
|
|
makefile += "\nEXTRA_DIST = abinit.src\n"
|
|
|
|
# Write internal library dependencies
|
|
dep = os.path.join(par_dir, "abinit.dep")
|
|
if ( os.path.exists(dep) ):
|
|
makefile += "\nEXTRA_DIST += abinit.dep\n"
|
|
makefile += "\n"+ open(dep,"rt").read()
|
|
|
|
# Write targets for checkers
|
|
try:
|
|
tmp_chk = "\ncheck_PROGRAMS ="
|
|
tmp_chk_cln = "\nCLEANFILES +="
|
|
for chk in checkers:
|
|
tmp_chk += " \\\n\t%s" % (chk)
|
|
tmp_chk_cln += " \\\n\t%s.log" % (chk)
|
|
tmp_chk_cln += " \\\n\t%s.tmp" % (chk)
|
|
makefile += tmp_chk + "\n"
|
|
for chk in checkers:
|
|
# FIXME: hard-coded for now
|
|
makefile += "\n%s_SOURCES = %s.F90" % (chk,chk)
|
|
makefile += "\n%s_CPPFLAGS = @sd_netcdf_cppflags@ @sd_linalg_cppflags@ -I$(top_srcdir)/shared/common/src/incs -I$(top_srcdir)/src/incs -I$(top_builddir)/shared/common/src/mods -I$(top_builddir)/src/mods" % \
|
|
(chk)
|
|
makefile += "\n%s_LDADD = \\\n\tlib%s.a" % (chk,lib)
|
|
for elc in checkers[chk] + hard_chklibs:
|
|
makefile += " \\\n\t../%s/lib%s.a" % (elc,elc)
|
|
makefile += " \\\n\t@%s@\n" % \
|
|
("@ \\\n\t@".join(["sd_netcdf_libs","sd_linalg_libs"]))
|
|
makefile += "\ncheck-local:\n"
|
|
for chk in checkers:
|
|
makefile += "\t./%s >%s.log 2>&1; grep '^TEST FAILED' %s.log && echo 'Unit test %s FAILED' || echo 'Unit test %s OK'\n" % \
|
|
(chk,chk,chk,chk,chk)
|
|
makefile += tmp_chk_cln + "\n"
|
|
except:
|
|
pass
|
|
|
|
# Write CUDA rules
|
|
if ( len(cudas) > 0 ):
|
|
makefile += "\nSUFFIXES = .o .cu\n\n.cu.o:\n\t$(NVCC) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(NVCC_CPPFLAGS) $(NVCC_CFLAGS) -c $<\n"
|
|
for src in cudas:
|
|
makefile += "\n%s.$(OBJEXT): %s\n" % (re.sub(r"\.cu","",src),src)
|
|
|
|
# Write optional source files
|
|
# Note: useless because Automake already takes care of it
|
|
#try:
|
|
# ob_xtra = "\nEXTRA_DIST +="
|
|
# for cnd in optional_sources:
|
|
# ob_xtra += " \\\n " + " \\\n ".join(optional_sources[cnd])
|
|
# ob_xtra += "\n"
|
|
# makefile += ob_xtra
|
|
#except NameError:
|
|
# pass
|
|
|
|
# Write source file templates
|
|
if ( len(ed_srcs) > 0 ):
|
|
makefile += "\n\nEXTRA_DIST +=" + ed_srcs + "\n"
|
|
|
|
# Write additional hand-made information
|
|
add = os.path.join(par_dir, "abinit.amf")
|
|
if ( os.path.exists(add) ):
|
|
makefile += "\nEXTRA_DIST += abinit.amf\n"
|
|
makefile += "\n" + open(add, "rt").read()
|
|
|
|
# Include RoboDOC header
|
|
hdr = "%s/_%s_" % (par_dir,lib)
|
|
if ( os.path.exists(hdr) ):
|
|
makefile += "\n\nEXTRA_DIST += _%s_\n" % (lib)
|
|
|
|
# Write additional cmake information
|
|
cml = os.path.join(par_dir, "CMakeLists.txt")
|
|
if ( os.path.exists(cml) ):
|
|
makefile += "\nEXTRA_DIST += CMakeLists.txt\n"
|
|
|
|
# Output to Makefile.am
|
|
mf = open(os.path.join(par_dir, "Makefile.am"), "wt")
|
|
mf.write(makefile)
|
|
mf.close()
|