Skip to content

ENH: Add windows support #184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 45 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
8e99db3
Bump iqtree2 from `1320c4c` to `39cbee5`
dependabot[bot] Mar 19, 2025
6911d6a
DEV: ignore dll files
rmcar17 Mar 19, 2025
52dab31
DEV: update libiqtree function signatures and add custom type convert…
rmcar17 Mar 19, 2025
971bb3e
DEV: ensure DLLs are included in build on windows
rmcar17 Mar 19, 2025
4af4b53
BUG: on windows, change out of tmp directory before cleaning up
rmcar17 Mar 19, 2025
48dcde4
TST: skip tests which throw error on IQ-TREE side on windows
rmcar17 Mar 19, 2025
b2273f6
ENH: include cstddef for other platforms
rmcar17 Mar 19, 2025
fbe6bba
MAINT: ignore attr-defined typing error for non-windows
rmcar17 Mar 19, 2025
e814a74
DEV: add windows build scripts
rmcar17 Mar 20, 2025
40196d3
DEV: build windows when building iqtree and cache correct files.
rmcar17 Mar 20, 2025
5e65f8a
DEV: test build process on windows
rmcar17 Mar 20, 2025
29f586f
DEV: install boost through action on windows, remove non-available ch…
rmcar17 Mar 20, 2025
6d7cf29
DEV: set boost env variables
rmcar17 Mar 20, 2025
7792886
DEV: debug boost env vars
rmcar17 Mar 20, 2025
14cef0a
DEV: removed path debugs, manually specify boost dirs
rmcar17 Mar 20, 2025
d570951
DEV: manually specify toolchain, downgrade llvm
rmcar17 Mar 20, 2025
fca8540
DEV: add lib.exe to path
rmcar17 Mar 20, 2025
688e589
DEV: debug msvc path
rmcar17 Mar 20, 2025
d1e4d61
DEV: try running wswhere through cmd
rmcar17 Mar 20, 2025
a189060
DEV: try configuring MSVC
rmcar17 Mar 20, 2025
26acfa1
DEV: use cmd to setup VS env
rmcar17 Mar 20, 2025
b6d38b5
DEV: use action to setup msvc
rmcar17 Mar 20, 2025
d52c8b4
DEV: continue build process with found lib
rmcar17 Mar 20, 2025
25611ac
DEV: only brew install on mac
rmcar17 Mar 20, 2025
ecb84ea
DEV: use different caches on unix/windows
rmcar17 Mar 20, 2025
fa7083d
DEV: Install llvm when testing windows ci, make build_iqtree compatib…
rmcar17 Mar 20, 2025
289e9df
DEV: re-enable full CI matrix
rmcar17 Mar 20, 2025
002f74e
DEV: use runner.os for choosing before_all script
rmcar17 Mar 20, 2025
fec36ab
DEV: standardise cache names
rmcar17 Mar 20, 2025
2d0f3b2
DEV: use correct input for cache key
rmcar17 Mar 20, 2025
631298f
DEV: add windows to cibuildwheel
rmcar17 Mar 20, 2025
19b0648
DEV: run before_all_windows script with bash
rmcar17 Mar 20, 2025
2c221e4
DEV: debug BOOST env vars
rmcar17 Mar 20, 2025
0914a96
DEV: attempt hardcoding boost paths
rmcar17 Mar 20, 2025
060b659
DEV: fix BOOST lib path
rmcar17 Mar 20, 2025
d9673de
DEV: remove hardcoding of BOOST paths
rmcar17 Mar 20, 2025
a4d9bd1
DEV: hardcode paths again
rmcar17 Mar 20, 2025
a8e8476
DEV: normalise slashes in before_all_windows
rmcar17 Mar 20, 2025
9f9669c
MAINT: remove extra space
rmcar17 Mar 20, 2025
c0d4be7
MAINT: update python version (#4)
rmcar17 Mar 20, 2025
84dad45
Merge branch 'main' into windows-support
rmcar17 Mar 20, 2025
505c1d9
DEV: update iqtree to error handling version
rmcar17 Mar 23, 2025
e4ad032
DEV: update return/arg types for calling IQ-TREE
rmcar17 Mar 23, 2025
bc80ae0
DEV: remove pytest skips on windows
rmcar17 Mar 23, 2025
466e979
DEV: rebase windows-support on main (#5)
rmcar17 May 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 56 additions & 7 deletions .github/actions/build-iqtree/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,68 @@ runs:
IQ_TREE_2_SHA=$(git rev-parse HEAD)
echo "iqtree2-sha=${IQ_TREE_2_SHA}" >> "$GITHUB_OUTPUT"

- uses: actions/cache@v4
id: cache
- name: Cache IQ-TREE 2 (Windows)
if: runner.os == 'Windows'
uses: actions/cache@v4
id: cache-windows
with:
key: libiqtree-${{ inputs.os }}-${{ steps.iqtree2-sha.outputs.iqtree2-sha }}
path: |
src/piqtree/_libiqtree/iqtree2.lib
src/piqtree/_libiqtree/iqtree2.dll
lookup-only: true

- name: Cache IQ-TREE 2 (Linux/macOS)
if: runner.os != 'Windows'
uses: actions/cache@v4
id: cache-unix
with:
key: libiqtree-${{ inputs.os }}-${{ steps.iqtree2-sha.outputs.iqtree2-sha }}
path: src/piqtree/_libiqtree/libiqtree2.a
path: |
src/piqtree/_libiqtree/libiqtree2.a
lookup-only: true

- name: Combine Cache Hits
id: cache
shell: bash
run: |
if [[ "${{ steps.cache-windows.outputs.cache-hit }}" == 'true' || "${{ steps.cache-unix.outputs.cache-hit }}" == 'true' ]]; then
echo "cache-hit=true" >> "$GITHUB_OUTPUT"
else
echo "cache-hit=false" >> "$GITHUB_OUTPUT"
fi

- name: Install Boost
if: runner.os == 'Windows' && steps.cache.outputs.cache-hit != 'true'
uses: MarkusJx/[email protected]
id: install-boost
with:
boost_version: 1.84.0
platform_version: 2022
toolset: mingw

- name: Set Boost Environment Variables
if: runner.os == 'Windows' && steps.cache.outputs.cache-hit != 'true'
shell: bash
run: |
echo "Boost_INCLUDE_DIR=${{ steps.install-boost.outputs.BOOST_ROOT }}/include" >> "$GITHUB_ENV"
echo "Boost_LIBRARY_DIRS=${{ steps.install-boost.outputs.BOOST_ROOT }}/lib" >> "$GITHUB_ENV"

- name: Setup MSVC Developer Command Prompt
if: runner.os == 'Windows' && steps.cache.outputs.cache-hit != 'true'
uses: ilammy/msvc-dev-cmd@v1

- name: Build IQ-TREE
shell: bash
if: steps.cache.outputs.cache-hit != 'true'
run: |
if [[ "${{ inputs.os }}" == "ubuntu-latest" ]]; then
sudo ./build_tools/before_all_linux.sh
if [[ "${{ runner.os }}" == "Linux" ]]; then
sudo ./build_tools/before_all_linux.sh
elif [[ "${{ runner.os }}" == "macOS" ]]; then
./build_tools/before_all_mac.sh
elif [[ "${{ runner.os }}" == "Windows" ]]; then
./build_tools/before_all_windows.sh
else
./build_tools/before_all_mac.sh
fi
echo "Unrecognized OS: '${{ inputs.os }}'."
exit 1
fi
23 changes: 19 additions & 4 deletions .github/actions/setup-piqtree/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,24 @@ runs:
- uses: "actions/setup-python@v5"
with:
python-version: ${{ inputs.python-version }}

- uses: actions/cache/restore@v4

- name: Cache IQ-TREE 2 (Windows)
if: runner.os == 'Windows'
uses: actions/cache/restore@v4
id: cache-windows
with:
key: ${{ inputs.cache-key }}
path: src/piqtree/_libiqtree/libiqtree2.a
fail-on-cache-miss: true
path: |
src/piqtree/_libiqtree/iqtree2.lib
src/piqtree/_libiqtree/iqtree2.dll
fail-on-cache-miss: true

- name: Cache IQ-TREE 2 (Linux/macOS)
if: runner.os != 'Windows'
uses: actions/cache/restore@v4
id: cache-unix
with:
key: ${{ inputs.cache-key }}
path: |
src/piqtree/_libiqtree/libiqtree2.a
fail-on-cache-miss: true
26 changes: 23 additions & 3 deletions .github/workflows/build_wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
fail-fast: false
matrix:
include:
# manylinux (x86)
# manylinux x86_64
- os: ubuntu-latest
platform_id: manylinux_x86_64

Expand All @@ -22,6 +22,10 @@ jobs:
- os: macos-14
platform_id: macosx_arm64

# Windows x86_64
- os: windows-latest
platform_id: win_amd64

steps:
- uses: "actions/checkout@v4"
with:
Expand All @@ -35,21 +39,37 @@ jobs:
platforms: arm64

- name: Set macOS Deployment Target
if: ${{startsWith(matrix.os, 'macos')}}
if: runner.os == 'macOS'
run: |
if [[ "${{ matrix.os }}" == "macos-13" ]]; then
echo "MACOSX_DEPLOYMENT_TARGET=13.0" >> $GITHUB_ENV
elif [[ "${{ matrix.os }}" == "macos-14" ]]; then
echo "MACOSX_DEPLOYMENT_TARGET=14.0" >> $GITHUB_ENV
fi

- name: Install Boost
if: runner.os == 'Windows'
uses: MarkusJx/[email protected]
id: install-boost
with:
boost_version: 1.84.0
platform_version: 2022
toolset: mingw

- name: Setup MSVC Developer Command Prompt
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1

- name: Build wheels
uses: pypa/[email protected].1
uses: pypa/[email protected].3
env: # Can specify per os - e.g. CIBW_BEFORE_ALL_LINUX, CIBW_BEFORE_ALL_MACOS, CIBW_BEFORE_ALL_WINDOWS
CIBW_BEFORE_ALL_LINUX: ./build_tools/before_all_linux.sh
CIBW_BEFORE_ALL_MACOS: ./build_tools/before_all_mac.sh
CIBW_BEFORE_ALL_WINDOWS: bash ./build_tools/before_all_windows.sh
CIBW_ENVIRONMENT_WINDOWS: Boost_INCLUDE_DIR='${{ steps.install-boost.outputs.BOOST_ROOT }}/include' Boost_LIBRARY_DIRS='${{ steps.install-boost.outputs.BOOST_ROOT }}/lib'
CIBW_ARCHS_LINUX: ${{endsWith(matrix.platform_id, '_x86_64') && 'x86_64' || 'aarch64'}}
CIBW_ARCHS_MACOS: ${{endsWith(matrix.platform_id, 'universal2') && 'universal2' || 'auto'}}
CIBW_ARCHS_WINDOWS: ${{endsWith(matrix.platform_id, '_amd64') && 'AMD64' || 'ARM64'}}
CIBW_BUILD: "*${{matrix.platform_id}}"
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: pytest {package}/tests
Expand Down
13 changes: 9 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-13, macos-14] # Intel linux, Intel Mac, ARM Mac
os: [ubuntu-latest, macos-13, macos-14, windows-latest] # Intel linux, Intel Mac, ARM Mac, Windows

steps:
- uses: "actions/checkout@v4"
Expand All @@ -35,7 +35,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-13, macos-14] # Intel linux, Intel Mac, ARM Mac
os: [ubuntu-latest, macos-13, macos-14, windows-latest] # Intel linux, Intel Mac, ARM Mac, Windows
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: "actions/checkout@v4"
Expand All @@ -48,10 +48,15 @@ jobs:
python-version: ${{ matrix.python-version }}
cache-key: libiqtree-${{ matrix.os }}-${{ needs.build-iqtree.outputs.iqtree2-sha }}

- name: Install llvm
if: matrix.os != 'ubuntu-latest'
- name: Install llvm (macOS)
if: runner.os == 'macOS'
run: |
brew install llvm

- name: Install llvm (Windows)
if: runner.os == 'Windows'
run: |
choco install -y llvm --version=14.0.6 --allow-downgrade

- name: Run Nox Testing
run: |
Expand Down
30 changes: 26 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
fail-fast: false
matrix:
include:
# manylinux (x86)
# manylinux x86_64
- os: ubuntu-latest
platform_id: manylinux_x86_64

Expand All @@ -22,6 +22,10 @@ jobs:
- os: macos-14
platform_id: macosx_arm64

# Windows x86_64
- os: windows-latest
platform_id: win_amd64

steps:
- uses: "actions/checkout@v4"
with:
Expand All @@ -35,23 +39,41 @@ jobs:
platforms: arm64

- name: Set macOS Deployment Target
if: ${{startsWith(matrix.os, 'macos')}}
if: runner.os == 'macOS'
run: |
if [[ "${{ matrix.os }}" == "macos-13" ]]; then
echo "MACOSX_DEPLOYMENT_TARGET=13.0" >> $GITHUB_ENV
elif [[ "${{ matrix.os }}" == "macos-14" ]]; then
echo "MACOSX_DEPLOYMENT_TARGET=14.0" >> $GITHUB_ENV
fi


- name: Install Boost
if: runner.os == 'Windows'
uses: MarkusJx/[email protected]
id: install-boost
with:
boost_version: 1.84.0
platform_version: 2022
toolset: mingw

- name: Setup MSVC Developer Command Prompt
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1

- name: Build wheels
uses: pypa/[email protected].1
uses: pypa/[email protected].3
env: # Can specify per os - e.g. CIBW_BEFORE_ALL_LINUX, CIBW_BEFORE_ALL_MACOS, CIBW_BEFORE_ALL_WINDOWS
CIBW_BEFORE_ALL_LINUX: ./build_tools/before_all_linux.sh
CIBW_BEFORE_ALL_MACOS: ./build_tools/before_all_mac.sh
CIBW_BEFORE_ALL_WINDOWS: bash ./build_tools/before_all_windows.sh
CIBW_ENVIRONMENT_WINDOWS: Boost_INCLUDE_DIR='${{ steps.install-boost.outputs.BOOST_ROOT }}/include' Boost_LIBRARY_DIRS='${{ steps.install-boost.outputs.BOOST_ROOT }}/lib'
CIBW_ARCHS_LINUX: ${{endsWith(matrix.platform_id, '_x86_64') && 'x86_64' || 'aarch64'}}
CIBW_ARCHS_MACOS: ${{endsWith(matrix.platform_id, 'universal2') && 'universal2' || 'auto'}}
CIBW_ARCHS_WINDOWS: ${{endsWith(matrix.platform_id, '_amd64') && 'AMD64' || 'ARM64'}}
CIBW_BUILD: "*${{matrix.platform_id}}"
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: pytest {package}/tests
CIBW_TEST_SKIP: "*-macosx_universal2:x86_64" # skip x86 on m1 mac
CIBW_SKIP: pp* # Disable building PyPy wheels on all platforms

- name: Upload wheels
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

# piqtree specific ignores
src/piqtree/_libiqtree/**/*.a
src/piqtree/_libiqtree/**/*.dll
src/piqtree/_libiqtree/**/*.lib
src/*.dll

# docs
data
Expand Down
13 changes: 13 additions & 0 deletions build_tools/before_all_windows.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Install dependencies using choco

export Boost_INCLUDE_DIR=$(echo $Boost_INCLUDE_DIR | sed 's|\\|/|g')
export Boost_LIBRARY_DIRS=$(echo $Boost_LIBRARY_DIRS | sed 's|\\|/|g')

echo "Boost_INCLUDE_DIR: $Boost_INCLUDE_DIR"
echo "Boost_LIBRARY_DIRS: $Boost_LIBRARY_DIRS"

choco install -y llvm --version=14.0.6 --allow-downgrade
choco install -y eigen

# Build IQ-TREE
bash build_tools/build_iqtree.sh
30 changes: 28 additions & 2 deletions build_tools/build_iqtree.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,37 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
echo $CXXFLAGS
cmake -DBUILD_LIB=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ..
gmake -j
elif [[ "$OSTYPE" == "msys"* || "$OSTYPE" == "cygwin"* ]]; then
echo "Building for Windows."

if [[ -n "$BOOST_ROOT" ]]; then
export Boost_INCLUDE_DIR="${BOOST_ROOT}"
export Boost_LIBRARY_DIRS="${BOOST_ROOT}"
fi

cmake -G "MinGW Makefiles" \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_FLAGS=--target=x86_64-pc-windows-gnu \
-DCMAKE_CXX_FLAGS=--target=x86_64-pc-windows-gnu \
-DCMAKE_MAKE_PROGRAM=make \
-DBoost_INCLUDE_DIR=$Boost_INCLUDE_DIR \
-DBoost_LIBRARY_DIRS=$Boost_LIBRARY_DIRS \
-DIQTREE_FLAGS="cpp14" \
-DBUILD_LIB=ON \
..
make -j
else
echo "Building for linux."
cmake -DBUILD_LIB=ON ..
cmake -DBUILD_LIB=ON -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ..
make -j
fi

cd ../..
mv iqtree2/build/libiqtree2.a src/piqtree/_libiqtree/

if [[ "$OSTYPE" == "darwin"* || "$OSTYPE" == "linux"* ]]; then
mv iqtree2/build/libiqtree2.a src/piqtree/_libiqtree/
elif [[ "$OSTYPE" == "msys"* || "$OSTYPE" == "cygwin"* ]]; then
mv iqtree2/build/iqtree2.lib src/piqtree/_libiqtree/
mv iqtree2/build/iqtree2.dll src/piqtree/_libiqtree/
fi
20 changes: 20 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@

<a id='changelog-0.5.0'></a>
# Changes in release "0.5.0"

## Contributors

- @GavinHuttley added `nj_tree` as a hook for `cogent3.Alignment.quick_tree`.
- @YapengLang handled negative branch lengths from the rapidNJ tree.
- @rmcar17, @thomaskf general maintanence on the piqtree/IQ-TREE sides including work on windows behind the scenes.

## ENH

- Add support for Python 3.13, remove support for 3.10
- IQ-TREE's rapidNJ implementation can be used as a hook for `quick_tree` on `cogent3` alignment objects. Try `Alignment.quick_tree(use_hook="piqtree")`.
- `nj_tree` now by default does not allow negative branch lengths. Set `allow_negative=True` if this behaviour is desired.
- Allow `str` to be used for `model` in `build_tree` and `fit_tree`. The value is automatically coerced into the `Model` class.

## API

- Simplify API for `piqtree_phylo` and `piqtree_fit` apps. Both now take a single parameter for the model, matching the parameter for `model` in `build_tree` and `fit_tree`.

<a id='changelog-0.4.0'></a>
# Changes in release "0.4.0"

Expand Down
2 changes: 1 addition & 1 deletion docs/developers/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The documentation is fetched by readthedocs from the "Build Docs" GitHub Action.

- The `piqtree` version has been correctly bumped.
- The testing, linting and type checking all pass on all supported platforms.
- The code has been throuroughly tested (check what's been missed in the coverage report).
- The code has been thoroughly tested (check what's been missed in the coverage report).
- The documentation builds and appears correct.
- The documentation has been updated on readthedocs (this must be triggered from readthedocs).
- The "Release" GitHub Action has correctly uploaded to Test PyPI.
Expand Down
2 changes: 1 addition & 1 deletion iqtree2
Loading
Loading