-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy path_compile.py
175 lines (136 loc) · 4.21 KB
/
_compile.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
""" Compile script for Fortran """
import os
import subprocess
import sys
from pathlib import Path
import numpy as np
DEFAULT_FC = "gfortran"
f90_modules = {
"representations/frepresentations": ["frepresentations.f90"],
"representations/facsf": ["facsf.f90"],
"representations/fslatm": ["fslatm.f90"],
"representations/arad/farad_kernels": ["farad_kernels.f90"],
"representations/fchl/ffchl_module": [
"ffchl_kernel_types.f90",
"ffchl_module.f90",
"ffchl_module_ef.f90",
"ffchl_kernels.f90",
"ffchl_scalar_kernels.f90",
"ffchl_kernels_ef.f90",
"ffchl_force_kernels.f90",
],
"solvers/fsolvers": ["fsolvers.f90"],
"kernels/fdistance": ["fdistance.f90"],
"kernels/fkernels": [
"fkernels.f90",
"fkpca.f90",
"fkwasserstein.f90",
],
"kernels/fgradient_kernels": ["fgradient_kernels.f90"],
"utils/fsettings": ["fsettings.f90"],
}
def find_mkl():
raise NotImplementedError()
def find_env() -> dict[str, str]:
"""Find compiler flag"""
"""
For anaconda-like envs
TODO Find MKL
For brew,
brew install llvm libomp
brew install openblas lapack
export LDFLAGS="-L/opt/homebrew/opt/lapack/lib"
export CPPFLAGS="-I/opt/homebrew/opt/lapack/include"
export LDFLAGS="-L/opt/homebrew/opt/libomp/lib"
export CPPFLAGS="-I/opt/homebrew/opt/libomp/include"
"""
fc = os.environ.get("FC", DEFAULT_FC)
# TODO Check if FC is there, not not raise Error
# TODO Check if lapack / blas is there, if not raise Error
# TODO Check if omp is installed
# TODO Find ifort flags, choose from FC
# TODO Find mkl lib
# TODO Check if darwin, check for brew paths
# Default GNU flags
compiler_flags = [
"-O3",
"-m64",
"-march=native",
"-fPIC",
"-Wno-maybe-uninitialized",
"-Wno-unused-function",
"-Wno-cpp",
]
compiler_openmp = [
"-fopenmp",
]
linker_flags = [
"-lpthread",
"-lm",
"-ldl",
]
linker_openmp = [
"-lgomp",
]
linker_math = [
"-lblas",
"-llapack",
"-L/usr/lib/",
]
# MacOS X specific flags
if "darwin" in sys.platform:
expected_omp_dir = Path("/opt/homebrew/opt/libomp/lib")
if expected_omp_dir.is_dir():
compiler_openmp = [
"-fopenmp",
]
linker_openmp = [
f"-L{expected_omp_dir}",
"-lomp",
]
else:
print(f"Expected OpenMP dir not found: {expected_omp_dir}, compiling without OpenMP")
compiler_openmp = []
linker_openmp = []
# FreeBSD specific flags
if "freebsd" in sys.platform:
# Location of BLAS / Lapack for FreeBSD 14
linker_math += ["-L/usr/local/lib/"]
fflags = [] + compiler_flags + compiler_openmp
ldflags = [] + linker_flags + linker_math + linker_openmp
env = {"FFLAGS": " ".join(fflags), "LDFLAGS": " ".join(ldflags), "FC": fc}
return env
def main():
"""Compile f90 in src/qmllib"""
print(
f"Using python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
)
print(f"Using numpy {np.__version__}")
# Find and set Fortran compiler, compiler flags and linker flags
env = find_env()
for key, value in env.items():
print(f"export {key}='{value}'")
os.environ[key] = value
f2py = [sys.executable, "-m", "numpy.f2py"]
meson_flags = [
"--backend",
"meson",
]
for module_name, module_sources in f90_modules.items():
path = Path(module_name)
parent = path.parent
stem = path.stem
cwd = Path("src/qmllib") / parent
cmd = f2py + ["-c"] + module_sources + ["-m", str(stem)] + meson_flags
print(cwd, " ".join(cmd))
proc = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True)
stdout = proc.stdout
stderr = proc.stderr
exitcode = proc.returncode
if exitcode > 0:
print(stderr)
print()
print(stdout)
exit(exitcode)
if __name__ == "__main__":
main()