Skip to content

Commit 3e21484

Browse files
committed
start replacement of deployement sh script by python script
1 parent 19f84ce commit 3e21484

File tree

3 files changed

+209
-0
lines changed

3 files changed

+209
-0
lines changed

ci/fpm.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ test-drive.tag = "v0.4.0"
1111

1212
[preprocess]
1313
[preprocess.cpp]
14+
suffixes = [".F90", ".f90"]
15+
macros = ["MAXRANK=7"]

ci/fypp_deployment.py

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
import os
2+
import shutil
3+
import fypp
4+
import argparse
5+
from joblib import Parallel, delayed
6+
7+
def copy_folder_with_filter(source_folder, destination_folder, filter_list=None, filter_suffix=None):
8+
# Create destination folder if it doesn't exist
9+
if not os.path.exists(destination_folder):
10+
os.makedirs(destination_folder)
11+
12+
# Iterate over the files and folders in the source folder
13+
for item in os.listdir(source_folder):
14+
source_item = os.path.join(source_folder, item)
15+
destination_item = os.path.join(destination_folder, item)
16+
17+
# If it's a folder, recursively copy it
18+
if os.path.isdir(source_item):
19+
copy_folder_with_filter(source_item, destination_item, filter_list, filter_suffix)
20+
else:
21+
# If filter_list is provided, check if the filename is in the list to avoid it
22+
should_copy = False if filter_list and item in filter_list else True
23+
should_copy = False if filter_suffix and item.endswith(filter_suffix) else should_copy
24+
if should_copy:
25+
shutil.copy2(source_item, destination_item)
26+
27+
def pre_process_toml(args):
28+
"""
29+
Pre-process the fpm.toml
30+
"""
31+
from tomlkit import table, dumps
32+
data = table()
33+
data.add("name", "stdlib")
34+
data.add("version", str(args.vmajor)+
35+
"."+str(args.vminor)+
36+
"."+str(args.vpatch) )
37+
data.add("license", "MIT")
38+
data.add("author", "stdlib contributors")
39+
data.add("maintainer", "@fortran-lang/stdlib")
40+
data.add("copyright", "2019-2021 stdlib contributors")
41+
42+
if(args.with_blp):
43+
build = table()
44+
build.add("link", ["lapack", "blas"] )
45+
data.add("build", build)
46+
47+
dev_dependencies = table()
48+
dev_dependencies.add("test-drive", {"git" : "https://github.com/fortran-lang/test-drive",
49+
"tag" : "v0.4.0"})
50+
data.add("dev-dependencies", dev_dependencies)
51+
52+
preprocess = table()
53+
preprocess.add("cpp", {} )
54+
preprocess['cpp'].add("suffixes", [".F90", ".f90"] )
55+
preprocess['cpp'].add("macros", ["MAXRANK="+str(args.maxrank)] )
56+
data.add("preprocess", preprocess)
57+
58+
if args.destdir == 'stdlib-fpm':
59+
if not os.path.exists('stdlib-fpm'):
60+
os.makedirs('stdlib-fpm')
61+
name = 'stdlib-fpm'+os.sep+'fpm.toml'
62+
else:
63+
name = "fpm.toml"
64+
with open(name, "w") as f:
65+
f.write(dumps(data))
66+
return
67+
68+
C_PREPROCESSED = (
69+
"stdlib_linalg_constants" ,
70+
"stdlib_linalg_blas" ,
71+
"stdlib_linalg_blas_aux",
72+
"stdlib_linalg_blas_s",
73+
"stdlib_linalg_blas_d",
74+
"stdlib_linalg_blas_q",
75+
"stdlib_linalg_blas_c",
76+
"stdlib_linalg_blas_z",
77+
"stdlib_linalg_blas_w",
78+
"stdlib_linalg_lapack",
79+
"stdlib_linalg_lapack_aux",
80+
"stdlib_linalg_lapack_s",
81+
"stdlib_linalg_lapack_d",
82+
"stdlib_linalg_lapack_q",
83+
"stdlib_linalg_lapack_c",
84+
"stdlib_linalg_lapack_z",
85+
"stdlib_linalg_lapack_w"
86+
)
87+
88+
def pre_process_fypp(args):
89+
kwd = []
90+
kwd.append("-DMAXRANK="+str(args.maxrank))
91+
kwd.append("-DPROJECT_VERSION_MAJOR="+str(args.vmajor))
92+
kwd.append("-DPROJECT_VERSION_MINOR="+str(args.vminor))
93+
kwd.append("-DPROJECT_VERSION_PATCH="+str(args.vpatch))
94+
if args.with_qp:
95+
kwd.append("-DWITH_QP=True")
96+
if args.with_xqp:
97+
kwd.append("-DWITH_XDP=True")
98+
99+
optparser = fypp.get_option_parser()
100+
options, leftover = optparser.parse_args(args=kwd)
101+
options.includes = ['include']
102+
# options.line_numbering = True
103+
tool = fypp.Fypp(options)
104+
105+
# Check destination folder for preprocessing. if not 'stdlib-fpm', it is assumed to be the root folder.
106+
in_place = False if args.destdir == 'stdlib-fpm' else True
107+
src = 'src' if in_place else 'stdlib-fpm'+os.sep+'src'
108+
test = 'test' if in_place else 'stdlib-fpm'+os.sep+'test'
109+
example = 'example' if in_place else 'stdlib-fpm'+os.sep+'example'
110+
if not in_place:
111+
copy_folder_with_filter('src', src,
112+
filter_list=['CMakeLists.txt',"f18estop.f90"])
113+
copy_folder_with_filter('test', test,
114+
filter_list=['CMakeLists.txt',"test_always_fail.f90",
115+
"test_always_skip.f90","test_hash_functions.f90"],
116+
filter_suffix='manual')
117+
copy_folder_with_filter('example',example,
118+
filter_list=['CMakeLists.txt'])
119+
shutil.copy2('ci'+os.sep+'fpm.toml', 'stdlib-fpm'+os.sep+'fpm.toml')
120+
shutil.copy2('LICENSE', 'stdlib-fpm'+os.sep+'LICENSE')
121+
122+
# Define the folders to search for *.fypp files
123+
folders = [src,test]
124+
# Process all folders
125+
fypp_files = [os.path.join(root, file) for folder in folders
126+
for root, _, files in os.walk(folder)
127+
for file in files if file.endswith(".fypp")]
128+
129+
def process_f(file):
130+
source_file = file
131+
root = os.path.dirname(file)
132+
basename = os.path.splitext(os.path.basename(source_file))[0]
133+
sfx = 'f90' if basename not in C_PREPROCESSED else 'F90'
134+
target_file = root + os.sep + basename + '.' + sfx
135+
tool.process_file(source_file, target_file)
136+
# if folder different from root
137+
if not in_place:
138+
os.remove(source_file)
139+
140+
Parallel(n_jobs=args.njob)(delayed(process_f)(f) for f in fypp_files)
141+
142+
return
143+
144+
def fpm_build(unknown):
145+
import subprocess
146+
#==========================================
147+
# check compilers
148+
FPM_FC = os.environ['FPM_FC'] if "FPM_FC" in os.environ else "gfortran"
149+
FPM_CC = os.environ['FPM_CC'] if "FPM_CC" in os.environ else "gcc"
150+
FPM_CXX = os.environ['FPM_CXX'] if "FPM_CXX" in os.environ else "gcc"
151+
#==========================================
152+
# Filter out the macro definitions.
153+
macros = [arg for arg in unknown if arg.startswith("-D")]
154+
# Filter out the include paths with -I prefix.
155+
include_paths = [arg for arg in unknown if arg.startswith("-I")]
156+
# Filter out flags
157+
flags = " "
158+
for idx, arg in enumerate(unknown):
159+
if arg.startswith("--flag"):
160+
flags= unknown[idx+1]
161+
#==========================================
162+
# build with fpm
163+
subprocess.run(["fpm build"]+
164+
[" --compiler "]+[FPM_FC]+
165+
[" --c-compiler "]+[FPM_CC]+
166+
[" --cxx-compiler "]+[FPM_CXX]+
167+
[" --flag "]+[flags], shell=True, check=True)
168+
return
169+
170+
if __name__ == "__main__":
171+
parser = argparse.ArgumentParser(description='Preprocess stdlib source files.')
172+
# fypp arguments
173+
parser.add_argument("--vmajor", type=int, default=0, help="Project Version Major")
174+
parser.add_argument("--vminor", type=int, default=5, help="Project Version Minor")
175+
parser.add_argument("--vpatch", type=int, default=0, help="Project Version Patch")
176+
177+
parser.add_argument("--njob", type=int, default=4, help="Number of parallel jobs for preprocessing")
178+
parser.add_argument("--maxrank",type=int, default=7, help="Set the maximum allowed rank for arrays")
179+
parser.add_argument("--with_qp",type=bool, default=False, help="Include WITH_QP in the command")
180+
parser.add_argument("--with_xqp",type=bool, default=False, help="Include WITH_XDP in the command")
181+
182+
parser.add_argument('--destdir', action='store', type=str, default='stdlib-fpm', help='destination directory for the fypp preprocessing.')
183+
# external libraries arguments
184+
parser.add_argument("--with_blp",type=bool, default=False, help="Link against OpenBLAS")
185+
parser.add_argument("--build",type=bool, default=False, help="Build the project")
186+
187+
args, unknown = parser.parse_known_args()
188+
#==========================================
189+
# read current manifest
190+
import tomlkit
191+
with open('ci'+os.sep+'fpm.toml', 'r') as file:
192+
manifest = tomlkit.parse(file.read())
193+
version = manifest['version'].split(".")
194+
if version != ['VERSION']:
195+
vmajor, vminor, vpatch = [int(value) for value in version]
196+
#==========================================
197+
# pre process the fpm manifest
198+
#pre_process_toml(args)
199+
#==========================================
200+
# pre process the meta programming fypp files
201+
pre_process_fypp(args)
202+
#==========================================
203+
# build using fpm
204+
if args.build:
205+
fpm_build(unknown)

ci/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
fypp
2+
joblib

0 commit comments

Comments
 (0)