-
Notifications
You must be signed in to change notification settings - Fork 191
Closed
Labels
ideaProposition of an idea and opening an issue to discuss itProposition of an idea and opening an issue to discuss it
Description
Motivation
This proposal is meant to start a discussion on a replacement for the current fpm
ci for stdlib. The idea would be to use a python script to preprocess stdlib before building with fpm or CMake. While CMake already has a customized fypp preprocessor, such script could serve as a replacement using a PRE_BUILD
action with add_custom_command
. Also, currently the fpm
branch lacks the means for a flexible way of adding dependencies in the toml file. This proposal would try to remedy these shortcomings.
Prior Art
No response
Additional Information
Proposal
Say a fypp_deployement.py
file is at the root of stdlib:
import os
import fypp
import argparse
from joblib import Parallel, delayed
def pre_process_toml(kargs):
"""
Pre-process the fpm.toml
"""
from tomlkit import table, dumps
data = table()
data.add("name", "stdlib")
data.add("version", str(kargs.vmajor)+
"."+str(kargs.vminor)+
"."+str(kargs.vpatch) )
data.add("license", "MIT")
data.add("author", "stdlib contributors")
data.add("maintainer", "@fortran-lang/stdlib")
data.add("copyright", "2019-2021 stdlib contributors")
if(kargs.with_blp):
build = table()
build.add("link", ["lapack", "blas"] )
data.add("build", build)
dev_dependencies = table()
dev_dependencies.add("test-drive", {"git" : "https://github.com/fortran-lang/test-drive",
"tag" : "v0.4.0"})
data.add("dev-dependencies", dev_dependencies)
preprocess = table()
preprocess.add("cpp", {} )
preprocess['cpp'].add("suffixes", [".F90", ".f90", ".fypp"] )
preprocess['cpp'].add("macros", ["MAXRANK="+str(kargs.maxrank),
"PROJECT_VERSION_MAJOR="+str(kargs.vmajor),
"PROJECT_VERSION_MINOR="+str(kargs.vminor),
"PROJECT_VERSION_PATCH="+str(kargs.vpatch)] )
data.add("preprocess", preprocess)
with open("fpm.toml", "w") as f:
f.write(dumps(data))
C_PREPROCESSED = (
"stdlib_linalg_constants" ,
"stdlib_linalg_blas" ,
"stdlib_linalg_blas_aux",
"stdlib_linalg_blas_s",
"stdlib_linalg_blas_d",
"stdlib_linalg_blas_q",
"stdlib_linalg_blas_c",
"stdlib_linalg_blas_z",
"stdlib_linalg_blas_w",
"stdlib_linalg_lapack",
"stdlib_linalg_lapack_aux",
"stdlib_linalg_lapack_s",
"stdlib_linalg_lapack_d",
"stdlib_linalg_lapack_q",
"stdlib_linalg_lapack_c",
"stdlib_linalg_lapack_z",
"stdlib_linalg_lapack_w"
)
def pre_process_fypp(kargs):
kwd = []
kwd.append("-DMAXRANK="+str(kargs.maxrank))
kwd.append("-DPROJECT_VERSION_MAJOR="+str(kargs.vmajor))
kwd.append("-DPROJECT_VERSION_MINOR="+str(kargs.vminor))
kwd.append("-DPROJECT_VERSION_PATCH="+str(kargs.vpatch))
if kargs.with_qp:
kwd.append("-DWITH_QP=True")
if kargs.with_xqp:
kwd.append("-DWITH_XQP=True")
optparser = fypp.get_option_parser()
options, leftover = optparser.parse_args(args=kwd)
options.includes = ['include']
# options.line_numbering = True
tool = fypp.Fypp(options)
# Define the folders to search for *.fypp files
folders = ['src', 'test', 'example']
# Process all folders
fypp_files = [os.path.join(root, file) for folder in folders
for root, _, files in os.walk(folder)
for file in files if file.endswith(".fypp")]
def process_f(file):
source_file = file
basename = os.path.splitext(source_file)[0]
sfx = 'f90' if os.path.basename(basename) not in C_PREPROCESSED else 'F90'
target_file = basename + '.' + sfx
tool.process_file(source_file, target_file)
Parallel(n_jobs=kargs.njob)(delayed(process_f)(f) for f in fypp_files)
return
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Preprocess stdlib source files.')
# fypp arguments
parser.add_argument("--vmajor", type=int, default=0, help="Project Version Major")
parser.add_argument("--vminor", type=int, default=4, help="Project Version Minor")
parser.add_argument("--vpatch", type=int, default=0, help="Project Version Patch")
parser.add_argument("--njob", type=int, default=4, help="Number of parallel jobs for preprocessing")
parser.add_argument("--maxrank",type=int, default=7, help="Set the maximum allowed rank for arrays")
parser.add_argument("--with_qp",type=bool, default=False, help="Include WITH_QP in the command")
parser.add_argument("--with_xqp",type=bool, default=False, help="Include WITH_XQP in the command")
# external libraries arguments
parser.add_argument("--with_blp",type=bool, default=False, help="Link against OpenBLAS")
args = parser.parse_args()
pre_process_toml(args)
pre_process_fypp(args)
Example:
python fypp_deployment.py --with_blp 1
Would produce a fpm.toml:
name = "stdlib"
version = "0.4.0"
license = "MIT"
author = "stdlib contributors"
maintainer = "@fortran-lang/stdlib"
copyright = "2019-2021 stdlib contributors"
[build]
link = ["lapack", "blas"]
[dev-dependencies]
[dev-dependencies.test-drive]
git = "https://github.com/fortran-lang/test-drive"
tag = "v0.4.0"
[preprocess]
[preprocess.cpp]
suffixes = [".F90", ".f90", ".fypp"]
macros = ["MAXRANK=7", "PROJECT_VERSION_MAJOR=0", "PROJECT_VERSION_MINOR=4", "PROJECT_VERSION_PATCH=0"]
Current limitations
- In this first example the fypp files are being preprocessed into .f90 files at the same location. Should they go somewhere else?
Metadata
Metadata
Assignees
Labels
ideaProposition of an idea and opening an issue to discuss itProposition of an idea and opening an issue to discuss it