diff --git a/CMakeLists.txt b/CMakeLists.txt index 12d61a67..63b32e03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,16 +6,16 @@ if (CMAKE_VERSION VERSION_GREATER "3.11.99") cmake_policy(SET CMP0074 NEW) endif() -project(slycot VERSION ${SLYCOT_VERSION}) +project(slycot VERSION ${SLYCOT_VERSION} LANGUAGES NONE) # Fortran detection fails on windows, use the CMAKE_C_SIMULATE flag to # force success if(WIN32) set(CMAKE_Fortran_SIMULATE_VERSION 19.0) -# set(CMAKE_Fortran_COMPILER_FORCED TRUE) -# set(CMAKE_C_COMPILER_VERSION 19.0) endif() +# this does not seem to work, maybe scikit-build's doing? the cxx compiler is +# still tested enable_language(C) enable_language(Fortran) diff --git a/conda-recipe-openblas/bld.bat b/conda-recipe-openblas/bld.bat index 372501cb..f5218f4a 100644 --- a/conda-recipe-openblas/bld.bat +++ b/conda-recipe-openblas/bld.bat @@ -2,71 +2,13 @@ cd %RECIPE_DIR% cd .. -:: indicating fortran compiler is essential -set FC=%BUILD_PREFIX%\Library\bin\flang.exe +:: Clear old build attempts +RD /S /Q _skbuild -:: The batch file created by conda-build sets a load of environment variables -:: Building worked fine without conda; apparently one or more of these -:: variables produce test & link failures. Resetting most of these here -set ARCH= -set BUILD= -set BUILD_PREFIX= -set CMAKE_GENERATOR= -set CommandPromptType= -set CPU_COUNT= -set DISTUTILS_USE_SDK= -set folder= -set cpu_optimization_target= -set fortran_compiler= -set Framework40Version= -set FrameworkDir= -set FrameworkDIR64= -set FrameworkVersion= -set FrameworkVersion64= -set ignore_build_only_deps= -set CFLAGS= -set CXXFLAGS= -set cxx_compiler= -set c_compiler= -set INCLUDE= -set LDFLAGS_SHARED= -set LIBPATH= -set LIB=;%LIB% -set MSSdk= -set MSYS2_ARG_CONV_EXCL= -set MSYS2_ENV_CONV_EXCL= -set NETFSXDIR= -set PIP_IGNORE_INSTALLED= -set platform= -set WindowsLibPath= -set WindowsSdkDir= -set CYGWIN_PREFIX= -set SRC_DIR= -set STDLIB_DIR= -set SUBDIR= -set SYS_PREFIX= -set target_platform= -set UCRTVersion= -set UniversalCRTSdkDir= -set VCINSTALLDIR= -set vc= -set win= -set VisualStudioVersion= -set VSINSTALLDIR= -set VSREGKEY= -set VS_MAJOR= -set VS_VERSION= -set VS_YEAR= -set WindowsSDKLibVersion= -set WindowsSDKVersion= -set WindowsSDKExecutablePath_x64= -set WindowsSDKExecutablePath_x86= - -:: information on remaining variables -set - -set BLAS_ROOT=%CONDA_PREFIX% -set LAPACK_ROOT=%CONDA_PREFIX% +set BLAS_ROOT=%PREFIX% +set LAPACK_ROOT=%PREFIX% +set NUMPY_INCLUDE=%PREFIX%\Include +set F2PY=%PREFIX%\Scripts\f2py.exe "%PYTHON%" setup.py install diff --git a/conda-recipe-openblas/build.sh b/conda-recipe-openblas/build.sh index 6868b900..fad66798 100644 --- a/conda-recipe-openblas/build.sh +++ b/conda-recipe-openblas/build.sh @@ -3,7 +3,12 @@ cd $RECIPE_DIR/.. # specify where CMAKE will search for lapack and blas # needs recent cmake (conda's 3.12) and policy CMP0074 NEW -export BLAS_ROOT=${CONDA_PREFIX} -export LAPACK_ROOT=${CONDA_PREFIX} +# the ${PREFIX} points to conda-build's host environment +export BLAS_ROOT=${PREFIX} +export LAPACK_ROOT=${PREFIX} +# ensure we are not building with old cmake files +rm -rf _skbuild + +# do the build $PYTHON setup.py install diff --git a/conda-recipe-openblas/meta.yaml b/conda-recipe-openblas/meta.yaml index 020c0f01..cd90047a 100644 --- a/conda-recipe-openblas/meta.yaml +++ b/conda-recipe-openblas/meta.yaml @@ -1,41 +1,47 @@ package: name: slycot - version: "0.3.3" + version: {{ environ.get('GIT_DESCRIBE_TAG', 'v0.0.0')[1:] }} + +source: + git_url: ../ build: - number: 0 + number: {{ environ.get('GIT_DESCRIBE_NUMBER', 0) }} + string: py{{ environ.get('PY_VER').replace('.', '') }}{{ environ.get('GIT_DESCRIBE_HASH', '') }}_obl_{{ environ.get('GIT_DESCRIBE_NUMBER', 0) }} requirements: - host: - - python {{PY_VER}} - - flang # [win] - - {{ compiler('c') }} # [win] - - {{ compiler('fortran') }} # [not win] - - numpy - - scikit-build >=0.8.0 - build: - - numpy - - libflang # [win] - - libgfortran # [not win] + - python {{ PY_VER }} + - numpy >=1.16 + - openblas >=0.3.0 + - {{ compiler('c') }} # [not osx] + - gcc # [osx] + - {{ compiler('fortran') }} # [linux] + - scikit-build >=0.8.0 + + host: + - python {{ PY_VER }} + - flang # [win] + - numpy >=1.16 - openblas >=0.3.0 + - libgfortran-ng # [not-win] + - libgcc-ng # [linux] + - scikit-build >=0.8.0 # on Windows, this relies on having visual studio CE 2015 # this link needed quite some searching, please do not delete! # https://go.microsoft.com/fwlink/?LinkId=532606&clcid=0x409 run: - - numpy + - python {{ PY_VER }} + - numpy >=1.16 - openblas >=0.3.0 - - libgfortran # [not win] - - libflang # [win] + - libgfortran-ng # [not win] + - libgcc-ng # [linux] + - libflang # [win] test: requires: - - numpy - - openblas - python {{PY_VER}} - - libgfortran # [not win] - - libflang # [win] imports: - slycot @@ -43,3 +49,7 @@ about: home: https://github.com/python-control/slycot license: GPLv2 summary: 'A wrapper for the SLICOT control and systems library' + +# on OSX, the SDK for 10.9 is currently needed +# download the 10.9 sdk from https://github.com/phracker/MacOSX-SDKs/releases +# unpack and set environment variable CONDA_BUILD_SYSROOT to that location diff --git a/conda-recipe/bld.bat b/conda-recipe/bld.bat index c5294765..01aab363 100644 --- a/conda-recipe/bld.bat +++ b/conda-recipe/bld.bat @@ -2,10 +2,14 @@ cd %RECIPE_DIR% cd .. -set F77=%BUILD_PREFIX%\Library\bin\flang.exe -set F90=%BUILD_PREFIX%\Library\bin\flang.exe +:: clean old build attempts +RD /S /Q _skbuild + +set BLAS_ROOT=%PREFIX% +set LAPACK_ROOT=%PREFIX% +set NUMPY_INCLUDE=%PREFIX%\Include +set F2PY=%PREFIX%\Scripts\f2py.exe -"%PYTHON%" setup.py build "%PYTHON%" setup.py install if errorlevel 1 exit 1 diff --git a/conda-recipe/build.sh b/conda-recipe/build.sh index abebc130..fd92a091 100644 --- a/conda-recipe/build.sh +++ b/conda-recipe/build.sh @@ -1,2 +1,15 @@ cd $RECIPE_DIR/.. + +# specify where CMAKE will search for lapack and blas +# needs recent cmake (conda's 3.12) and policy CMP0074 NEW +# the ${PREFIX} points to conda-build's host environment +export BLAS_ROOT=${PREFIX} +export LAPACK_ROOT=${PREFIX} + +# ensure we are not building with old cmake files +rm -rf _skbuild + +env + +# do the build $PYTHON setup.py install diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index d72239b1..6f62c3c6 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -1,41 +1,51 @@ package: name: slycot - version: "0.3.3" + version: {{ environ.get('GIT_DESCRIBE_TAG', 'v0.0.0')[1:] }} + +source: + git_url: ../ build: - number: 0 + number: {{ environ.get('GIT_DESCRIBE_NUMBER', 0) }} + string: py{{ environ.get('PY_VER').replace('.', '') }}{{ environ.get('GIT_DESCRIBE_HASH', '') }}_mkl_{{ environ.get('GIT_DESCRIBE_NUMBER', 0) }} requirements: - host: + # note: the osx build is with gcc for now, due to problems with the + # conda-supplied clang and library linking see e.g. + # https://github.com/conda-forge/mpi-feedstock issue #4 + # conda-forge might have the configuration in place for clang build and link? + build: - python {{PY_VER}} - - numpy - - flang # [win] - - {{ compiler('c') }} # [win] - - {{ compiler('fortran') }} # [not win] - - scikit-build >=0.8.0 + - numpy >=1.16 + - {{ compiler('c') }} # [not osx] + - gcc # [osx] + - {{ compiler('fortran') }} # [linux] + - scikit-build >=0.8.0 - build: - - numpy - - libflang # [win] - - libgfortran # [not win] - - lapack + host: + - python {{ PY_VER }} + - flang # [win] + - numpy >=1.16 + - mkl + - libgfortran-ng # [not win] + - libgcc-ng # [linux] + - libflang # [win] + - scikit-build >=0.8.0 # on Windows, this relies on having visual studio CE 2015 # this link needed quite some searching, please do not delete! # https://go.microsoft.com/fwlink/?LinkId=532606&clcid=0x409 run: - - numpy - - lapack - - libgfortran # [not win] - - libflang # [win] + - python {{ PY_VER }} + - numpy >=1.16 + - mkl + - libgfortran-ng # [not win] + - libgcc-ng # [linux] + - libflang # [win] test: requires: - - numpy - - lapack - python {{PY_VER}} - - libgfortran # [not win] - - libflang # [win] imports: - slycot diff --git a/setup.py b/setup.py index d015cddd..9d50bd33 100644 --- a/setup.py +++ b/setup.py @@ -42,14 +42,11 @@ Operating System :: MacOS """ -MAJOR = 0 -MINOR = 3 -MICRO = 4 -POST = 0 +# defaults ISRELEASED = False -VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO) -if POST != 0: - VERSION += '-post{:d}'.format(POST) +# assume a version set by conda, next update with git, +# otherwise count on default +VERSION = '0.3.3' # Return the git revision as a string def git_version(srcdir=None): @@ -72,12 +69,19 @@ def _minimal_ext_cmd(cmd, srcdir): return out try: + GIT_VERSION = VERSION + GIT_REVISION = 'Unknown' + CIT_CYCLE = 0 out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD'], srcdir) GIT_REVISION = out.strip().decode('ascii') + out = _minimal_ext_cmd(['git', 'tag'], srcdir) + GIT_VERSION = out.strip().decode('ascii').split('\n')[-1][1:] + out = _minimal_ext_cmd(['git', 'describe', '--tags'], srcdir) + GIT_CYCLE = out.strip().decode('ascii').split('-')[1] except OSError: - GIT_REVISION = "Unknown" + pass - return GIT_REVISION + return GIT_VERSION, GIT_REVISION, GIT_CYCLE # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly # update it when the contents of directories change. @@ -91,13 +95,19 @@ def _minimal_ext_cmd(cmd, srcdir): builtins.__SLYCOT_SETUP__ = True -def get_version_info(): +def get_version_info(srcdir=None): + global ISRELEASED + # Adding the git rev number needs to be done inside write_version_py(), # otherwise the import of slycot.version messes up # the build under Python 3. - FULLVERSION = VERSION - if os.path.exists('.git'): - GIT_REVISION = git_version() + if os.environ.get('CONDA_BUILD', False): + FULLVERSION = os.environ.get('PKG_VERSION', '???') + GIT_REVISION = '' + GIT_CYCLE = 0 + ISRELEASED = True + elif os.path.exists('.git'): + FULLVERSION, GIT_REVISION, GIT_CYCLE = git_version(srcdir) elif os.path.exists('slycot/version.py'): # must be a source distribution, use existing version file try: @@ -107,38 +117,14 @@ def get_version_info(): "slycot/version.py and the build directory " "before building.") else: + FULLVERSION = VERSION GIT_REVISION = "Unknown" if not ISRELEASED: - FULLVERSION += '.dev-' + GIT_REVISION[:7] + FULLVERSION += '.' + str(GIT_CYCLE) return FULLVERSION, GIT_REVISION - -def write_version_py(filename='slycot/version.py'): - cnt = """ -# THIS FILE IS GENERATED FROM SLYCOT SETUP.PY -short_version = '%(version)s' -version = '%(version)s' -full_version = '%(full_version)s' -git_revision = '%(git_revision)s' -release = %(isrelease)s - -if not release: - version = full_version -""" - FULLVERSION, GIT_REVISION = get_version_info() - - a = open(filename, 'w') - try: - a.write(cnt % {'version': VERSION, - 'full_version': FULLVERSION, - 'git_revision': GIT_REVISION, - 'isrelease': str(ISRELEASED)}) - finally: - a.close() - - def configuration(parent_package='', top_path=None): from numpy.distutils.misc_util import Configuration config = Configuration(None, parent_package, top_path) @@ -190,11 +176,11 @@ def setup_package(): sys.path.insert(0, src_path) # Rewrite the version file everytime - #write_version_py(src_path+'/slycot/version.py') - gitrevision = git_version(src_path) + VERSION, gitrevision = get_version_info(src_path) metadata = dict( name='slycot', + cmake_languages=('C', 'Fortran'), version=VERSION, maintainer="Slycot developers", maintainer_email="python-control-discuss@lists.sourceforge.net", @@ -220,16 +206,36 @@ def setup_package(): # tools have improved, most of this might be removed? import platform if platform.system() == 'Windows': + pbase = r'/'.join(sys.executable.split(os.sep)[:-1]) + env2cmakearg = { + 'FC': ('-DCMAKE_Fortran_COMPILER=', + pbase + r'/Library/bin/flang.exe'), + 'F2PY': ('-DF2PY_EXECUTABLE=', + pbase + r'/Scripts/f2py.exe'), + 'NUMPY_INCLUDE': ('-DNumPy_INCLUDE_DIR=', + pbase + r'/Include') + } + + metadata['cmake_args'].extend([ + '-GNMake Makefiles']) + + for k, v in env2cmakearg.items(): + print(k, v, os.environ.get(k, '')) + envval = os.environ.get(k, None) + if envval: + # get from environment + metadata['cmake_args'].append( + v[0] + envval.replace('\\', '/')) + else: + # default + metadata['cmake_args'].append(v[0] + v[1]) + metadata['cmake_args'].extend([ - '-GNMake Makefiles', - '-DF2PY_EXECUTABLE=' + pbase + r'/Scripts/f2py.bat', - '-DCMAKE_Fortran_COMPILER=' + pbase + r'/Library/bin/flang.exe', + '-DCMAKE_Fortran_SIMULATE_VERSION=5.0.0', '-DCMAKE_Fortran_COMPILER_ID=Flang', - '-DCMAKE_C_COMPILER_ID=MSVC', - '-DCMAKE_C_COMPILER_VERSION=19.0.0', - '-DNumPy_INCLUDE_DIR=' + pbase + r'/Include', '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON' ]) + print(metadata['cmake_args']) try: setup(**metadata) finally: diff --git a/slycot/setup.py b/slycot/setup.py deleted file mode 100644 index e8a1010d..00000000 --- a/slycot/setup.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python -from __future__ import division, print_function -import glob -import os -import sys -import sysconfig - -def configuration(parent_package='', top_path=None): - from numpy.distutils.misc_util import Configuration - config = Configuration('slycot', parent_package, top_path) - - # can disable building extension to test packaging - build_fortran = True - - if build_fortran: - fortran_sources = glob.glob( - os.path.join('slycot', 'src', '*.f')) - else: - print('WARNING FORTRAN BUILD DISABLED') - fortran_sources = [] - - f2py_sources = ['src/_wrapper.pyf'] - - pyver = sysconfig.get_config_var('VERSION') - - if sys.platform == 'win32': - liblist = [ 'openblas', 'flang' ] - extra_objects = [ ] - ppath = os.sep.join(sys.executable.split(os.sep)[:-1]) - - library_dirs = [r'\Library\lib', ] - library_dirs = [ppath + l for l in library_dirs] - extra_link_args = [ ] - extra_compile_args = [ ] - else: - # this is needed on Py 3.x, and fails on Py 2.7 - try: - abiflags = sys.abiflags - except AttributeError: - abiflags = '' - extra_objects = [] - ppath = os.sep.join(sys.executable.split(os.sep)[:-2]) - library_dirs = [r'/lib', ] - library_dirs = [ppath + l for l in library_dirs] - if sys.platform == 'darwin': - liblist = ['openblas' ] - extra_link_args = [ '-Wl,-dylib,-undefined,dynamic_lookup' ] - extra_compile_args = [ '-fPIC' ] - else: - liblist = ['openblas'] - extra_link_args = [ '-shared', '-Wl,--allow-shlib-undefined' ] - extra_compile_args = [ '-fPIC' ] - - # override when libraries have been specified - if os.environ.get("LAPACKLIBS", None): - liblist = os.environ.get("LAPACKLIBS").split(':') - print("Overriding library list with", liblist) - - config.add_extension( - name='_wrapper', - libraries=liblist, - extra_objects=extra_objects, - extra_link_args=extra_link_args, - library_dirs=library_dirs, - extra_compile_args=extra_compile_args, - sources=fortran_sources + f2py_sources) - - config.make_config_py() # installs __config__.py - - config.add_subpackage('tests') - - return config - -if __name__ == '__main__': - print('This is the wrong setup.py file to run')