diff --git a/.github/tools/cibw_repair_wheel_command_windows.sh b/.github/tools/cibw_repair_wheel_command_windows.sh new file mode 100644 index 0000000..22e7352 --- /dev/null +++ b/.github/tools/cibw_repair_wheel_command_windows.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -e +set -x + +WHEEL=$1 +DEST_DIR=$2 + +python -m pip install delvewheel +python -m delvewheel show "$WHEEL" && python -m delvewheel repair -w "$DEST_DIR" "$WHEEL" --no-mangle-all diff --git a/.github/workflows/CI_pyFrame3DD.yml b/.github/workflows/CI_pyFrame3DD.yml index 9978d6f..fde0f2b 100644 --- a/.github/workflows/CI_pyFrame3DD.yml +++ b/.github/workflows/CI_pyFrame3DD.yml @@ -16,42 +16,51 @@ jobs: fail-fast: false #true matrix: os: ["ubuntu-latest", "macOS-latest", "windows-latest"] - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - name: Setup C/C++ Compiler + if: false == contains( matrix.os, 'windows') id: install_cc - uses: rlalik/setup-cpp-compiler@v1.2 + uses: rlalik/setup-cpp-compiler@master + with: + compiler: clang + + - name: Install mingw-w64 on Windows + if: contains( matrix.os, 'windows') + uses: msys2/setup-msys2@v2 with: - compiler: gcc #clang + path-type: inherit + install: | + mingw-w64-x86_64-gcc - name: checkout repository uses: actions/checkout@v4 + - name: Set compilers + if: false == contains( matrix.os, 'windows') + run: | + echo "CC=${{ steps.install_cc.outputs.cc }}" >> $GITHUB_ENV + echo "CXX=${{ steps.install_cc.outputs.cxx }}" >> $GITHUB_ENV + - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 id: cp with: python-version: ${{ matrix.python-version }} update-environment: true - + - name: Editable Pip Install pyFrame3DD - env: - CC: '${{ steps.install_cc.outputs.cc }}' - CXX: '${{ steps.install_cc.outputs.cxx }}' run: | '${{ steps.cp.outputs.python-path }}' -m pip install --upgrade pip '${{ steps.cp.outputs.python-path }}' -m pip install meson-python meson numpy ninja wheel '${{ steps.cp.outputs.python-path }}' -m pip install --no-build-isolation -e .[test] - + - name: Editable Test run run: | '${{ steps.cp.outputs.python-path }}' -m pytest test - name: Pip Install pyFrame3DD - env: - CC: '${{ steps.install_cc.outputs.cc }}' - CXX: '${{ steps.install_cc.outputs.cxx }}' run: | '${{ steps.cp.outputs.python-path }}' -m pip uninstall pyframe3dd '${{ steps.cp.outputs.python-path }}' -m pip install -v .[test] @@ -78,7 +87,7 @@ jobs: fail-fast: false #true matrix: os: ["ubuntu-latest", "macOS-latest", "windows-latest"] - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - name: checkout repository diff --git a/.github/workflows/Publish_pyFrame3DD.yml b/.github/workflows/Publish_pyFrame3DD.yml index 7077f47..3686399 100644 --- a/.github/workflows/Publish_pyFrame3DD.yml +++ b/.github/workflows/Publish_pyFrame3DD.yml @@ -1,37 +1,49 @@ name: Build and upload to PyPI +# https://github.com/pypa/cibuildwheel/blob/main/examples/github-deploy.yml +# Best comparable example: https://github.com/pdfo/pdfo -# Build on every branch push, tag push, and pull request change: -#on: [push, pull_request] -# Alternatively, to publish when a (published) GitHub Release is created, use the following: -on: - release: - types: - - published +# Build on every pull request (no need for every push) and release change: +on: [pull_request, release] jobs: build_wheels: name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu-latest, windows-latest, macos-13, macos-14] steps: - - name: Setup C/C++ Compiler + - name: Install compiler + if: false == contains( matrix.os, 'windows') id: install_cc - uses: rlalik/setup-cpp-compiler@v1.2 + uses: rlalik/setup-cpp-compiler@master with: - compiler: gcc #clang + compiler: clang + + - name: Install mingw-w64 on Windows + if: contains( matrix.os, 'windows') + uses: msys2/setup-msys2@v2 + with: + path-type: inherit + install: | + mingw-w64-x86_64-gcc - name: Checkout uses: actions/checkout@v4 - - name: Build wheels + - name: Build wheels mac and linux + if: false == contains( matrix.os, 'windows') + uses: pypa/cibuildwheel@v2.17.0 env: - CC: '${{ steps.install_cc.outputs.cc }}' - CXX: '${{ steps.install_cc.outputs.cxx }}' - uses: pypa/cibuildwheel@v2.16.2 + CC: ${{ steps.install_cc.outputs.cc }} + CXX: ${{ steps.install_cc.outputs.cxx }} + - name: Build wheels windows + if: contains( matrix.os, 'windows') + uses: pypa/cibuildwheel@v2.17.0 + - uses: actions/upload-artifact@v4 with: name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} @@ -41,7 +53,7 @@ jobs: name: Build source distribution runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build sdist run: pipx run build --sdist diff --git a/pyframe3dd/meson.build b/pyframe3dd/meson.build index bcb71be..a803e07 100644 --- a/pyframe3dd/meson.build +++ b/pyframe3dd/meson.build @@ -8,28 +8,33 @@ py3.install_sources( subdir: 'pyframe3dd', ) -sources = ['src/py_main.c', - 'src/py_structs.h', - 'src/py_io.c', - 'src/py_io.h', - 'src/py_frame3dd.c', - 'src/py_frame3dd.h', - 'src/py_eig.c', - 'src/py_eig.h', - 'src/py_HPGmatrix.c', - 'src/py_HPGmatrix.h', - 'src/coordtrans.c', - 'src/coordtrans.h', - 'src/HPGutil.c', - 'src/HPGutil.h', - 'src/NRutil.c', - 'src/NRutil.h'] +sources = [ + 'src/HPGutil.h', + 'src/HPGutil.c', + 'src/coordtrans.h', + 'src/coordtrans.c', + 'src/NRutil.h', + 'src/NRutil.c', + 'src/py_io.h', + 'src/py_io.c', + 'src/py_eig.h', + 'src/py_eig.c', + 'src/py_structs.h', + 'src/py_HPGmatrix.h', + 'src/py_HPGmatrix.c', + 'src/py_frame3dd.h', + 'src/py_frame3dd.c', + 'src/py_main.c', +] # We need to build a shared library NOT A PYTHON EXTENSION # The ctypes wrapper handles the extension part. # If the interface was done purely in C, then need the python extension. -temp = shared_library('_pyframe3dd', sources, - name_prefix: '', - include_directories: 'src', - install_dir: py3.get_install_dir() / 'pyframe3dd', - install : true) +temp = shared_library( + '_pyframe3dd', + sources, + name_prefix: '', + include_directories: ['src','src/microstran'], + install_dir: py3.get_install_dir() / 'pyframe3dd', + install : true, +) diff --git a/pyframe3dd/src/Makefile b/pyframe3dd/src/Makefile index 3592ebd..6d05902 100644 --- a/pyframe3dd/src/Makefile +++ b/pyframe3dd/src/Makefile @@ -1,5 +1,5 @@ CC ?= clang #gcc -CFLAGS = -c -g -O2 -fPIC +CFLAGS = -c -g -O2 -fPIC -Wall OBS = coordtrans.o HPGutil.o NRutil.o PYOBS = py_main.o py_io.o py_frame3dd.o py_eig.o py_HPGmatrix.o diff --git a/pyproject.toml b/pyproject.toml index a3abfc2..4163425 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "mesonpy" [project] name = "WISDEM-pyFrame3DD" -version = "1.1.0" +version = "1.1.1" description = "Python bindings to Frame3DD, a code for static and dynamic structural analysis of 2D and 3D frames and trusses, with permission from Prof Henri Gavin" readme = "README.md" requires-python = ">=3.9" @@ -116,5 +116,15 @@ atomic = true #src_paths=isort,test [tool.cibuildwheel] -skip = ["cp36-*", "cp37-*", "cp38-*", "*-win32"] -build-frontend = "build" +skip = ["pp*", "cp36-*", "cp37-*", "cp38-*", "*-win32", "*-win_arm64"] #, "*-musllinux*"] +build-frontend = { name = "build", args = ["-w","-n","-x"] } +before-build = "pip install numpy ninja meson meson-python" +build-verbosity = "3" + +# https://github.com/pdfo/pdfo +[[tool.cibuildwheel.overrides]] +select = "*-win_amd64" +environment = { PKG_CONFIG_PATH="c:/opt/64/lib/pkgconfig" } + +[tool.cibuildwheel.windows] +repair-wheel-command = "bash .github/tools/cibw_repair_wheel_command_windows.sh {wheel} {dest_dir}" diff --git a/test/test_beam_theory.py b/test/test_beam_theory.py index bd3a085..762b827 100644 --- a/test/test_beam_theory.py +++ b/test/test_beam_theory.py @@ -107,13 +107,5 @@ def testFixedFree_FreeFree(self): self.assertAlmostEqual(freq[5], anal[2], -2) - - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(FrameTestEXA)) - return suite - if __name__ == '__main__': - unittest.TextTestRunner().run(suite()) + unittest.main() diff --git a/test/test_breakdown.py b/test/test_breakdown.py index a5dfa81..710ec55 100644 --- a/test/test_breakdown.py +++ b/test/test_breakdown.py @@ -213,19 +213,10 @@ def testModal(self): npt.assert_almost_equal(rxns_mass.Mxx, rxns_force.Mxx) npt.assert_almost_equal(rxns_mass.Myy, rxns_force.Myy) npt.assert_almost_equal(rxns_mass.Mzz, rxns_force.Mzz) - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestBreakdown)) - return suite -if __name__ == "__main__": - result = unittest.TextTestRunner().run(suite()) - if result.wasSuccessful(): - exit(0) - else: - exit(1) +if __name__ == "__main__": + unittest.main() diff --git a/test/test_frame.py b/test/test_frame.py index 83e6bf4..f3d71c8 100644 --- a/test/test_frame.py +++ b/test/test_frame.py @@ -917,11 +917,18 @@ def test_addgrav_working(self): def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(FrameTestEXA)) - suite.addTest(unittest.makeSuite(FrameTestEXB)) - suite.addTest(unittest.makeSuite(GravityAdd)) - return suite - -if __name__ == '__main__': - unittest.TextTestRunner().run(suite()) + suite = [ + unittest.TestLoader().loadTestsFromTestCase(FrameTestEXA), + unittest.TestLoader().loadTestsFromTestCase(FrameTestEXB), + unittest.TestLoader().loadTestsFromTestCase(GravityAdd), + ] + return unittest.TestSuite(suite) + +if __name__ == "__main__": + result = unittest.TextTestRunner().run(suite()) + + if result.wasSuccessful(): + exit(0) + else: + exit(1) +