Skip to content

Commit

Permalink
Merge pull request #86 from samrensenhouse/github_action_wheels
Browse files Browse the repository at this point in the history
GitHub action wheels
  • Loading branch information
samhatchett authored Mar 9, 2022
2 parents f492d41 + c42cffd commit c290f95
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 103 deletions.
119 changes: 98 additions & 21 deletions .github/workflows/build-wheels.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
name: Build Wheels
name: Build wheels

on: [push, pull_request]
on:
workflow_dispatch:

jobs:
build_toolkit_wheels:
name: Build MacOS python 3.8
runs-on: macos-10.15
defaults:
run:
working-directory: ./owa-epanet
build_wheels:
name: Build wheel for cp${{ matrix.python }}-${{ matrix.platform_id }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ windows-latest, ubuntu-latest, macos-latest ]
python: [ 36, 37, 38, 39, 310]
bitness: [ 32, 64 ]
include:
# Run 32 and 64 bit version in parallel for Linux and Windows
- os: windows-latest
bitness: 64
platform_id: win_amd64
- os: windows-latest
bitness: 32
platform_id: win32
- os: ubuntu-latest
bitness: 64
platform_id: manylinux_x86_64
- os: macos-latest
bitness: 64
platform_id: macosx_x86_64
exclude:
- os: macos-latest
bitness: 32
# This build was broken on OpenMP so is excluded for now
- os: ubuntu-latest
bitness: 32

steps:
- name: Checkout repo
Expand All @@ -18,24 +42,77 @@ jobs:

- name: Install Python
uses: actions/setup-python@v2

- uses: ilammy/msvc-dev-cmd@v1
if: startsWith(matrix.os, 'windows')

- name: Install cibuildwheel
run: python -m pip install cibuildwheel==2.3.1

- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse owa-epanet
env:
CIBW_BUILD: cp${{ matrix.python }}-${{ matrix.platform_id }}
CIBW_BEFORE_ALL_LINUX: git submodule update --init && yum install swig -y
CIBW_BEFORE_ALL_WINDOWS: git submodule update && choco install swig
CIBW_BEFORE_ALL_MACOS: git submodule update && brew install swig ninja libomp
CIBW_BEFORE_BUILD: pip install scikit-build==0.11.1 cmake==3.18.4
CIBW_BUILD_VERBOSITY: 1
CIBW_TEST_COMMAND: pytest {package}
CIBW_BEFORE_TEST: pip install scikit-build==0.11.1 cmake==3.18.4
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_SKIP: "*-win32 *-manylinux_i686"

- name: Store artifacts
uses: actions/upload-artifact@v2
with:
python-version: 3.8
path: ./wheelhouse/*.whl


build_sdist:
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true

- name: Install required system packages
run: brew install swig
- name: Fix submodules
run: |
cd owa-epanet
git submodule update
- uses: actions/setup-python@v2
name: Install Python
with:
python-version: '3.8'

- name: Build wheel
- name: Install dependencies
run: |
pip install scikit-build
python setup.py bdist_wheel
sudo apt update
sudo apt install swig -y
pip install scikit-build==0.11.1 cmake==3.18.4
- name: Test wheel
- name: Build sdist
run: |
pip install pytest
pip install --no-index --find-links=./dist owa-epanet
pytest
cd owa-epanet
python setup.py sdist
- name: Upload artifacts
uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v2
with:
path: owa-epanet/dist/*.tar.gz

upload_pypi:
needs: [ build_wheels, build_sdist ]
runs-on: ubuntu-latest

steps:
- uses: actions/download-artifact@v2
with:
name: artifact
path: dist

- uses: pypa/[email protected]
with:
path: owa-epanet/dist/*.whl
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
158 changes: 81 additions & 77 deletions owa-epanet/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,100 +1,104 @@
cmake_minimum_required(VERSION 3.8)

project(OWA-EPANET)
project(owa-epanet)
set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})

if(SKBUILD)
message(STATUS "The project is built using scikit-build")
endif()

find_package(PythonLibs 3 REQUIRED)
find_package(PythonInterp ${PYTHONLIBS_VERSION_STRING} REQUIRED)
# If find_package() has difficulty finding the appropriate python
# directories and libraries (especially in Windows with multiple
# versions of python) set them manually as in the next three lines
# below (and comment out the above two find_package() lines):
# set(PYTHON_EXECUTABLE "c:/python/python38/python.exe")
# set(PYTHON_INCLUDE_PATH "c:/python/python38/include")
# set(PYTHON_LIBRARIES "c:/python/python38/libs/python38.lib")
# Setup python
if(NOT MSVC)
find_package (Python3 ${PYTHON_VERSION_STRING} COMPONENTS Interpreter Development.Module EXACT REQUIRED)
else()
find_package (Python3 ${PYTHON_VERSION_STRING} COMPONENTS Interpreter Development EXACT REQUIRED)
endif()

# Setup swig
find_package(SWIG REQUIRED)
cmake_policy(SET CMP0078 NEW)
cmake_policy(SET CMP0086 NEW)
include(${SWIG_USE_FILE})
set(CMAKE_SWIG_FLAGS -py3)

message("PYTHONLIBS_VERSION_STRING: ${PYTHONLIBS_VERSION_STRING}")
message("CMAKE_SWIG_FLAGS: ${CMAKE_SWIG_FLAGS}")

INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
INCLUDE_DIRECTORIES(EPANET/include)
INCLUDE_DIRECTORIES(EPANET/src/outfile/include)

SET(CMAKE_SWIG_FLAGS "")

SET_SOURCE_FILES_PROPERTIES(toolkit.i PROPERTIES CPLUSPLUS ON)
SET_SOURCE_FILES_PROPERTIES(toolkit.i PROPERTIES SWIG_FLAGS "-includeall")


# build the EPANET library
# Build the EPANET library
ADD_SUBDIRECTORY(EPANET)

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

SWIG_ADD_LIBRARY( toolkit LANGUAGE python SOURCES wrapper/toolkit.i )
set_property(SOURCE toolkit.i PROPERTY USE_LIBRARY_INCLUDE_DIRECTORIES TRUE)
set_property(TARGET epanet2 PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE)
SWIG_LINK_LIBRARIES(toolkit epanet2)
# Set up rpath on MacOS and Linux
if(APPLE)
set(PACKAGE_RPATH "@loader_path")
else()
set(PACKAGE_RPATH "$ORIGIN")
endif()

SWIG_LINK_LIBRARIES(toolkit ${PYTHON_LIBRARIES})
set_property(TARGET _toolkit PROPERTY INSTALL_RPATH "$ORIGIN")

#SWIG_ADD_LIBRARY( output LANGUAGE python SOURCES wrapper/output.i )
#SET_PROPERTY( SOURCE output.i PROPERTY USE_LIBRARY_INCLUDE_DIRECTORIES TRUE )
#SET_PROPERTY( TARGET epanet-output PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE )
#SWIG_LINK_LIBRARIES( output epanet-output)
#SWIG_LINK_LIBRARIES( output ${PYTHON_LIBRARIES} )
#SET_PROPERTY( TARGET _output PROPERTY INSTALL_RPATH "$ORIGIN" )
# Include files for swig
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
INCLUDE_DIRECTORIES(EPANET/include)
INCLUDE_DIRECTORIES(EPANET/src/outfile/include)

IF (APPLE)
set_target_properties(_toolkit PROPERTIES INSTALL_RPATH "@loader_path")
ENDIF (APPLE)

install(TARGETS _toolkit LIBRARY DESTINATION packages/epanet)
# Allow target_include_directories to be used later
set_property(SOURCE wrapper/toolkit.i
PROPERTY
USE_TARGET_INCLUDE_DIRECTORIES TRUE
)
set_property(TARGET epanet2
PROPERTY
USE_TARGET_INCLUDE_DIRECTORIES TRUE
)

# Create cmake target
swig_add_library(toolkit
TYPE
MODULE
LANGUAGE
python
SOURCES
wrapper/toolkit.i
)

target_include_directories(toolkit
PUBLIC
${Python3_INCLUDE_DIRS}
)

target_link_options(toolkit
PUBLIC
$<$<BOOL:${APPLE}>:-undefined dynamic_lookup>
)



swig_link_libraries(toolkit
PUBLIC
$<$<BOOL:$<C_COMPILER_ID:MSVC>>:Python3::Module>
epanet2
)

set_target_properties(toolkit
PROPERTIES
SWIG_COMPILE_DEFINITIONS EXPORT_OUT_API
MACOSX_RPATH TRUE
SKIP_BUILD_RPATH FALSE
BUILD_WITH_INSTALL_RPATH FALSE
INSTALL_RPATH "${PACKAGE_RPATH}"
INSTALL_RPATH_USE_LINK_PATH TRUE
)

install(TARGETS toolkit LIBRARY DESTINATION packages/epanet)

add_custom_command(
TARGET _toolkit POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/toolkit.py
${CMAKE_CURRENT_BINARY_DIR}/../../../packages/epanet/toolkit.py)

IF(WIN32)
add_custom_command(
TARGET _toolkit POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/lib/_toolkit.pyd
${CMAKE_CURRENT_BINARY_DIR}/../../../packages/epanet/_toolkit.pyd)
add_custom_command(
TARGET _toolkit POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/bin/epanet2.dll
${CMAKE_CURRENT_BINARY_DIR}/../../../packages/epanet/epanet2.dll)
ELSE(True)
add_custom_command(
TARGET _toolkit POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/lib/libepanet2.*
${CMAKE_CURRENT_BINARY_DIR}/../../../packages/epanet/)
ENDIF(WIN32)



#add_custom_command(
# TARGET _toolkit POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E copy
# ${CMAKE_CURRENT_BINARY_DIR}/output.py
# ${CMAKE_CURRENT_BINARY_DIR}/../../../packages/epanet/output.py)

#add_custom_command(
# TARGET _toolkit POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E copy
# ${CMAKE_CURRENT_BINARY_DIR}/lib/libepanet-output.*
# ${CMAKE_CURRENT_BINARY_DIR}/../../../packages/epanet/)
TARGET toolkit
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${CMAKE_CURRENT_BINARY_DIR}/toolkit.py"
$<$<BOOL:${WIN32}>:${CMAKE_CURRENT_BINARY_DIR}/_toolkit.pyd>
$<$<BOOL:${WIN32}>:${CMAKE_CURRENT_BINARY_DIR}/bin/epanet2.dll>
$<$<NOT:$<BOOL:${WIN32}>>:${CMAKE_CURRENT_BINARY_DIR}/lib/libepanet2.*>
${CMAKE_SOURCE_DIR}/packages/epanet
)

18 changes: 13 additions & 5 deletions owa-epanet/test/test_owa_epanet.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@


def clean_dir():
def safe_delete(filename):
try:
os.remove(filename)
except PermissionError:
pass
if os.path.exists('report.rpt'):
os.remove('report.rpt')
safe_delete('report.rpt')
if os.path.exists('output.out'):
os.remove('output.out')
safe_delete('output.out')
if os.path.exists('saved_inp_file.inp'):
os.remove('saved_inp_file.inp')
safe_delete('saved_inp_file.inp')


def test_create_project():
Expand Down Expand Up @@ -236,8 +241,9 @@ def test_water_age_sim():
en.closeQ(ph=epanet_proj)
en.closeH(ph=epanet_proj)
en.close(ph=epanet_proj)
assert age_list[26] == [1.0, 2.2141675704376946, 12.939125434025273, 24.44152992466322, 13.174235412569542,
24.441519659540887, 15.679376648181817, 21.97064181429266, 19.048343501261524, 1.0]
assert age_list[26] == pytest.approx(
[1.0, 2.2141675704376946, 12.939125434025273, 24.44152992466322, 13.174235412569542,
24.441519659540887, 15.679376648181817, 21.97064181429266, 19.048343501261524, 1.0])
clean_dir()


Expand Down Expand Up @@ -324,6 +330,7 @@ def test_setnodevalue():
assert tank_level_list ==[121.0]
clean_dir()


def test_setcurve():
def make_array(values):
dbl_arr = en.doubleArray(len(values))
Expand All @@ -341,6 +348,7 @@ def make_array(values):
count = en.getcurvelen(ph=epanet_proj, index=curve_index)
assert count == 5


def test_coords():
epanet_proj = en.createproject()
en.open(ph=epanet_proj, inpFile=example_1_path, rptFile='report.rpt', outFile='output.out')
Expand Down

0 comments on commit c290f95

Please sign in to comment.