Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9eefede

Browse files
authored
Merge pull request #26870 from charris/backport-26703-26706-26812
BUG: Handle --f77flags and --f90flags for meson [wheel build]
2 parents 46d31ce + 526a2f4 commit 9eefede

File tree

7 files changed

+70
-6
lines changed

7 files changed

+70
-6
lines changed

.github/workflows/wheels.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ jobs:
130130
- name: Setup macOS
131131
if: matrix.buildplat[0] == 'macos-13' || matrix.buildplat[0] == 'macos-14'
132132
run: |
133+
# Needed due to https://github.com/actions/runner-images/issues/3371
134+
# Supported versions: https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md
135+
echo "FC=gfortran-13" >> "$GITHUB_ENV"
136+
echo "F77=gfortran-13" >> "$GITHUB_ENV"
137+
echo "F90=gfortran-13" >> "$GITHUB_ENV"
133138
if [[ ${{ matrix.buildplat[2] }} == 'accelerate' ]]; then
134139
# macosx_arm64 and macosx_x86_64 with accelerate
135140
# only target Sonoma onwards

numpy/f2py/_backends/_meson.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def __init__(
2828
include_dirs: list[Path],
2929
object_files: list[Path],
3030
linker_args: list[str],
31-
c_args: list[str],
31+
fortran_args: list[str],
3232
build_type: str,
3333
python_exe: str,
3434
):
@@ -46,12 +46,18 @@ def __init__(
4646
self.include_dirs = []
4747
self.substitutions = {}
4848
self.objects = object_files
49+
# Convert args to '' wrapped variant for meson
50+
self.fortran_args = [
51+
f"'{x}'" if not (x.startswith("'") and x.endswith("'")) else x
52+
for x in fortran_args
53+
]
4954
self.pipeline = [
5055
self.initialize_template,
5156
self.sources_substitution,
5257
self.deps_substitution,
5358
self.include_substitution,
5459
self.libraries_substitution,
60+
self.fortran_args_substitution,
5561
]
5662
self.build_type = build_type
5763
self.python_exe = python_exe
@@ -109,6 +115,14 @@ def include_substitution(self) -> None:
109115
[f"{self.indent}'''{inc}'''," for inc in self.include_dirs]
110116
)
111117

118+
def fortran_args_substitution(self) -> None:
119+
if self.fortran_args:
120+
self.substitutions["fortran_args"] = (
121+
f"{self.indent}fortran_args: [{', '.join([arg for arg in self.fortran_args])}],"
122+
)
123+
else:
124+
self.substitutions["fortran_args"] = ""
125+
112126
def generate_meson_build(self):
113127
for node in self.pipeline:
114128
node()
@@ -126,6 +140,7 @@ def __init__(self, *args, **kwargs):
126140
self.build_type = (
127141
"debug" if any("debug" in flag for flag in self.fc_flags) else "release"
128142
)
143+
self.fc_flags = _get_flags(self.fc_flags)
129144

130145
def _move_exec_to_root(self, build_dir: Path):
131146
walk_dir = Path(build_dir) / self.meson_build_dir
@@ -203,3 +218,17 @@ def _prepare_sources(mname, sources, bdir):
203218
if not Path(source).suffix == ".pyf"
204219
]
205220
return extended_sources
221+
222+
223+
def _get_flags(fc_flags):
224+
flag_values = []
225+
flag_pattern = re.compile(r"--f(77|90)flags=(.*)")
226+
for flag in fc_flags:
227+
match_result = flag_pattern.match(flag)
228+
if match_result:
229+
values = match_result.group(2).strip().split()
230+
values = [val.strip("'\"") for val in values]
231+
flag_values.extend(values)
232+
# Hacky way to preserve order of flags
233+
unique_flags = list(dict.fromkeys(flag_values))
234+
return unique_flags

numpy/f2py/_backends/meson.build.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,5 @@ ${dep_list}
5151
${lib_list}
5252
${lib_dir_list}
5353
],
54+
${fortran_args}
5455
install : true)

numpy/f2py/f2py2e.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -635,10 +635,14 @@ def run_compile():
635635
r'--((f(90)?compiler(-exec|)|compiler)=|help-compiler)')
636636
flib_flags = [_m for _m in sys.argv[1:] if _reg3.match(_m)]
637637
sys.argv = [_m for _m in sys.argv if _m not in flib_flags]
638-
_reg4 = re.compile(
639-
r'--((f(77|90)(flags|exec)|opt|arch)=|(debug|noopt|noarch|help-fcompiler))')
640-
fc_flags = [_m for _m in sys.argv[1:] if _reg4.match(_m)]
641-
sys.argv = [_m for _m in sys.argv if _m not in fc_flags]
638+
# TODO: Once distutils is dropped completely, i.e. min_ver >= 3.12, unify into --fflags
639+
reg_f77_f90_flags = re.compile(r'--f(77|90)flags=')
640+
reg_distutils_flags = re.compile(r'--((f(77|90)exec|opt|arch)=|(debug|noopt|noarch|help-fcompiler))')
641+
fc_flags = [_m for _m in sys.argv[1:] if reg_f77_f90_flags.match(_m)]
642+
distutils_flags = [_m for _m in sys.argv[1:] if reg_distutils_flags.match(_m)]
643+
if not (MESON_ONLY_VER or backend_key == 'meson'):
644+
fc_flags.extend(distutils_flags)
645+
sys.argv = [_m for _m in sys.argv if _m not in (fc_flags + distutils_flags)]
642646

643647
del_list = []
644648
for s in flib_flags:
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
C This is an invalid file, but it does compile with -ffixed-form
2+
subroutine mwe(
3+
& x)
4+
real x
5+
end subroutine mwe

numpy/f2py/tests/test_regression.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import pytest
3+
import platform
34

45
import numpy as np
56
import numpy.testing as npt
@@ -109,6 +110,7 @@ def test_gh26148b(self):
109110
assert(res[0] == 8)
110111
assert(res[1] == 15)
111112

113+
@pytest.mark.slow
112114
def test_gh26623():
113115
# Including libraries with . should not generate an incorrect meson.build
114116
try:
@@ -119,3 +121,21 @@ def test_gh26623():
119121
)
120122
except RuntimeError as rerr:
121123
assert "lparen got assign" not in str(rerr)
124+
125+
126+
@pytest.mark.slow
127+
@pytest.mark.skipif(platform.system() not in ['Linux', 'Darwin'], reason='Unsupported on this platform for now')
128+
def test_gh25784():
129+
# Compile dubious file using passed flags
130+
try:
131+
aa = util.build_module(
132+
[util.getpath("tests", "src", "regression", "f77fixedform.f95")],
133+
options=[
134+
# Meson will collect and dedup these to pass to fortran_args:
135+
"--f77flags='-ffixed-form -O2'",
136+
"--f90flags=\"-ffixed-form -Og\"",
137+
],
138+
module_name="Blah",
139+
)
140+
except ImportError as rerr:
141+
assert "unknown_subroutine_" in str(rerr)

numpy/f2py/tests/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def build_module(source_files, options=[], skip=[], only=[], module_name=None):
121121
dst_sources.append(dst)
122122

123123
base, ext = os.path.splitext(dst)
124-
if ext in (".f90", ".f", ".c", ".pyf"):
124+
if ext in (".f90", ".f95", ".f", ".c", ".pyf"):
125125
f2py_sources.append(dst)
126126

127127
assert f2py_sources

0 commit comments

Comments
 (0)