11#!/usr/bin/env python3
22
3+ import json
34import os
45import platform
56import shlex
@@ -67,15 +68,12 @@ def __init__(self, build_dir="build", verbose=False):
6768 self .mpi_exec = "mpirun"
6869 self .platform = platform .system ()
6970
70- # Detect MPI implementation to choose compatible flags
71- self .mpi_env_mode = "unknown" # one of: openmpi, mpich, unknown
72- self .mpi_np_flag = "-np"
7371 if self .platform == "Windows" :
74- # MSMPI uses -env and -n
7572 self .mpi_env_mode = "mpich"
7673 self .mpi_np_flag = "-n"
7774 else :
78- self .mpi_env_mode , self .mpi_np_flag = self .__detect_mpi_impl ()
75+ self .mpi_env_mode = "unknown"
76+ self .mpi_np_flag = "-np"
7977
8078 @staticmethod
8179 def __get_project_path ():
@@ -105,18 +103,68 @@ def setup_env(self, ppc_env):
105103 build_dir = project_path / build_dir
106104 self .__build_dir_path = build_dir
107105
108- install_bin_dir = project_path / "install" / "bin"
106+ install_dir = project_path / "install"
107+ install_bin_dir = install_dir / "bin"
109108 if install_bin_dir .exists ():
109+ self .__apply_mpi_runtime_config (install_dir / "ppc_mpi_runtime_env.json" )
110110 self .work_dir = install_bin_dir
111+ self .__detect_configured_mpi ()
111112 return
112113
114+ self .__apply_mpi_runtime_config (build_dir / "ppc_mpi_runtime_env.json" )
113115 bin_dir = build_dir if build_dir .name == "bin" else build_dir / "bin"
114116 if not bin_dir .exists ():
115117 raise FileNotFoundError (
116118 f"Test binaries directory not found: '{ bin_dir } '. "
117119 "Build the project or pass a correct '--build-dir' (e.g. 'build', 'build_seq', or 'build/bin')."
118120 )
119121 self .work_dir = bin_dir
122+ self .__detect_configured_mpi ()
123+
124+ def __prepend_env_path (self , name , value ):
125+ current = self .__ppc_env .get (name )
126+ self .__ppc_env [name ] = (
127+ str (value ) if not current else f"{ value } { os .pathsep } { current } "
128+ )
129+
130+ def __apply_mpi_runtime_config (self , config_path ):
131+ if self .platform == "Windows" :
132+ return
133+
134+ if not config_path .exists ():
135+ raise FileNotFoundError (
136+ f"MPI runtime config not found: '{ config_path } '. "
137+ "Configure CMake with -DPPC_MPI_EXTENSIONS_HOME=/path/to/mpi-extensions-openmpi."
138+ )
139+
140+ with config_path .open (encoding = "utf-8" ) as input_file :
141+ config = json .load (input_file )
142+
143+ env_values = config .get ("env" , {})
144+ for name , value in env_values .items ():
145+ self .__ppc_env [name ] = str (value )
146+
147+ path_prepend = config .get ("path_prepend" )
148+ if path_prepend :
149+ self .__prepend_env_path ("PATH" , path_prepend )
150+
151+ library_path_prepend = config .get ("library_path_prepend" )
152+ if library_path_prepend :
153+ self .__prepend_env_path ("LD_LIBRARY_PATH" , library_path_prepend )
154+ self .__prepend_env_path ("DYLD_LIBRARY_PATH" , library_path_prepend )
155+
156+ mpi_exec = config .get ("mpi_exec" )
157+ if mpi_exec :
158+ mpi_exec_path = Path (mpi_exec )
159+ if not mpi_exec_path .exists ():
160+ raise FileNotFoundError (
161+ f"Configured MPI launcher not found: '{ mpi_exec_path } '"
162+ )
163+ self .mpi_exec = str (mpi_exec_path )
164+
165+ def __detect_configured_mpi (self ):
166+ if self .platform != "Windows" :
167+ self .mpi_env_mode , self .mpi_np_flag = self .__detect_mpi_impl ()
120168
121169 def __run_exec (self , command , extra_env = None ):
122170 if self .verbose :
@@ -142,6 +190,7 @@ def __detect_mpi_impl(self):
142190 stdout = subprocess .PIPE ,
143191 stderr = subprocess .STDOUT ,
144192 text = True ,
193+ env = self .__ppc_env ,
145194 )
146195 out = (proc .stdout or "" ).lower ()
147196 if out :
0 commit comments