diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml new file mode 100644 index 00000000..baa4873c --- /dev/null +++ b/.github/workflows/package.yml @@ -0,0 +1,103 @@ +name: Packaging + +# on: [push] +on: + push: + tags: + - '*' + +jobs: + setup: + name: Build SWIG wrappers + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - name: Install numpy + run: python -m pip install numpy + + - run: bash swig/python-packaging/setup.sh + - uses: actions/upload-artifact@v2 + with: + name: my-artifact + path: build/swig/python-packaging/ + - name: List + run: pwd && ls build/swig/python-packaging + + build_wheels: + needs: setup + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + # os: [ubuntu-20.04, windows-2019, macos-11] + os: [ubuntu-20.04, macos-11] + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - name: Install cibuildwheel + run: python -m pip install cibuildwheel==2.13.1 + + - uses: actions/download-artifact@v2 + with: + name: my-artifact + + - name: Build wheels + run: python -m cibuildwheel --output-dir wheelhouse + env: + # Use boost 1_72, since this allows c++11. We need c++11, since manylinux2014 only has gcc 4.8 + # Can't use boost 1.53 (default on linux) because it doesn't have rtree functionality + # CIBW_BUILD: cp36-manylinux_x86_64 cp36-win_amd64 cp36-macosx_x86_64 + # CIBW_BUILD: cp310-macosx_x86_64 + # PyPy compilation on MACOS doesn't work, possibly since there is no available numpy release for this + # Armadillo isn't available for i687 on Centos 7, making compilation more complicated + # # Musllinux doesn't use yum as its package manager + CIBW_SKIP: pp*-macosx* *i686* *musllinux* + CIBW_BEFORE_ALL_LINUX: | + yum install -y lapack-devel armadillo-devel + curl -L -O https://boostorg.jfrog.io/artifactory/main/release/1.72.0/source/boost_1_72_0.tar.gz + tar -xf boost_1_72_0.tar.gz + cd boost_1_72_0 + cp -r boost /usr/include + CIBW_BEFORE_ALL_MACOS: | + # Other than the latest version, Brew only has boost 1.76. Therefore we must install boost from source + # brew reinstall gcc lapack gsl armadillo + brew reinstall lapack armadillo + curl -L -O https://boostorg.jfrog.io/artifactory/main/release/1.72.0/source/boost_1_72_0.tar.gz + tar -xf boost_1_72_0.tar.gz + cd boost_1_72_0 + cp -r boost /usr/local/include + # Link in gcc, otherwise the default Apple compiler will be used, which doesn't support openmp by default + # ln -s /usr/local/bin/gcc-13 /usr/local/bin/gcc + # ln -s /usr/local/bin/g++-13 /usr/local/bin/g++ + # CIBW_ENVIRONMENT_MACOS: CC='/usr/local/bin/gcc' LDSHARED='/usr/local/bin/gcc' CXX='/usr/local/bin/g++' + CIBW_ENVIRONMENT_MACOS: CFLAGS='-Wno-c++11-narrowing' + CIBW_BEFORE_ALL_WINDOWS: choco install -y lapack-devel + CIBW_TEST_COMMAND: > + python {project}/tests/check_installation.py + + - uses: actions/upload-artifact@v3 + with: + name: wheels + path: ./wheelhouse/*.whl + + + pypi-publish: + needs: build_wheels + name: Upload release to PyPI + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v3 + with: + name: wheels + path: wheelhouse + - name: Publish + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: wheelhouse/ + name: pypi + user: __token__ + password: ${{ secrets.PYPI_TOKEN }} + url: https://pypi.org/p/gridpp + skip_existing: true diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ca08f1d..e284b8a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,60 +7,67 @@ string(REGEX REPLACE "^.+define GRIDPP_VERSION \"([^\n]+)\".+" "\\1" PROJECT_VER set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) -# Boost 1.75 and above requires c++14 for the geometry library. For creating the python packages on -# CentOS5, c++11 is more readily available, so this is preferred. -find_package(Boost REQUIRED) -find_package(Armadillo 6.5 REQUIRED) -if(${Boost_MINOR_VERSION} GREATER 74) - set(CMAKE_CXX_STANDARD 14) +option(BUILD_PACKAGE "Build package" OFF) + +if (BUILD_PACKAGE) + else() - set(CMAKE_CXX_STANDARD 11) -endif() + # Boost 1.75 and above requires c++14 for the geometry library. For creating the python packages on + # CentOS5, c++11 is more readily available, so this is preferred. + find_package(Boost REQUIRED) + find_package(Armadillo 6.5 REQUIRED) + if(${Boost_MINOR_VERSION} GREATER 74) + set(CMAKE_CXX_STANDARD 14) + else() + set(CMAKE_CXX_STANDARD 11) + endif() -# Set compiler flags -enable_language(CXX) + # Set compiler flags + enable_language(CXX) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) -if (NOT CMAKE_BUILD_TYPE) - message(STATUS "CMAKE_BUILD_TYPE is not set, switching to RELEASE") - set(CMAKE_BUILD_TYPE "RELEASE" CACHE STRING - "Choose the type of build, options are: NONE DEBUG RELEASE." - FORCE) -endif() -string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_CXX_EXTENSIONS OFF) + if (NOT CMAKE_BUILD_TYPE) + message(STATUS "CMAKE_BUILD_TYPE is not set, switching to RELEASE") + set(CMAKE_BUILD_TYPE "RELEASE" CACHE STRING + "Choose the type of build, options are: NONE DEBUG RELEASE." + FORCE) + endif() + string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) -if(APPLE) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wfatal-errors -Wno-reorder -Wno-unused-variable -Wno-unused-value -Wno-narrowing -Wno-sign-compare -Wno-Wdelete-non-virtual-dtor -Wno-c++11-narrowing") -else() - # SWIG generates a lot of warnings - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wfatal-errors -Wno-reorder -Wno-unused-variable -Wno-unused-value -Wno-narrowing -Wno-sign-compare -Wno-delete-non-virtual-dtor -Wl,-init,initialize_omp") -endif() + if(APPLE) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wfatal-errors -Wno-reorder -Wno-unused-variable -Wno-unused-value -Wno-narrowing -Wno-sign-compare -Wno-Wdelete-non-virtual-dtor -Wno-c++11-narrowing") + else() + # SWIG generates a lot of warnings + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wfatal-errors -Wno-reorder -Wno-unused-variable -Wno-unused-value -Wno-narrowing -Wno-sign-compare -Wno-delete-non-virtual-dtor -Wl,-init,initialize_omp") + endif() -if (CMAKE_BUILD_TYPE MATCHES "DEBUG") - set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fPIC -g -pg -rdynamic --coverage") - set(CMAKE_LFLAGS_DEBUG " --coverage") - add_definitions("-DDEBUG") -elseif(CMAKE_BUILD_TYPE MATCHES "RELEASE") - find_package(OpenMP REQUIRED) - if(APPLE) - set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fPIC") + if (CMAKE_BUILD_TYPE MATCHES "DEBUG") + set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fPIC -g -pg -rdynamic --coverage") + set(CMAKE_LFLAGS_DEBUG " --coverage") + add_definitions("-DDEBUG") + elseif(CMAKE_BUILD_TYPE MATCHES "RELEASE") + find_package(OpenMP REQUIRED) + if(APPLE) + set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fPIC") + else() + set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fPIC ${OpenMP_CXX_FLAGS}") + endif() else() - set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fPIC ${OpenMP_CXX_FLAGS}") + message(FATAL_ERROR "Unknown release type") endif() -else() - message(FATAL_ERROR "Unknown release type") -endif() -# Required packages + # Required packages + + add_library(gridpp ${SOURCES}) + target_link_libraries(gridpp "${Boost_LIBRARIES}") + target_link_libraries(gridpp "${ARMADILLO_LIBRARIES}") + target_include_directories(gridpp PUBLIC "${Boost_INCLUDE_DIR}") + target_include_directories(gridpp PUBLIC "${ARMADILLO_INCLUDE_DIRS}") +endif() include_directories(./include) file(GLOB SOURCES "src/api/*.cpp") -add_library(gridpp ${SOURCES}) -target_link_libraries(gridpp "${Boost_LIBRARIES}") -target_link_libraries(gridpp "${ARMADILLO_LIBRARIES}") -target_include_directories(gridpp PUBLIC "${Boost_INCLUDE_DIR}") -target_include_directories(gridpp PUBLIC "${ARMADILLO_INCLUDE_DIRS}") # Documentation option(BUILD_DOC "Build documentation" ON) diff --git a/include/gridpp.h b/include/gridpp.h index b082bece..14256d03 100644 --- a/include/gridpp.h +++ b/include/gridpp.h @@ -13,7 +13,7 @@ #endif #include -#define GRIDPP_VERSION "0.7.0.dev2" +#define GRIDPP_VERSION "0.7.0.dev4" #define __version__ GRIDPP_VERSION namespace gridpp { diff --git a/swig/CMakeLists.txt b/swig/CMakeLists.txt index 3de23b5f..b4358a96 100644 --- a/swig/CMakeLists.txt +++ b/swig/CMakeLists.txt @@ -4,11 +4,14 @@ include(${SWIG_USE_FILE}) # Add subdirectories for each language if desired option(BUILD_PYTHON "Build Python SWIG module" ON) -if(BUILD_PYTHON) - add_subdirectory(python) +if(BUILD_PACKAGE) add_subdirectory(python-packaging) -endif() -option(BUILD_R "Build R SWIG module" ON) -if(BUILD_R) - add_subdirectory(R) +else() + if(BUILD_PYTHON) + add_subdirectory(python) + endif() + option(BUILD_R "Build R SWIG module" ON) + if(BUILD_R) + add_subdirectory(R) + endif() endif() diff --git a/swig/python-packaging/CMakeLists.txt b/swig/python-packaging/CMakeLists.txt index f46bf1f8..b69455d0 100644 --- a/swig/python-packaging/CMakeLists.txt +++ b/swig/python-packaging/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories(${PYTHON_INCLUDE_PATH}) # Files to install with Python file(GLOB CPP_INCLUDE_FILES ${CMAKE_SOURCE_DIR}/include/*.h) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/MANIFEST.in DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/pyproject.toml DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) # Configure setup.py and copy to output directory set(SETUP_PY_IN ${CMAKE_CURRENT_SOURCE_DIR}/setup.in.py) @@ -22,8 +23,9 @@ add_custom_target(package-python COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/README.md ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E copy ${SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/src/api COMMAND ${CMAKE_COMMAND} -E copy ${CPP_INCLUDE_FILES} ${CMAKE_CURRENT_BINARY_DIR}/include - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/include/dependencies ${CMAKE_CURRENT_BINARY_DIR}/include + # COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/include/dependencies ${CMAKE_CURRENT_BINARY_DIR}/include COMMAND ${SWIG_EXECUTABLE} -python -outdir ${CMAKE_CURRENT_BINARY_DIR} -c++ -I./include -o ${CMAKE_CURRENT_BINARY_DIR}/gridppPYTHON_wrap.cxx ${SWIG_INTERFACE} - COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY_OUT} sdist --dist-dir ${CMAKE_BINARY_DIR} + # COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY_OUT} sdist --dist-dir ${CMAKE_BINARY_DIR} + COMMAND python ${SETUP_PY_OUT} sdist --dist-dir ${CMAKE_BINARY_DIR} ) # add_dependencies(package-python _gridpp2) diff --git a/swig/python-packaging/pyproject.toml b/swig/python-packaging/pyproject.toml new file mode 100644 index 00000000..b6e13f03 --- /dev/null +++ b/swig/python-packaging/pyproject.toml @@ -0,0 +1,10 @@ +[build-system] +requires = [ + "setuptools>=42", + "wheel", + "Cython", + "numpy==1.12.1; python_version<'3.5'", + "oldest-supported-numpy; python_version>='3.5'", +] + +build-backend = "setuptools.build_meta" diff --git a/swig/python-packaging/setup.in.py b/swig/python-packaging/setup.in.py index 26d55382..4ad98460 100644 --- a/swig/python-packaging/setup.in.py +++ b/swig/python-packaging/setup.in.py @@ -7,7 +7,8 @@ from setuptools import setup, Extension import glob import itertools -import numpy +import numpy as np +import sys __version__ = '${PROJECT_VERSION}' @@ -29,14 +30,18 @@ def run(self): # self.do_egg_install() orig.install.run(self) +args = [] +if sys.platform != "darwin": + args = "-fopenmp -fopenmp".split() +# NOTE: We need c++11 because manylinux2014 has gcc 4.8, which preceedes c++14 module = Extension('_gridpp', sources=glob.glob('src/api/*.cpp') + glob.glob('src/api/*.c') + ['gridppPYTHON_wrap.cxx'], libraries=["armadillo"], - extra_compile_args="${CMAKE_CXX_FLAGS_RELEASE} ${OpenMP_CXX_FLAGS} -std=c++${CMAKE_CXX_STANDARD}".split(), - extra_link_args="${CMAKE_CXX_FLAGS_RELEASE} ${OpenMP_CXX_FLAGS} -std=c++${CMAKE_CXX_STANDARD}".split(), - library_dirs=["/usr/lib64"], - include_dirs=['./include', numpy.get_include()] + extra_compile_args="-O3 -fPIC -std=c++11".split() + args, + extra_link_args="-O3 -fPIC -std=c++11".split() + args, + library_dirs=["/usr/lib64", "/usr/local/lib", "/usr/local/opt/armadillo/lib"], + include_dirs=['./include', np.get_include(), '/usr/local/opt/armadillo/include', "/usr/include", "/usr/local/include"] ) setup ( @@ -66,7 +71,7 @@ def run(self): # 3 - Alpha # 4 - Beta # 5 - Production/Stable - 'Development Status :: 4 - Beta', + 'Development Status :: 5 - Production/Stable', # Indicate who your project is intended for 'Intended Audience :: Science/Research', @@ -83,6 +88,9 @@ def run(self): 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', ], # What does your project relate to? diff --git a/swig/python-packaging/setup.sh b/swig/python-packaging/setup.sh new file mode 100644 index 00000000..2eb0c61b --- /dev/null +++ b/swig/python-packaging/setup.sh @@ -0,0 +1,4 @@ +mkdir build +cd build +cmake .. -DBUILD_PACKAGE=ON +VERBOSE=1 make package-python diff --git a/tests/check_installation.py b/tests/check_installation.py new file mode 100644 index 00000000..02c01891 --- /dev/null +++ b/tests/check_installation.py @@ -0,0 +1,6 @@ +import gridpp +import numpy as np + +gridpp.neighbourhood(np.zeros([10, 10]), 3, gridpp.Mean) + +print("Check complete")