Skip to content

Commit

Permalink
Compile EPANET on macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
andreArtelt committed Jun 5, 2024
1 parent 93f212a commit 29d88f2
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 6 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,18 @@ Unique features of EPyT-Flow that make it superior to other (Python) toolboxes a
EPyT-Flow supports Python 3.9 - 3.12

Note that [EPANET and EPANET-MSX sources](epyt_flow/EPANET/) are compiled and overwrite the binaries
shipped by EPyT IF EPyT-Flow is installed on a Linux system. By this we not only aim to achieve
a better performance of the simulations but also avoid any compatibility problems of pre-compiled binaries.
shipped by EPyT **IF** EPyT-Flow is installed on a Unix system and the *gcc* compiler is available.
By this we not only aim to achieve a better performance of the simulations but also avoid any
compatibility issues of pre-compiled binaries.

#### Prerequisites for macOS users
The "true" *gcc* compiler (version 12) is needed which is not the
*clang* compiler that is shipped with Xcode and is linked to gcc!

The correct version of the "true" *gcc* can be installed via [brew](https://brew.sh/):
```
brew install gcc@12
```

### PyPI

Expand Down
13 changes: 11 additions & 2 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,17 @@ Note that EPyT-Flow supports Python 3.9 - 3.12
.. note::

EPyT-Flow compiles EPANET and EPANET-MSX libraries (and uses those instead of the pre-compiled
libraries that are shipped with EPyT) if it is installed on a Linux system and if
build tools (i.e. *build-essentials* package) are available.
libraries that are shipped with EPyT) if it is installed on a Unix system and if
the *gcc* compiler is available -- i.e. Linux user can simply install the
*build-essentials* package.

**Attention macOS users:** The "true" *gcc* compiler (version 12) is needed which is not the
*clang* compiler that is shipped with Xcode and is linked to gcc!
The correct version of the "true" *gcc* can be installed via `brew <https://brew.sh/>`_:

.. code:: bash
brew install gcc@12
PyPI
----
Expand Down
4 changes: 4 additions & 0 deletions epyt_flow/EPANET/compile_macos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
mkdir -p "../customlibs/"
gcc-12 -w -O3 -march=native -dynamiclib -fPIC -install_name libepanet2_2.dylib -o "../customlibs/libepanet2_2.dylib" EPANET/SRC_engines/*.c -IEPANET/SRC_engines/include -lc -lm -pthread
gcc-12 -w -O3 -march=native -dynamiclib -fPIC -install_name libepanetmsx2_2_0.dylib -o "../customlibs/libepanetmsx2_2_0.dylib" -fopenmp -Depanetmsx_EXPORTS -IEPANET-MSX/Src/include -IEPANET/SRC_engines/include EPANET-MSX/Src/*.c -L'../customlibs' -lepanet2_2 -lm -lgomp -lpthread
8 changes: 6 additions & 2 deletions epyt_flow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
VERSION = f.read().strip()


def compile_libraries_unix(lib_epanet_name, compile_script_name):
def compile_libraries_unix(lib_epanet_name: str, compile_script_name: str,
gcc_name: str = "gcc") -> None:
"""Compile EPANET and EPANET-MSX libraries if needed."""
path_to_custom_libs = os.path.join(os.path.dirname(__file__), "customlibs")
path_to_lib_epanet = os.path.join(path_to_custom_libs, lib_epanet_name)
Expand All @@ -20,18 +21,21 @@ def compile_libraries_unix(lib_epanet_name, compile_script_name):
update = True

if not os.path.isfile(path_to_lib_epanet) or update:
if shutil.which("gcc") is not None:
if shutil.which(gcc_name) is not None:
print("Compiling EPANET and EPANET-MSX...")
try:
subprocess.check_call(f"cd \"{path_to_epanet}\"; bash {compile_script_name}",
shell=True)
print("Done")
except subprocess.CalledProcessError as ex:
print(f"Compilation failed\n{ex}")
warnings.warn("Falling back to pre-compiled library shipped by EPyT.")
else:
warnings.warn("GCC is not available to compile the required libraries.\n" +
"Falling back to pre-compiled library shipped by EPyT.")


if sys.platform.startswith("linux"):
compile_libraries_unix("libepanet2_2.so", "compile_linux.sh")
elif sys.platform.startswith("darwin"):
compile_libraries_unix("libepanet2_2.dylib", "compile_macos.sh", gcc_name="gcc-12")

0 comments on commit 29d88f2

Please sign in to comment.