Skip to content

Commit

Permalink
update(meson): make meson the default build tool
Browse files Browse the repository at this point in the history
* remove SUTRA from list of usgsprograms because of issues with meson build
  • Loading branch information
jdhughes-usgs committed Jun 13, 2024
1 parent 5e9e1b9 commit b6e6380
Show file tree
Hide file tree
Showing 22 changed files with 241 additions and 583 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ python mymf6script.py -fc ifort -cc icc

When pymake is installed, a `make-program` (or `make-program.exe` for Windows) program is installed. `make-program` can
be used to build MODFLOW 6, MODFLOW-2005, MODFLOW-NWT, MODFLOW-USG, MODFLOW-LGR, MODFLOW-2000, MODPATH 6, MODPATH 7,
GSFLOW, VS2DT, MT3DMS, MT3D-USGS, SEAWAT, and SUTRA. Utility programs CRT, Triangle, and GRIDGEN can also
GSFLOW, VS2DT, MT3DMS, MT3D-USGS, and SEAWAT. Utility programs CRT, Triangle, and GRIDGEN can also
be built. `make-program` downloads the distribution file (requires an internet connection), unzips the file, sets the
pymake settings required to build the program, and compiles the program from the source files. Optional pymake command
line arguments can be used to customize the build (`-fc`, `-cc`, `--fflags`, etc.). For example, MODFLOW 6 could be
Expand Down
54 changes: 28 additions & 26 deletions autotest/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
]
test_ostag = get_ostag()
test_fc_env = os.environ.get("FC")
if "win" in test_ostag:
meson_exclude = ("mt3dms", "vs2dt", "triangle", "gridgen", "sutra")
elif "win" not in test_ostag and test_fc_env in ("ifort",):
meson_exclude = ("mf2000", "mf2005", "swtv4", "mflgr", "sutra")
else:
meson_exclude = ("sutra",)
meson_exclude = tuple()
# if "win" in test_ostag:
# meson_exclude = ("mt3dms", "vs2dt", "triangle", "gridgen")
# elif "win" not in test_ostag and test_fc_env in ("ifort",):
# meson_exclude = ("mf2000", "mf2005", "swtv4", "mflgr")
# else:
# meson_exclude = tuple()
targets_meson = [t for t in targets if t not in meson_exclude]


Expand Down Expand Up @@ -61,26 +62,6 @@ def build_with_makefile(target, path, fc):
return success, errmsg


@pytest.mark.base
@flaky(max_runs=RERUNS)
@pytest.mark.parametrize("target", targets)
def test_build(function_tmpdir, target: str) -> None:
with set_dir(function_tmpdir):
pm = pymake.Pymake(verbose=True)
pm.target = target
pm.inplace = True
fc = os.environ.get("FC", "gfortran")
assert (
pymake.build_apps(
target,
pm,
verbose=True,
clean=False,
)
== 0
), f"could not compile {target}"


@pytest.mark.base
@flaky(max_runs=RERUNS)
@pytest.mark.parametrize("target", targets_meson)
Expand Down Expand Up @@ -121,3 +102,24 @@ def test_makefile_build(function_tmpdir, target: str) -> None:

success, errmsg = build_with_makefile(target, function_tmpdir, pm.fc)
assert success, errmsg


@pytest.mark.base
@flaky(max_runs=RERUNS)
@pytest.mark.parametrize("target", targets)
def test_build(function_tmpdir, target: str) -> None:
with set_dir(function_tmpdir):
pm = pymake.Pymake(verbose=True)
pm.target = target
pm.inplace = True
fc = os.environ.get("FC", "gfortran")
assert (
pymake.build_apps(
target,
pm,
verbose=True,
clean=False,
meson=False,
)
== 0
), f"could not compile {target}"
49 changes: 21 additions & 28 deletions autotest/test_gridgen.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import os
import pathlib as pl
import subprocess
from os import environ
from platform import system

import pytest
from modflow_devtools.misc import set_dir

import pymake

Expand All @@ -22,20 +23,7 @@ def prog_data(target) -> dict:

@pytest.fixture(scope="module")
def workspace(module_tmpdir, prog_data) -> pl.Path:
return module_tmpdir / prog_data.dirname


@pytest.fixture(scope="module")
def pm(module_tmpdir, target) -> pymake.Pymake:
pm = pymake.Pymake(verbose=True)
pm.target = str(target)
pm.appdir = str(module_tmpdir)
pm.cc = environ.get("CXX", "g++")
pm.fc = None
pm.inplace = True
pm.makeclean = True
yield pm
pm.finalize()
return module_tmpdir / f"temp/{prog_data.dirname}"


def run_command(args, cwd):
Expand All @@ -58,17 +46,22 @@ def run_gridgen(cmd, ws, exe):
return run_command(args, ws) == 0


@pytest.mark.dependency(name="download")
@pytest.mark.base
def test_download(pm, module_tmpdir, target):
pm.download_target(target, download_path=module_tmpdir)
assert pm.download, f"could not download {target} distribution"


@pytest.mark.dependency(name="build", depends=["download"])
@pytest.mark.base
def test_compile(pm, target):
assert pm.build() == 0, f"could not compile {target}"
@pytest.mark.dependency(name="build")
@pytest.mark.regression
def test_compile(module_tmpdir, target):
cc = os.environ.get("CC", "g++")
fc = None
pymake.linker_update_environment(cc=cc, fc=fc)
with set_dir(module_tmpdir):
assert (
pymake.build_apps(
target.stem,
verbose=True,
clean=False,
meson=True,
)
== 0
), f"could not compile {target.stem}"


@pytest.mark.dependency(name="test", depends=["build"])
Expand All @@ -89,7 +82,7 @@ def test_compile(pm, target):
"grid02qtg-to-vtkfilesv action05_vtkfile.dfn",
],
)
def test_gridgen(cmd, workspace, target):
def test_gridgen(module_tmpdir, cmd, workspace, target):
assert run_gridgen(
cmd, workspace / "examples" / "biscayne", target
cmd, workspace / "examples" / "biscayne", module_tmpdir / target
), f"could not run {cmd}"
42 changes: 19 additions & 23 deletions autotest/test_mf2005.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import os
import sys
from pathlib import Path

import flopy
import pytest
from modflow_devtools.misc import set_dir

import pymake

Expand All @@ -22,18 +24,7 @@ def prog_data(target) -> dict:

@pytest.fixture(scope="module")
def workspace(module_tmpdir, prog_data) -> Path:
return module_tmpdir / prog_data.dirname


@pytest.fixture(scope="module")
def pm(module_tmpdir, target) -> pymake.Pymake:
pm = pymake.Pymake(verbose=True)
pm.target = str(target)
pm.appdir = str(module_tmpdir)
pm.fflags = "-O3"
pm.cflags = "-O3"
yield pm
pm.finalize()
return module_tmpdir / f"temp/{prog_data.dirname}"


def run_mf2005(namefile, ws, exe):
Expand All @@ -42,17 +33,22 @@ def run_mf2005(namefile, ws, exe):
return success


@pytest.mark.dependency(name="download")
@pytest.mark.base
def test_download(pm, module_tmpdir, target):
pm.download_target(target, download_path=module_tmpdir)
assert pm.download, f"could not download {target}"


@pytest.mark.dependency(name="build", depends=["download"])
@pytest.mark.base
def test_compile(pm, target):
assert pm.build() == 0, f"could not compile {target}"
@pytest.mark.dependency(name="build")
@pytest.mark.regression
def test_compile(module_tmpdir, target):
cc = os.environ.get("CC", "gcc")
fc = os.environ.get("FC", "gfortran")
pymake.linker_update_environment(cc=cc, fc=fc)
with set_dir(module_tmpdir):
assert (
pymake.build_apps(
target.stem,
verbose=True,
clean=False,
meson=True,
)
== 0
), f"could not compile {target.stem}"


@pytest.mark.dependency(name="test", depends=["build"])
Expand Down
123 changes: 17 additions & 106 deletions autotest/test_mf6.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,85 +31,32 @@ def target(module_tmpdir) -> Path:
return module_tmpdir / f"{name}{ext}"


@pytest.fixture(scope="module")
def target_so(module_tmpdir) -> Path:
sharedobject_target = "libmf6"
if sys.platform.lower() == "win32":
sharedobject_target += ".dll"
elif sys.platform.lower() == "darwin":
sharedobject_target += ".dylib"
else:
sharedobject_target += ".so"
return module_tmpdir / sharedobject_target


@pytest.fixture(scope="module")
def prog_data(target) -> dict:
return pymake.usgs_program_data.get_target(target.name)


@pytest.fixture(scope="module")
def workspace(module_tmpdir, prog_data) -> Path:
return module_tmpdir / prog_data.dirname


@pytest.fixture(scope="module")
def pm(module_tmpdir, target) -> pymake.Pymake:
pm = pymake.Pymake(verbose=True)
pm.target = str(target)
pm.appdir = module_tmpdir
pm.makefile = True
pm.makeclean = True
pm.makefiledir = module_tmpdir
pm.inplace = True
pm.networkx = True
pm.verbose = True
yield pm
pm.finalize()


def build_with_makefile(pm, workspace, exe):
exe_path = Path(exe)
success = False
with set_dir(workspace):
if os.path.isfile("makefile"):
# wait to delete on windows
if sys.platform.lower() == "win32":
time.sleep(6)

# clean prior to make
print(f"clean {exe} with makefile")
os.system("make clean")

# build MODFLOW 6 with makefile
print(f"build {exe} with makefile")
return_code = os.system("make")

# test if running on Windows with ifort, if True the makefile
# should fail
if sys.platform.lower() == "win32" and pm.fc == "ifort":
if return_code != 0:
success = True
else:
success = False
# verify that target was made
else:
success = exe_path.is_file()
return module_tmpdir / f"temp/{prog_data.dirname}"

return success


@pytest.mark.dependency(name="download")
@pytest.mark.base
def test_download(pm, module_tmpdir, target):
pm.download_target(target, download_path=module_tmpdir)
assert pm.download, f"could not download {target} distribution"


@pytest.mark.dependency(name="build", depends=["download"])
@pytest.mark.base
def test_compile(pm, target):
assert pm.build() == 0, f"could not compile {target}"
@pytest.mark.dependency(name="build")
@pytest.mark.regression
def test_compile(module_tmpdir, target):
cc = os.environ.get("CC", "gcc")
fc = os.environ.get("FC", "gfortran")
pymake.linker_update_environment(cc=cc, fc=fc)
with set_dir(module_tmpdir):
assert (
pymake.build_apps(
target.stem,
verbose=True,
clean=False,
meson=True,
)
== 0
), f"could not compile {target.stem}"


@pytest.mark.dependency(name="test", depends=["build"])
Expand All @@ -118,39 +65,3 @@ def test_compile(pm, target):
def test_mf6(ws, target):
success, _ = flopy.run_model(target, None, model_ws=ws, silent=False)
assert success, f"could not run {ws}"


@pytest.mark.dependency(name="makefile", depends=["build"])
@pytest.mark.base
def test_makefile(pm, module_tmpdir, target):
assert build_with_makefile(
pm, module_tmpdir, target
), f"could not compile {target} with makefile"


@pytest.mark.dependency(name="shared", depends=["makefile"])
@pytest.mark.base
def test_sharedobject(pm, module_tmpdir, workspace, target_so, prog_data):
# reconfigure pymake object
pm.target = str(target_so)
pm.appdir = module_tmpdir
pm.srcdir = workspace / prog_data.srcdir
pm.srcdir2 = workspace / "src"
pm.excludefiles = [os.path.join(pm.srcdir2, "mf6.f90")]
pm.makefile = True
pm.makeclean = True
pm.sharedobject = True
pm.inplace = True
pm.dryrun = False

# build the target
assert pm.build() == 0, f"could not compile {pm.target}"
assert target_so.is_file()


@pytest.mark.dependency(name="shared_makefile", depends=["shared", "makefile"])
@pytest.mark.base
def test_sharedobject_makefile(pm, module_tmpdir, target_so):
assert build_with_makefile(
pm, module_tmpdir, target_so
), f"could not compile {target_so} with makefile"
Loading

0 comments on commit b6e6380

Please sign in to comment.