diff --git a/conda.recipe/build.sh b/conda.recipe/build.sh index 4c22600f..089ec8e8 100644 --- a/conda.recipe/build.sh +++ b/conda.recipe/build.sh @@ -1,6 +1,11 @@ #!/usr/bin/env bash set -ex +sed -i "s^use_MKL=^use_MKL=True^g" setup.cfg +sed -i "s^MKLROOT=^MKLROOT=${CONDA_PREFIX}/lib^g" setup.cfg + + # Install the Python package, but without dependencies, # because Conda takes care of that -$PYTHON -m pip install . --no-deps --ignore-installed --no-cache-dir -vvv \ No newline at end of file +$PYTHON -m pip install . --no-deps --ignore-installed --no-cache-dir -vvv +sed -i "s^MKLROOT=${CONDA_PREFIX}/lib^MKLROOT=^g" setup.cfg \ No newline at end of file diff --git a/conda.recipe/conda_build_config.yaml b/conda.recipe/conda_build_config.yaml index 87fed87a..599b3af6 100644 --- a/conda.recipe/conda_build_config.yaml +++ b/conda.recipe/conda_build_config.yaml @@ -3,3 +3,7 @@ python: - 3.9 - 3.10 - 3.11 + +mpi: + - mpich # [not win] + - msmpi # [win] \ No newline at end of file diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml index cf6401e1..cbce27f7 100644 --- a/conda.recipe/meta.yaml +++ b/conda.recipe/meta.yaml @@ -18,13 +18,14 @@ requirements: - pip - setuptools - numpy - - blas-devel - - liblapack - mpi4py + - {{ mpi }} + - mkl-static build: - make # [not win] - {{ compiler('c') }} - {{ compiler('fortran') }} # [not win] + - cmake run: - python - {{ pin_compatible('numpy') }} @@ -36,5 +37,5 @@ about: description: | pyPDAF is a python interface to the Fortran-based PDAF library license: GPL - doc_url: https://github.com/BoldingBruggeman/eat/wiki - dev_url: https://github.com/BoldingBruggeman/eat \ No newline at end of file + doc_url: https://yumengch.github.io/pyPDAF/index.html + dev_url: https://github.com/yumengch/pyPDAF \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index f215616a..31cc6cb3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -24,5 +24,14 @@ CPP_DEFS = -DUSE_PDAF [pyPDAF] pwd = /home/runner/work/pyPDAF/pyPDAF/ CC = mpicc +# if MKL is used, give the path to the static MKL library +use_MKL= +MKLROOT= +# if dynamic/shared liblapack and libblas library is used, +# give the library path and flags LAPACK_PATH= -LAPACK_Flag=lapack,blas +LAPACK_Flag= +# GIVE MPI information +MPI_INC_PATH= +MPI_MOD_PATH= +MPI_LIB_PATH= diff --git a/setup.py b/setup.py index eef9e756..c1d33f50 100644 --- a/setup.py +++ b/setup.py @@ -45,6 +45,7 @@ if not os.path.isabs(PDAFdir): PDAFdir = os.path.join(pwd, PDAFdir) print ('input PDAF directory is not absolute path, changing to: ', PDAFdir) + # set up C compiler for cython and Python if os.name == 'nt': compiler = 'msvc' @@ -67,78 +68,80 @@ else: print ('....using GNU compiler....') -# compiler options for cython extra_compile_args=[] +extra_link_args = [] +extra_objects = [] +library_dirs=[] +libraries = [] + +# compiler options for cython if compiler == 'gnu': extra_compile_args+=['-Wno-unreachable-code-fallthrough'] + # linking static PDAF library and interface objects -extra_objects = [] -if sys.platform == 'darwin': - extra_objects+=['-Wl,-force_load', f'{PDAFdir}/lib/libpdaf-var.a', - '-Wl,-force_load', f'{pwd}/lib/libPDAFc.a',] -elif os.name != 'nt': - extra_objects+=['-Wl,--whole-archive', f'{PDAFdir}/lib/libpdaf-var.a', - f'{pwd}/lib/libPDAFc.a', '-Wl,--no-whole-archive'] +if os.name == 'nt': + library_dirs+=[os.path.join(PDAFdir, 'lib', 'Release'), + os.path.join(pwd, 'pyPDAF', 'fortran', 'build', 'Release'), + ] + libraries += ['pdaf-var', 'pdafc'] +else: + if sys.platform == 'darwin': + extra_objects+=['-Wl,-force_load', f'{PDAFdir}/lib/libpdaf-var.a', + '-Wl,-force_load', f'{pwd}/lib/libPDAFc.a',] + else: + extra_objects+=['-Wl,--whole-archive', f'{PDAFdir}/lib/libpdaf-var.a', + f'{pwd}/lib/libPDAFc.a', '-Wl,--no-whole-archive'] -if compiler == 'intel': +# linking BLAS/LAPACK +use_MKL=dist.get_option_dict('pyPDAF')['use_MKL'][1] +if use_MKL == 'True': MKLROOT=dist.get_option_dict('pyPDAF')['MKLROOT'][1] - extra_objects+=['-Wl,--start-group', - f'{MKLROOT}/lib/intel64/libmkl_intel_lp64.a', - f'{MKLROOT}/lib/intel64/libmkl_sequential.a', - f'{MKLROOT}/lib/intel64/libmkl_core.a', - '-Wl,--end-group'] + if os.name == 'nt': + extra_objects+=['-Wl,--start-group', + f'{MKLROOT}/libmkl_intel_lp64.a', + f'{MKLROOT}/libmkl_sequential.a', + f'{MKLROOT}/libmkl_core.a', + '-Wl,--end-group'] + else: + library_dirs+=[MKLROOT,] + libraries = ['mkl_core', 'mkl_sequential', 'mkl_intel_lp64'] +else: + # setup library to MPI-fortran + LAPACK_PATH=dist.get_option_dict('pyPDAF')['LAPACK_PATH'][1] + if LAPACK_PATH != '': library_dirs += LAPACK_PATH.split(',') + LAPACK_Flag=dist.get_option_dict('pyPDAF')['LAPACK_Flag'][1] + print ('LAPACK_Flag', LAPACK_Flag) + if LAPACK_Flag != '': libraries += LAPACK_Flag.split(',') -# PDAF library contains multiple same .o files -# multiple-definition is thus necessary -extra_link_args = [] -# setup library to MPI-fortran -LAPACK_PATH=dist.get_option_dict('pyPDAF')['LAPACK_PATH'][1] -print ('LAPACK_PATH', LAPACK_PATH) -library_dirs=[] -if LAPACK_PATH != '': library_dirs += LAPACK_PATH.split(',') # add mpi library path -if os.name != 'nt': - if compiler == 'intel': - result = subprocess.run(['mpiifort', '-show'], stdout=subprocess.PIPE) - else: - result = subprocess.run(['mpifort', '-show'], stdout=subprocess.PIPE) +if os.name == 'nt': + MPI_LIB_PATH=dist.get_option_dict('pyPDAF')['MPI_LIB_PATH'][1] + library_dirs+=[MPI_LIB_PATH,] + libraries += ['msmpi', 'msmpifec'] +else: + mpifortran = 'mpiifort' if compiler == 'intel' else 'mpifort' + result = subprocess.run([mpifortran, '-show'], stdout=subprocess.PIPE) result = result.stdout.decode()[:-1].split(' ') s = [l[2:].replace('"', '') for l in result if l[:2] == '-L'] if len(s) > 0: library_dirs += s - # add gfortran library path - if sys.platform == 'darwin': - result = subprocess.run(['gfortran', '--print-file', 'libgfortran.dylib'], stdout=subprocess.PIPE) - result = result.stdout.decode()[:-18] - else: - result = subprocess.run(['gfortran', '--print-file', 'libgfortran.so'], stdout=subprocess.PIPE) - result = result.stdout.decode()[:-15] - library_dirs+=[result,] - library_dirs+=['/usr/lib', ] -else: - library_dirs+=[os.path.join(PDAFdir, 'lib', 'Release'), - os.path.join(pwd, 'pyPDAF', 'fortran', 'build', 'Release'), - ] -print ('library_dirs', library_dirs) + s = [l[2:] for l in result if l[:2] == '-l'] + if len(s) > 0: libraries += s +# add fortran library to the linking if os.name != 'nt': - if compiler == 'intel': - # somehow gfortran is always necessary - libraries = ['ifcore', 'ifcoremt', 'gfortran', 'm'] - else: - libraries=['gfortran', 'm'] + suffix = 'dylib' if sys.platform == 'darwin' else 'so' + result = subprocess.run(['gfortran', '--print-file', 'libgfortran.'+suffix], stdout=subprocess.PIPE) + result = result.stdout.decode()[:-18] if sys.platform == 'darwin' else result.stdout.decode()[:-15] + library_dirs+=[result,] + library_dirs+=['/usr/lib', ] + # somehow gfortran is always necessary + libraries += ['gfortran', 'm'] + if compiler == 'intel': libraries += ['ifcore', 'ifcoremt'] - if compiler == 'intel': - result = subprocess.run(['mpiifort', '-show'], stdout=subprocess.PIPE) - else: - result = subprocess.run(['mpifort', '-show'], stdout=subprocess.PIPE) - result = result.stdout.decode()[:-1].split(' ') - s = [l[2:] for l in result if l[:2] == '-l'] - if len(s) > 0: libraries += s -else: - libraries = ['msmpi', 'msmpifec', 'pdaf-var', 'pdafc', 'mkl_core', 'mkl_sequential', 'mkl_intel_lp64'] -LAPACK_Flag=dist.get_option_dict('pyPDAF')['LAPACK_Flag'][1] -print ('LAPACK_Flag', LAPACK_Flag) -if LAPACK_Flag != '': libraries += LAPACK_Flag.split(',') +print ('extra_compile_args', extra_compile_args) +print ('extra_link_args', extra_link_args) +print ('extra_objects', extra_objects) +print ('library_dirs', library_dirs) print ('libraries', libraries) def compilePDAFLibraryInterface(): diff --git a/setup_intel.cfg b/setup_intel.cfg deleted file mode 100644 index 3bceab74..00000000 --- a/setup_intel.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[PDAF] -# PDAF source file directory -directory= PDAF_V2.1 -# fortran compiler -FC = mpiifort -# fortran linker -LD = mpiifort -AR = ar -RANLIB = ranlib -CPP = cpp -OPT = -O3 -r8 -fPIC -OPT_LNK = -INC = -IPDAF_V2.1/include -LINK_LIBS = -llapack -lblas -CPP_DEFS = -DUSE_PDAF - -[pyPDAF] -pwd = /scratch/local/yumeng/testpyPDAF/pyPDAF -CC = mpiicc -MKLROOT=/opt/intel/oneapi/mkl/2022.0.2 -LAPACK_PATH=/opt/intel/oneapi/mkl/2022.0.2/lib/intel64 -LAPACK_Flag=mkl_intel_lp64,mkl_sequential,mkl_core,pthread,m,dl diff --git a/setup_mac.cfg b/setup_mac.cfg index f6d17fef..09d46f9b 100644 --- a/setup_mac.cfg +++ b/setup_mac.cfg @@ -35,5 +35,14 @@ CPP_DEFS = -DUSE_PDAF [pyPDAF] pwd = /Users/runner/work/pyPDAF/pyPDAF/ CC = mpicc +# if MKL is used, give the path to the static MKL library +use_MKL= +MKLROOT= +# if dynamic/shared liblapack and libblas library is used, +# give the library path and flags LAPACK_PATH= -LAPACK_Flag=lapack,blas \ No newline at end of file +LAPACK_Flag= +# GIVE MPI information +MPI_INC_PATH= +MPI_MOD_PATH= +MPI_LIB_PATH=