diff options
| author | Charles BIENVENUE <charles.bienvenue@polymtl.ca> | 2025-11-07 19:18:39 +0000 |
|---|---|---|
| committer | Charles BIENVENUE <charles.bienvenue@polymtl.ca> | 2025-11-07 19:18:39 +0000 |
| commit | eea73a7fc4cd4d586e7ff257974f3b20fb458eff (patch) | |
| tree | 2b0fbc26f0d63e3d379148736db03d95953beecd /PyGan/src/setup_cle2000.py | |
| parent | a64a4c4f9336ccb510a8a01c298da07845dce40b (diff) | |
Issue with make llvm=1 in PyGan/ solved.
Diffstat (limited to 'PyGan/src/setup_cle2000.py')
| -rw-r--r-- | PyGan/src/setup_cle2000.py | 163 |
1 files changed, 156 insertions, 7 deletions
diff --git a/PyGan/src/setup_cle2000.py b/PyGan/src/setup_cle2000.py index c712b26..4b97458 100644 --- a/PyGan/src/setup_cle2000.py +++ b/PyGan/src/setup_cle2000.py @@ -8,7 +8,8 @@ elif version_info[0] > 3: from setuptools import setup, Extension else: from distutils.core import setup, Extension -import sysconfig +import sys +import os def _detect_gfortran_dir(): import subprocess, os @@ -22,13 +23,161 @@ def _detect_gfortran_dir(): pass return None +def _has_any(paths): + for p in paths: + if any(os.path.exists(pfx) for pfx in _expand_suffixes(p)): + return True + return False + +def _expand_suffixes(base): + # Consider common library suffixes across UNIX + # Static is last resort; we prefer shared for Python extension link + exts = ['.dylib', '.so', '.a'] + return [base + ext for ext in exts] + +def _detect_flang_dir(): + """Best-effort detection of the flang/Fortran runtime library directory on UNIX. + Priority order: + 1) FLANGLIB or FLANG_LIBDIR (explicit path) + 2) From LLVMTOOLS (../lib or ../lib64) + 3) llvm-config --libdir + 4) flang-new location heuristic (bin -> lib or sibling llvm lib) + 5) Homebrew (macOS): brew --prefix flang, then /opt/homebrew/opt/flang/lib + 6) Common system locations (/usr/lib, /usr/lib64, /usr/local/lib, /opt/local/lib) + Returns the first directory that appears to contain flang/Fortran runtime libs. + """ + import subprocess + candidates = [] + + # 1) Explicit overrides + for env_name in ('FLANGLIB', 'FLANG_LIBDIR'): + d = os.environ.get(env_name) + if d and os.path.isdir(d): + candidates.append(d) + + # 2) Derive from LLVMTOOLS (often a bin path) + t = os.environ.get('LLVMTOOLS') + if t: + for sub in ('..',): + for libname in ('lib', 'lib64'): + cand = os.path.abspath(os.path.join(t, sub, libname)) + if os.path.isdir(cand): + candidates.append(cand) + + # 3) llvm-config --libdir + try: + libdir = subprocess.check_output(['llvm-config', '--libdir'], text=True).strip() + if os.path.isdir(libdir): + candidates.append(libdir) + except Exception: + pass + + # 4) Locate flang-new executable and probe nearby + try: + fl = subprocess.check_output(['which', 'flang-new'], text=True).strip() + if fl and os.path.isabs(fl): + base = os.path.dirname(os.path.dirname(fl)) # prefix + for libname in ('lib', 'lib64'): + cand = os.path.join(base, libname) + if os.path.isdir(cand): + candidates.append(cand) + except Exception: + pass + + # 5) macOS Homebrew + if sys.platform == 'darwin': + try: + prefix = subprocess.check_output(['brew', '--prefix', 'flang'], text=True).strip() + cand = os.path.join(prefix, 'lib') + if os.path.isdir(cand): + candidates.append(cand) + except Exception: + pass + for cand in ('/opt/homebrew/opt/flang/lib', '/usr/local/opt/flang/lib'): + if os.path.isdir(cand): + candidates.append(cand) + + # 6) Fallback common UNIX lib dirs + for cand in ('/usr/lib', '/usr/lib64', '/usr/local/lib', '/opt/local/lib'): + if os.path.isdir(cand): + candidates.append(cand) + + # Validate candidates by presence of known Fortran runtime libs + def looks_valid(d): + probes = [ + os.path.join(d, 'libFortranRuntime'), + os.path.join(d, 'libFortranDecimal'), + os.path.join(d, 'libflang_rt.runtime'), + os.path.join(d, 'libflang'), + ] + return _has_any(probes) + + seen = set() + for d in candidates: + if not d or d in seen: + continue + seen.add(d) + if looks_valid(d): + return d + return None + +def _compute_flang_link_args(libdir): + """Return a list of extra link args appropriate for the platform and runtime present. + + We prefer the new LLVM flang runtime (FortranRuntime/FortranDecimal). If not present, + fall back to classic flang libraries when detected. On macOS, add clang runtime only when needed. + """ + args = [] + def haslib(name): + if not libdir: + return False + return _has_any([os.path.join(libdir, name)]) + + if haslib('libFortranRuntime') and haslib('libFortranDecimal'): + args += ['-lFortranRuntime', '-lFortranDecimal'] + elif haslib('libflang_rt.runtime') and haslib('libFortranDecimal'): + args += ['-lflang_rt.runtime', '-lFortranDecimal'] + elif haslib('libflang'): + args += ['-lflang'] + if haslib('libflangrti'): + args += ['-lflangrti'] + else: + args += [] + + if sys.platform == 'darwin': + args += ['-lclang_rt.osx'] + return args + +def _compute_openmp_link_args(compiler): + """Return OpenMP runtime link args based on the compiler suite. + + - LLVMTOOLS -> libomp (and Homebrew paths on macOS) + - default (gfortran) -> libgomp + """ + args = [] + if compiler == "LLVMTOOLS": + # LLVM OpenMP + if sys.platform == 'darwin': + # Add Homebrew libomp search and rpath paths for both arm64 and x86_64 + for p in ('/opt/homebrew/opt/libomp/lib', '/usr/local/opt/libomp/lib'): + args += ['-L'+p, '-Wl,-rpath,'+p] + args += ['-lomp'] + else: + # GCC toolchain + args += ['-lgomp'] + return args + def main(): import os from sysconfig import get_config_var mach = os.path.basename(os.getcwd()) Code = os.environ.get("CODE_EMBEDDED", None) # Code selection Compiler = os.environ.get("COMPILER", None) # Compiler selection - FortranLib = _detect_gfortran_dir() # directory with libfortran + # Directory containing Fortran runtime libraries + if Compiler == "LLVMTOOLS": + FortranLib = _detect_flang_dir() + else: + FortranLib = _detect_gfortran_dir() HDF5Lib = os.environ.get("HDF5_API", None) # directory with libhdf5 pylib = os.path.basename(get_config_var("LIBDIR")) # get lib or lib64 print("install Cle2000 binding to", Code, "on directory",mach, "pylib=",pylib, "Compiler=",Compiler) @@ -45,7 +194,7 @@ def main(): libTri="../../../Trivac/lib/"+mach+"_llvm" libDra="../../../Dragon/lib/"+mach+"_llvm" libDon="../../../Donjon/lib/"+mach+"_llvm" - extralink=["-lFortranRuntime", "-lFortranDecimal", "-lclang_rt.osx"] + extralink=_compute_flang_link_args(FortranLib) elif Compiler == "INTELTOOLS": libdir="../../lib/"+mach+"_intel" libUtl="../../../Utilib/lib/"+mach+"_intel" @@ -133,7 +282,7 @@ def main(): author_email="alain.hebert@polymtl.ca", license="LGPL", ext_modules=[Extension('cle2000',sources=['cle2000module.c'], - extra_link_args = ["-lgomp"]+extralink, + extra_link_args = _compute_openmp_link_args(Compiler)+extralink, include_dirs=["../../../Ganlib/src"], library_dirs=_dirs(libdir,FortranLib,HDF5Lib), runtime_library_dirs=_dirs(FortranLib,HDF5Lib), @@ -147,7 +296,7 @@ def main(): license="LGPL", ext_modules=[Extension('cle2000',sources=['cle2000module.c'], define_macros=[('__trivac__', None)], - extra_link_args = ["-lgomp"]+extralink, + extra_link_args = _compute_openmp_link_args(Compiler)+extralink, include_dirs=["../../../Ganlib/src"], library_dirs=_dirs(libdir,FortranLib,HDF5Lib,libUtl,libTri), runtime_library_dirs=_dirs(FortranLib,HDF5Lib), @@ -161,7 +310,7 @@ def main(): license="LGPL", ext_modules=[Extension('cle2000',sources=['cle2000module.c'], define_macros=[('__dragon__', None)], - extra_link_args = ["-lgomp"]+extralink, + extra_link_args = _compute_openmp_link_args(Compiler)+extralink, include_dirs=["../../../Ganlib/src"], library_dirs=_dirs(libdir,FortranLib,HDF5Lib,libUtl,libTri,libDra), runtime_library_dirs=_dirs(FortranLib,HDF5Lib), @@ -175,7 +324,7 @@ def main(): license="LGPL", ext_modules=[Extension('cle2000',sources=['cle2000module.c'], define_macros=[('__donjon__', None)], - extra_link_args = ["-lgomp"]+extralink, + extra_link_args = _compute_openmp_link_args(Compiler)+extralink, include_dirs=["../../../Ganlib/src"], library_dirs=_dirs(libdir,FortranLib,HDF5Lib,libUtl,libTri,libDra,libDon), runtime_library_dirs=_dirs(FortranLib,HDF5Lib), |
