Source code for ppafm.cpp_utils
import ctypes
import os
import platform
from pathlib import Path
# Check for environment variable PPAFM_RECOMPILE to determine whether
# we should recompile the C++ extensions.
if "PPAFM_RECOMPILE" in os.environ and os.environ["PPAFM_RECOMPILE"] != "":
_recompile = True
else:
_recompile = False
# Shared libraries are called .dll on Windows and .so on Linux by convention
system = platform.system()
if system == "Windows":
_lib_ext = "_lib.dll"
else:
_lib_ext = "_lib.so"
_vars_path = None
PACKAGE_PATH = Path(__file__).resolve().parent
CPP_PATH = PACKAGE_PATH.joinpath("cpp")
print(" PACKAGE_PATH = ", PACKAGE_PATH)
print(" CPP_PATH = ", CPP_PATH)
cpp_modules = {"PP": "ProbeParticle", "GU": "GridUtils", "fitting": "fitting", "fitSpline": "fitSpline"}
"""Dictionary of C++ extension modules. Keys are targets for make and values are module names."""
[docs]
def get_cdll(module):
"""
Get a handle to a C++ extension module.
Arguments:
module: str. Module to load. Should be one listed in :data:`cpp_modules`.
Returns:
cdll: ctypes.CDLL. Loaded module handle.
"""
if module not in cpp_modules:
raise ValueError(f"Unrecognized module `{module}`. Should be one of {list(cpp_modules.keys())}")
module_path = CPP_PATH / (cpp_modules[module] + _lib_ext)
if _recompile:
_make(module)
elif not module_path.exists():
raise RuntimeError(
f"Could not find compiled extension module in `{module_path}`. "
"Either check pip installation or enable dynamic compilation by setting "
"the environment variable PPAFM_RECOMPILE=1"
)
return ctypes.CDLL(str(module_path)) # Changing to str is required on Windows
def _make(module):
current_directory = Path.cwd()
os.chdir(CPP_PATH)
if system == "Windows":
_build_windows(module)
else:
os.system("make clean")
os.system("make " + module)
os.chdir(current_directory)
def _get_vars_path():
global _vars_path
if _vars_path is None:
vs_path = Path("C:/") / "Program Files (x86)" / "Microsoft Visual Studio"
if not vs_path.exists():
raise RuntimeError("Could not detect Microsoft Visual Studio installation")
vars_paths = list(vs_path.glob("**/VsDevCmd.bat"))
if len(vars_paths) == 0:
raise RuntimeError("Could not find VsDevCmd.bat")
_vars_path = vars_paths[0]
return _vars_path
def _build_windows(target):
vars_path = _get_vars_path()
if target == "all":
targets = cpp_modules.values()
else:
targets = [cpp_modules[target]]
for module in targets:
cmd = f'"{vars_path}" /no_logo /arch=amd64 && cl.exe /openmp /O2 /D_USRDLL /D_WINDLL {module}.cpp /link /dll /out:{module}{_lib_ext}'
print(cmd)
os.system(cmd)