From d1620f82a603091819a116e16a87bf2007187eba Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Tue, 5 Nov 2024 22:28:28 +0100 Subject: [PATCH 01/13] Move project files to `src` folder --- {pyfamsa => src/pyfamsa}/__init__.py | 0 {pyfamsa => src/pyfamsa}/_famsa.pxd | 0 {pyfamsa => src/pyfamsa}/_famsa.pyi | 0 {pyfamsa => src/pyfamsa}/_famsa.pyx | 0 {pyfamsa => src/pyfamsa}/_version.py | 0 {pyfamsa => src/pyfamsa}/py.typed | 0 {pyfamsa => src/pyfamsa}/tests/__init__.py | 0 {pyfamsa => src/pyfamsa}/tests/__main__.py | 0 {pyfamsa => src/pyfamsa}/tests/data/__init__.py | 0 {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.faa | 0 {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.p1.afa | 0 {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.p2.afa | 0 {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.sl.afa | 0 {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.sl.nwk | 0 {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.upgma.afa | 0 {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.upgma.nwk | 0 {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.upgma.pp.afa | 0 {pyfamsa => src/pyfamsa}/tests/data/hemopexin.faa | 0 {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-nj.afa | 0 {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-nj.nwk | 0 {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-sl.afa | 0 {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-sl.nwk | 0 {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-slink.nwk | 0 {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-upgma.afa | 0 {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-upgma.nwk | 0 {pyfamsa => src/pyfamsa}/tests/fasta.py | 0 {pyfamsa => src/pyfamsa}/tests/requirements.txt | 0 {pyfamsa => src/pyfamsa}/tests/test_aligner.py | 0 {pyfamsa => src/pyfamsa}/tests/test_alignment.py | 0 {pyfamsa => src/pyfamsa}/tests/test_doctest.py | 0 {pyfamsa => src/pyfamsa}/tests/test_sequence.py | 0 31 files changed, 0 insertions(+), 0 deletions(-) rename {pyfamsa => src/pyfamsa}/__init__.py (100%) rename {pyfamsa => src/pyfamsa}/_famsa.pxd (100%) rename {pyfamsa => src/pyfamsa}/_famsa.pyi (100%) rename {pyfamsa => src/pyfamsa}/_famsa.pyx (100%) rename {pyfamsa => src/pyfamsa}/_version.py (100%) rename {pyfamsa => src/pyfamsa}/py.typed (100%) rename {pyfamsa => src/pyfamsa}/tests/__init__.py (100%) rename {pyfamsa => src/pyfamsa}/tests/__main__.py (100%) rename {pyfamsa => src/pyfamsa}/tests/data/__init__.py (100%) rename {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.faa (100%) rename {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.p1.afa (100%) rename {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.p2.afa (100%) rename {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.sl.afa (100%) rename {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.sl.nwk (100%) rename {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.upgma.afa (100%) rename {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.upgma.nwk (100%) rename {pyfamsa => src/pyfamsa}/tests/data/adeno_fiber.upgma.pp.afa (100%) rename {pyfamsa => src/pyfamsa}/tests/data/hemopexin.faa (100%) rename {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-nj.afa (100%) rename {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-nj.nwk (100%) rename {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-sl.afa (100%) rename {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-sl.nwk (100%) rename {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-slink.nwk (100%) rename {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-upgma.afa (100%) rename {pyfamsa => src/pyfamsa}/tests/data/hemopexin.medoid-upgma.nwk (100%) rename {pyfamsa => src/pyfamsa}/tests/fasta.py (100%) rename {pyfamsa => src/pyfamsa}/tests/requirements.txt (100%) rename {pyfamsa => src/pyfamsa}/tests/test_aligner.py (100%) rename {pyfamsa => src/pyfamsa}/tests/test_alignment.py (100%) rename {pyfamsa => src/pyfamsa}/tests/test_doctest.py (100%) rename {pyfamsa => src/pyfamsa}/tests/test_sequence.py (100%) diff --git a/pyfamsa/__init__.py b/src/pyfamsa/__init__.py similarity index 100% rename from pyfamsa/__init__.py rename to src/pyfamsa/__init__.py diff --git a/pyfamsa/_famsa.pxd b/src/pyfamsa/_famsa.pxd similarity index 100% rename from pyfamsa/_famsa.pxd rename to src/pyfamsa/_famsa.pxd diff --git a/pyfamsa/_famsa.pyi b/src/pyfamsa/_famsa.pyi similarity index 100% rename from pyfamsa/_famsa.pyi rename to src/pyfamsa/_famsa.pyi diff --git a/pyfamsa/_famsa.pyx b/src/pyfamsa/_famsa.pyx similarity index 100% rename from pyfamsa/_famsa.pyx rename to src/pyfamsa/_famsa.pyx diff --git a/pyfamsa/_version.py b/src/pyfamsa/_version.py similarity index 100% rename from pyfamsa/_version.py rename to src/pyfamsa/_version.py diff --git a/pyfamsa/py.typed b/src/pyfamsa/py.typed similarity index 100% rename from pyfamsa/py.typed rename to src/pyfamsa/py.typed diff --git a/pyfamsa/tests/__init__.py b/src/pyfamsa/tests/__init__.py similarity index 100% rename from pyfamsa/tests/__init__.py rename to src/pyfamsa/tests/__init__.py diff --git a/pyfamsa/tests/__main__.py b/src/pyfamsa/tests/__main__.py similarity index 100% rename from pyfamsa/tests/__main__.py rename to src/pyfamsa/tests/__main__.py diff --git a/pyfamsa/tests/data/__init__.py b/src/pyfamsa/tests/data/__init__.py similarity index 100% rename from pyfamsa/tests/data/__init__.py rename to src/pyfamsa/tests/data/__init__.py diff --git a/pyfamsa/tests/data/adeno_fiber.faa b/src/pyfamsa/tests/data/adeno_fiber.faa similarity index 100% rename from pyfamsa/tests/data/adeno_fiber.faa rename to src/pyfamsa/tests/data/adeno_fiber.faa diff --git a/pyfamsa/tests/data/adeno_fiber.p1.afa b/src/pyfamsa/tests/data/adeno_fiber.p1.afa similarity index 100% rename from pyfamsa/tests/data/adeno_fiber.p1.afa rename to src/pyfamsa/tests/data/adeno_fiber.p1.afa diff --git a/pyfamsa/tests/data/adeno_fiber.p2.afa b/src/pyfamsa/tests/data/adeno_fiber.p2.afa similarity index 100% rename from pyfamsa/tests/data/adeno_fiber.p2.afa rename to src/pyfamsa/tests/data/adeno_fiber.p2.afa diff --git a/pyfamsa/tests/data/adeno_fiber.sl.afa b/src/pyfamsa/tests/data/adeno_fiber.sl.afa similarity index 100% rename from pyfamsa/tests/data/adeno_fiber.sl.afa rename to src/pyfamsa/tests/data/adeno_fiber.sl.afa diff --git a/pyfamsa/tests/data/adeno_fiber.sl.nwk b/src/pyfamsa/tests/data/adeno_fiber.sl.nwk similarity index 100% rename from pyfamsa/tests/data/adeno_fiber.sl.nwk rename to src/pyfamsa/tests/data/adeno_fiber.sl.nwk diff --git a/pyfamsa/tests/data/adeno_fiber.upgma.afa b/src/pyfamsa/tests/data/adeno_fiber.upgma.afa similarity index 100% rename from pyfamsa/tests/data/adeno_fiber.upgma.afa rename to src/pyfamsa/tests/data/adeno_fiber.upgma.afa diff --git a/pyfamsa/tests/data/adeno_fiber.upgma.nwk b/src/pyfamsa/tests/data/adeno_fiber.upgma.nwk similarity index 100% rename from pyfamsa/tests/data/adeno_fiber.upgma.nwk rename to src/pyfamsa/tests/data/adeno_fiber.upgma.nwk diff --git a/pyfamsa/tests/data/adeno_fiber.upgma.pp.afa b/src/pyfamsa/tests/data/adeno_fiber.upgma.pp.afa similarity index 100% rename from pyfamsa/tests/data/adeno_fiber.upgma.pp.afa rename to src/pyfamsa/tests/data/adeno_fiber.upgma.pp.afa diff --git a/pyfamsa/tests/data/hemopexin.faa b/src/pyfamsa/tests/data/hemopexin.faa similarity index 100% rename from pyfamsa/tests/data/hemopexin.faa rename to src/pyfamsa/tests/data/hemopexin.faa diff --git a/pyfamsa/tests/data/hemopexin.medoid-nj.afa b/src/pyfamsa/tests/data/hemopexin.medoid-nj.afa similarity index 100% rename from pyfamsa/tests/data/hemopexin.medoid-nj.afa rename to src/pyfamsa/tests/data/hemopexin.medoid-nj.afa diff --git a/pyfamsa/tests/data/hemopexin.medoid-nj.nwk b/src/pyfamsa/tests/data/hemopexin.medoid-nj.nwk similarity index 100% rename from pyfamsa/tests/data/hemopexin.medoid-nj.nwk rename to src/pyfamsa/tests/data/hemopexin.medoid-nj.nwk diff --git a/pyfamsa/tests/data/hemopexin.medoid-sl.afa b/src/pyfamsa/tests/data/hemopexin.medoid-sl.afa similarity index 100% rename from pyfamsa/tests/data/hemopexin.medoid-sl.afa rename to src/pyfamsa/tests/data/hemopexin.medoid-sl.afa diff --git a/pyfamsa/tests/data/hemopexin.medoid-sl.nwk b/src/pyfamsa/tests/data/hemopexin.medoid-sl.nwk similarity index 100% rename from pyfamsa/tests/data/hemopexin.medoid-sl.nwk rename to src/pyfamsa/tests/data/hemopexin.medoid-sl.nwk diff --git a/pyfamsa/tests/data/hemopexin.medoid-slink.nwk b/src/pyfamsa/tests/data/hemopexin.medoid-slink.nwk similarity index 100% rename from pyfamsa/tests/data/hemopexin.medoid-slink.nwk rename to src/pyfamsa/tests/data/hemopexin.medoid-slink.nwk diff --git a/pyfamsa/tests/data/hemopexin.medoid-upgma.afa b/src/pyfamsa/tests/data/hemopexin.medoid-upgma.afa similarity index 100% rename from pyfamsa/tests/data/hemopexin.medoid-upgma.afa rename to src/pyfamsa/tests/data/hemopexin.medoid-upgma.afa diff --git a/pyfamsa/tests/data/hemopexin.medoid-upgma.nwk b/src/pyfamsa/tests/data/hemopexin.medoid-upgma.nwk similarity index 100% rename from pyfamsa/tests/data/hemopexin.medoid-upgma.nwk rename to src/pyfamsa/tests/data/hemopexin.medoid-upgma.nwk diff --git a/pyfamsa/tests/fasta.py b/src/pyfamsa/tests/fasta.py similarity index 100% rename from pyfamsa/tests/fasta.py rename to src/pyfamsa/tests/fasta.py diff --git a/pyfamsa/tests/requirements.txt b/src/pyfamsa/tests/requirements.txt similarity index 100% rename from pyfamsa/tests/requirements.txt rename to src/pyfamsa/tests/requirements.txt diff --git a/pyfamsa/tests/test_aligner.py b/src/pyfamsa/tests/test_aligner.py similarity index 100% rename from pyfamsa/tests/test_aligner.py rename to src/pyfamsa/tests/test_aligner.py diff --git a/pyfamsa/tests/test_alignment.py b/src/pyfamsa/tests/test_alignment.py similarity index 100% rename from pyfamsa/tests/test_alignment.py rename to src/pyfamsa/tests/test_alignment.py diff --git a/pyfamsa/tests/test_doctest.py b/src/pyfamsa/tests/test_doctest.py similarity index 100% rename from pyfamsa/tests/test_doctest.py rename to src/pyfamsa/tests/test_doctest.py diff --git a/pyfamsa/tests/test_sequence.py b/src/pyfamsa/tests/test_sequence.py similarity index 100% rename from pyfamsa/tests/test_sequence.py rename to src/pyfamsa/tests/test_sequence.py From 9fc835b1bf36351d148d3bf40cb4f2479c493db0 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Tue, 5 Nov 2024 23:01:39 +0100 Subject: [PATCH 02/13] Fix paths to FAMSA test data in `pyfamsa.tests` --- src/pyfamsa/tests/data/adeno_fiber.faa | 2 +- src/pyfamsa/tests/data/adeno_fiber.p1.afa | 2 +- src/pyfamsa/tests/data/adeno_fiber.p2.afa | 2 +- src/pyfamsa/tests/data/adeno_fiber.sl.afa | 2 +- src/pyfamsa/tests/data/adeno_fiber.sl.nwk | 2 +- src/pyfamsa/tests/data/adeno_fiber.upgma.afa | 2 +- src/pyfamsa/tests/data/adeno_fiber.upgma.nwk | 2 +- src/pyfamsa/tests/data/adeno_fiber.upgma.pp.afa | 2 +- src/pyfamsa/tests/data/hemopexin.faa | 2 +- src/pyfamsa/tests/data/hemopexin.medoid-nj.afa | 2 +- src/pyfamsa/tests/data/hemopexin.medoid-nj.nwk | 2 +- src/pyfamsa/tests/data/hemopexin.medoid-sl.afa | 2 +- src/pyfamsa/tests/data/hemopexin.medoid-sl.nwk | 2 +- src/pyfamsa/tests/data/hemopexin.medoid-slink.nwk | 2 +- src/pyfamsa/tests/data/hemopexin.medoid-upgma.afa | 2 +- src/pyfamsa/tests/data/hemopexin.medoid-upgma.nwk | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/pyfamsa/tests/data/adeno_fiber.faa b/src/pyfamsa/tests/data/adeno_fiber.faa index 685db5f..0b9f961 120000 --- a/src/pyfamsa/tests/data/adeno_fiber.faa +++ b/src/pyfamsa/tests/data/adeno_fiber.faa @@ -1 +1 @@ -../../../vendor/FAMSA/test/adeno_fiber/adeno_fiber \ No newline at end of file +../../../../vendor/FAMSA/test/adeno_fiber/adeno_fiber \ No newline at end of file diff --git a/src/pyfamsa/tests/data/adeno_fiber.p1.afa b/src/pyfamsa/tests/data/adeno_fiber.p1.afa index e8dd57e..80b219c 120000 --- a/src/pyfamsa/tests/data/adeno_fiber.p1.afa +++ b/src/pyfamsa/tests/data/adeno_fiber.p1.afa @@ -1 +1 @@ -../../../vendor/FAMSA/test/adeno_fiber/upgma.no_refine.part1.fasta \ No newline at end of file +../../../../vendor/FAMSA/test/adeno_fiber/upgma.no_refine.part1.fasta \ No newline at end of file diff --git a/src/pyfamsa/tests/data/adeno_fiber.p2.afa b/src/pyfamsa/tests/data/adeno_fiber.p2.afa index 607a24f..672ccae 120000 --- a/src/pyfamsa/tests/data/adeno_fiber.p2.afa +++ b/src/pyfamsa/tests/data/adeno_fiber.p2.afa @@ -1 +1 @@ -../../../vendor/FAMSA/test/adeno_fiber/upgma.no_refine.part2.fasta \ No newline at end of file +../../../../vendor/FAMSA/test/adeno_fiber/upgma.no_refine.part2.fasta \ No newline at end of file diff --git a/src/pyfamsa/tests/data/adeno_fiber.sl.afa b/src/pyfamsa/tests/data/adeno_fiber.sl.afa index aaf1d6a..9417e93 120000 --- a/src/pyfamsa/tests/data/adeno_fiber.sl.afa +++ b/src/pyfamsa/tests/data/adeno_fiber.sl.afa @@ -1 +1 @@ -../../../vendor/FAMSA/test/adeno_fiber/sl.fasta \ No newline at end of file +../../../../vendor/FAMSA/test/adeno_fiber/sl.fasta \ No newline at end of file diff --git a/src/pyfamsa/tests/data/adeno_fiber.sl.nwk b/src/pyfamsa/tests/data/adeno_fiber.sl.nwk index 4a67f19..b5dd545 120000 --- a/src/pyfamsa/tests/data/adeno_fiber.sl.nwk +++ b/src/pyfamsa/tests/data/adeno_fiber.sl.nwk @@ -1 +1 @@ -../../../vendor/FAMSA/test/adeno_fiber/sl.dnd \ No newline at end of file +../../../../vendor/FAMSA/test/adeno_fiber/sl.dnd \ No newline at end of file diff --git a/src/pyfamsa/tests/data/adeno_fiber.upgma.afa b/src/pyfamsa/tests/data/adeno_fiber.upgma.afa index 94904cb..931e82d 120000 --- a/src/pyfamsa/tests/data/adeno_fiber.upgma.afa +++ b/src/pyfamsa/tests/data/adeno_fiber.upgma.afa @@ -1 +1 @@ -../../../vendor/FAMSA/test/adeno_fiber/upgma.fasta \ No newline at end of file +../../../../vendor/FAMSA/test/adeno_fiber/upgma.fasta \ No newline at end of file diff --git a/src/pyfamsa/tests/data/adeno_fiber.upgma.nwk b/src/pyfamsa/tests/data/adeno_fiber.upgma.nwk index 50fd871..9cb882c 120000 --- a/src/pyfamsa/tests/data/adeno_fiber.upgma.nwk +++ b/src/pyfamsa/tests/data/adeno_fiber.upgma.nwk @@ -1 +1 @@ -../../../vendor/FAMSA/test/adeno_fiber/upgma.dnd \ No newline at end of file +../../../../vendor/FAMSA/test/adeno_fiber/upgma.dnd \ No newline at end of file diff --git a/src/pyfamsa/tests/data/adeno_fiber.upgma.pp.afa b/src/pyfamsa/tests/data/adeno_fiber.upgma.pp.afa index 4314c59..0a53968 120000 --- a/src/pyfamsa/tests/data/adeno_fiber.upgma.pp.afa +++ b/src/pyfamsa/tests/data/adeno_fiber.upgma.pp.afa @@ -1 +1 @@ -../../../vendor/FAMSA/test/adeno_fiber/upgma.pp.fasta \ No newline at end of file +../../../../vendor/FAMSA/test/adeno_fiber/upgma.pp.fasta \ No newline at end of file diff --git a/src/pyfamsa/tests/data/hemopexin.faa b/src/pyfamsa/tests/data/hemopexin.faa index 8ec41b1..ddc58f1 120000 --- a/src/pyfamsa/tests/data/hemopexin.faa +++ b/src/pyfamsa/tests/data/hemopexin.faa @@ -1 +1 @@ -../../../vendor/FAMSA/test/hemopexin/hemopexin \ No newline at end of file +../../../../vendor/FAMSA/test/hemopexin/hemopexin \ No newline at end of file diff --git a/src/pyfamsa/tests/data/hemopexin.medoid-nj.afa b/src/pyfamsa/tests/data/hemopexin.medoid-nj.afa index d943fc8..b263022 120000 --- a/src/pyfamsa/tests/data/hemopexin.medoid-nj.afa +++ b/src/pyfamsa/tests/data/hemopexin.medoid-nj.afa @@ -1 +1 @@ -../../../vendor/FAMSA/test/hemopexin/medoid-nj.fasta \ No newline at end of file +../../../../vendor/FAMSA/test/hemopexin/medoid-nj.fasta \ No newline at end of file diff --git a/src/pyfamsa/tests/data/hemopexin.medoid-nj.nwk b/src/pyfamsa/tests/data/hemopexin.medoid-nj.nwk index c2c49b1..69ea2ce 120000 --- a/src/pyfamsa/tests/data/hemopexin.medoid-nj.nwk +++ b/src/pyfamsa/tests/data/hemopexin.medoid-nj.nwk @@ -1 +1 @@ -../../../vendor/FAMSA/test/hemopexin/medoid-nj.dnd \ No newline at end of file +../../../../vendor/FAMSA/test/hemopexin/medoid-nj.dnd \ No newline at end of file diff --git a/src/pyfamsa/tests/data/hemopexin.medoid-sl.afa b/src/pyfamsa/tests/data/hemopexin.medoid-sl.afa index 5b0707e..c41750d 120000 --- a/src/pyfamsa/tests/data/hemopexin.medoid-sl.afa +++ b/src/pyfamsa/tests/data/hemopexin.medoid-sl.afa @@ -1 +1 @@ -../../../vendor/FAMSA/test/hemopexin/medoid-sl.fasta \ No newline at end of file +../../../../vendor/FAMSA/test/hemopexin/medoid-sl.fasta \ No newline at end of file diff --git a/src/pyfamsa/tests/data/hemopexin.medoid-sl.nwk b/src/pyfamsa/tests/data/hemopexin.medoid-sl.nwk index e4918f2..20dbbec 120000 --- a/src/pyfamsa/tests/data/hemopexin.medoid-sl.nwk +++ b/src/pyfamsa/tests/data/hemopexin.medoid-sl.nwk @@ -1 +1 @@ -../../../vendor/FAMSA/test/hemopexin/medoid-sl.dnd \ No newline at end of file +../../../../vendor/FAMSA/test/hemopexin/medoid-sl.dnd \ No newline at end of file diff --git a/src/pyfamsa/tests/data/hemopexin.medoid-slink.nwk b/src/pyfamsa/tests/data/hemopexin.medoid-slink.nwk index be52ba8..1e05539 120000 --- a/src/pyfamsa/tests/data/hemopexin.medoid-slink.nwk +++ b/src/pyfamsa/tests/data/hemopexin.medoid-slink.nwk @@ -1 +1 @@ -../../../vendor/FAMSA/test/hemopexin/medoid-slink.dnd \ No newline at end of file +../../../../vendor/FAMSA/test/hemopexin/medoid-slink.dnd \ No newline at end of file diff --git a/src/pyfamsa/tests/data/hemopexin.medoid-upgma.afa b/src/pyfamsa/tests/data/hemopexin.medoid-upgma.afa index 89eba1e..23dd321 120000 --- a/src/pyfamsa/tests/data/hemopexin.medoid-upgma.afa +++ b/src/pyfamsa/tests/data/hemopexin.medoid-upgma.afa @@ -1 +1 @@ -../../../vendor/FAMSA/test/hemopexin/medoid-upgma.fasta \ No newline at end of file +../../../../vendor/FAMSA/test/hemopexin/medoid-upgma.fasta \ No newline at end of file diff --git a/src/pyfamsa/tests/data/hemopexin.medoid-upgma.nwk b/src/pyfamsa/tests/data/hemopexin.medoid-upgma.nwk index e0de9ba..6c14b92 120000 --- a/src/pyfamsa/tests/data/hemopexin.medoid-upgma.nwk +++ b/src/pyfamsa/tests/data/hemopexin.medoid-upgma.nwk @@ -1 +1 @@ -../../../vendor/FAMSA/test/hemopexin/medoid-upgma.dnd \ No newline at end of file +../../../../vendor/FAMSA/test/hemopexin/medoid-upgma.dnd \ No newline at end of file From f66f130be6e2b30a062a92fba69dc077c3dd5901 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Tue, 5 Nov 2024 23:24:19 +0100 Subject: [PATCH 03/13] Remove remaining `git` headers from diff patches --- patches/sequence.cpp.patch | 4 ---- patches/sequence.h.patch | 4 ---- 2 files changed, 8 deletions(-) diff --git a/patches/sequence.cpp.patch b/patches/sequence.cpp.patch index cc6f07d..5b7c7f6 100644 --- a/patches/sequence.cpp.patch +++ b/patches/sequence.cpp.patch @@ -1,7 +1,3 @@ -diff --git a/src/core/sequence.cpp b/src/core/sequence.cpp -index 54401be..83d0f2f 100644 ---- a/src/core/sequence.cpp -+++ b/src/core/sequence.cpp @@ -19,6 +19,18 @@ char CGappedSequence::mapping_table[25] = "ARNDCQEGHILKMFPSTWYVBZX*"; diff --git a/patches/sequence.h.patch b/patches/sequence.h.patch index fdd0e50..3e0a5bd 100644 --- a/patches/sequence.h.patch +++ b/patches/sequence.h.patch @@ -1,7 +1,3 @@ -diff --git a/src/core/sequence.h b/src/core/sequence.h -index ac37942..e17620e 100644 ---- a/src/core/sequence.h -+++ b/src/core/sequence.h @@ -32,7 +32,7 @@ public: bit_vec_t *p_bit_masks; uint32_t p_bv_len; From 5782dc04702f5ca06c6fa98c102fc4135eed32c9 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Tue, 5 Nov 2024 23:24:35 +0100 Subject: [PATCH 04/13] Add `pyproject.toml` to handle build with `scikit-build-core` --- .gitignore | 1 - pyproject.toml | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 pyproject.toml diff --git a/.gitignore b/.gitignore index 5c828c4..547e7d9 100644 --- a/.gitignore +++ b/.gitignore @@ -97,7 +97,6 @@ share/python-wheels/ .installed.cfg *.egg MANIFEST -pyproject.toml # PyInstaller # Usually these files are written by a python script from a template diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..40b55c5 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,14 @@ +[build-system] +requires = ['scikit-build-core', 'cython ~=3.0', 'scoring-matrices ~=0.3.0', 'semantic-version ~=2.10'] +build-backend = "scikit_build_core.build" + +[project] +name = "pyfamsa" +version = "0.6.0" + + + +[tool.scikit-build] +build-dir = "build/{build_type}" +editable.rebuild = true +editable.verbose = false \ No newline at end of file From 39347593d0da217a2286d2f8e6f651305d2f4c72 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Tue, 5 Nov 2024 23:26:09 +0100 Subject: [PATCH 05/13] Remove `PyInterpreterState_GetID` patch from `_famsa.pyx` --- src/pyfamsa/_famsa.pyx | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/pyfamsa/_famsa.pyx b/src/pyfamsa/_famsa.pyx index 25842ed..7007201 100644 --- a/src/pyfamsa/_famsa.pyx +++ b/src/pyfamsa/_famsa.pyx @@ -134,17 +134,6 @@ cdef extern from *: void sort_sequences(vector[CSequence*]& sequences) void shuffle_sequences(vector[CSequence*]& sequences, int shuffle) -# --- PyPI patch -------------------------------------------------------------- - -cdef extern from *: - """ - #ifndef HAS_PYINTERPRETERSTATE_GETID - int64_t PyInterpreterState_GetID(PyInterpreterState *interp) { - return 0; - } - #endif - """ - # --- Classes ---------------------------------------------------------------- cdef class Sequence: From 03a4720d7f31c3b8647905c9117016439ce6d18d Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Tue, 5 Nov 2024 23:28:48 +0100 Subject: [PATCH 06/13] Add CMake files to generate and compile the project --- CMakeLists.txt | 22 ++++ src/CMakeLists.txt | 2 + src/FAMSA/CMakeLists.txt | 107 ++++++++++++++++++ src/pyfamsa/CMakeLists.txt | 1 + src/scripts/apply_patch.py | 57 ++++++++++ src/scripts/cmake/CythonExtension.cmake | 139 ++++++++++++++++++++++++ src/scripts/cmake/pystate_patch.h | 10 ++ 7 files changed, 338 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 src/CMakeLists.txt create mode 100644 src/FAMSA/CMakeLists.txt create mode 100644 src/pyfamsa/CMakeLists.txt create mode 100644 src/scripts/apply_patch.py create mode 100644 src/scripts/cmake/CythonExtension.cmake create mode 100644 src/scripts/cmake/pystate_patch.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..76626c5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.20) +project(${SKBUILD_PROJECT_NAME} VERSION ${SKBUILD_PROJECT_VERSION} LANGUAGES C CXX) + +set(BUILD_SHARED_LIBS OFF) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_CXX_STANDARD 20) + +set_property(GLOBAL PROPERTY PYTHON_EXTENSIONS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) + +message(STATUS "Building ${SKBUILD_PROJECT_NAME} for ${CMAKE_SYSTEM_PROCESSOR}") + +# --- Setup include folders ---------------------------------------------------- + +set(CYTHON_HEADERS_DIR ${CMAKE_CURRENT_LIST_DIR}/include) + +# --- Add scripts for Cython --------------------------------------------------- + +include("src/scripts/cmake/CythonExtension.cmake") + +# --- Compile code ------------------------------------------------------------- + +add_subdirectory("src") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..0dc5fbb --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(FAMSA) +add_subdirectory(pyfamsa) \ No newline at end of file diff --git a/src/FAMSA/CMakeLists.txt b/src/FAMSA/CMakeLists.txt new file mode 100644 index 0000000..b0b5069 --- /dev/null +++ b/src/FAMSA/CMakeLists.txt @@ -0,0 +1,107 @@ +set(FAMSA_SOURCES + msa.cpp + msa_refinement.cpp + + tree/AbstractTreeGenerator.cpp + tree/Clustering.cpp + tree/DistanceCalculator.cpp + tree/FastTree.cpp + tree/GuideTree.cpp + tree/MSTPrim.cpp + tree/NeighborJoining.cpp + tree/NewickParser.cpp + tree/SingleLinkage.cpp + tree/UPGMA.cpp + + utils/timer.cpp + utils/log.cpp + utils/utils.cpp + + core/params.cpp + core/profile.cpp + core/profile_par.cpp + core/profile_seq.cpp + core/sequence.cpp + core/queues.cpp + + lcs/lcsbp.cpp + lcs/lcsbp_classic.cpp + + core/defs.h + core/params.h + core/profile.h + core/queues.h + core/sequence.h + core/version.h + + lcs/lcsbp_avx_intr.h + lcs/lcsbp_avx2_intr.h + lcs/lcsbp_classic.h + lcs/lcsbp_neon_intr.h + lcs/lcsbp.h + + tree/AbstractTreeGenerator.h + tree/AbstractTreeGenerator.hpp + tree/Chained.h + tree/Clustering.h + tree/DistanceCalculator.h + tree/FastTree.h + tree/GuideTree.h + tree/IPartialGenerator.h + tree/MSTPrim.h + tree/NeighborJoining.h + tree/NewickParser.h + tree/SingleLinkage.h + tree/SingleLinkageQueue.h + tree/TreeDefs.h + tree/UPGMA.h + + utils/array.h + utils/conversion.h + utils/cpuid.h + utils/deterministic_random.h + utils/log.h + utils/memory_monotonic.h + utils/meta_oper.h + utils/pooled_threads.h + utils/statistics.h + utils/timer.h + utils/utils.h + + msa.h + +) + +foreach(_file IN ITEMS ${FAMSA_SOURCES}) + cmake_path(GET _file FILENAME _name) + if(EXISTS ${PROJECT_SOURCE_DIR}/patches/${_name}.patch) + add_custom_command( + OUTPUT + ${_file} + COMMENT + "Patching ${_file}" + COMMAND + ${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/scripts/apply_patch.py + --input ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/${_file} + --patch ${PROJECT_SOURCE_DIR}/patches/${_name}.patch + --output ${CMAKE_CURRENT_BINARY_DIR}/${_file} + DEPENDS + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/${_file} + ${PROJECT_SOURCE_DIR}/patches/${_name}.patch + ) + else() + add_custom_command( + OUTPUT + ${_file} + COMMAND + cmake -E copy ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/${_file} ${CMAKE_CURRENT_BINARY_DIR}/${_file} + DEPENDS + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/${_file} + ) + endif() + set(FAMSA_PATCHED_SOURCES ${FAMSA_PATCHED_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/${_file}) +endforeach() + +add_library(famsa STATIC ${FAMSA_PATCHED_SOURCES}) +target_include_directories(famsa PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) +target_include_directories(famsa PUBLIC ${PROJECT_SOURCE_DIR}/vendor/FAMSA/libs) # FIXME? \ No newline at end of file diff --git a/src/pyfamsa/CMakeLists.txt b/src/pyfamsa/CMakeLists.txt new file mode 100644 index 0000000..eff7479 --- /dev/null +++ b/src/pyfamsa/CMakeLists.txt @@ -0,0 +1 @@ +cython_extension(_famsa LINKS famsa) \ No newline at end of file diff --git a/src/scripts/apply_patch.py b/src/scripts/apply_patch.py new file mode 100644 index 0000000..2a76f01 --- /dev/null +++ b/src/scripts/apply_patch.py @@ -0,0 +1,57 @@ +import argparse +import re + + +_HEADER_PATTERN = re.compile(r"^@@ -(\d+),?(\d+)? \+(\d+),?(\d+)? @@.*$") + + +def _apply_patch(s, patch, revert=False): + # see https://stackoverflow.com/a/40967337 + s = s.splitlines(keepends=True) + p = patch.splitlines(keepends=True) + t = [] + i = 0 + sl = 0 + midx, sign = (1, "+") if not revert else (3, "-") + while i < len(p) and p[i].startswith(("---", "+++")): + i += 1 # skip header lines + + while i < len(p): + match = _HEADER_PATTERN.match(p[i]) + if not match: + raise ValueError("Invalid line in patch: {!r}".format(p[i])) + i += 1 + l = int(match.group(midx)) - 1 + (match.group(midx + 1) == "0") + t.extend(s[sl:l]) + sl = l + while i < len(p) and p[i][0] != "@": + if i + 1 < len(p) and p[i + 1][0] == "\\": + line = p[i][:-1] + i += 2 + else: + line = p[i] + i += 1 + if len(line) > 0: + if line[0] == sign or line[0] == " ": + t += line[1:] + sl += line[0] != sign + + t.extend(s[sl:]) + return "".join(t) + + +parser = argparse.ArgumentParser() +parser.add_argument("-i", "--input", required=True) +parser.add_argument("-p", "--patch", required=True) +parser.add_argument("-o", "--output", required=True) +args = parser.parse_args() + +with open(args.input, "r") as f: + in_ = f.read() +with open(args.patch, "r") as f: + patch = f.read() + +patched = _apply_patch(in_, patch) + +with open(args.output, "w") as dst: + dst.write(patched) diff --git a/src/scripts/cmake/CythonExtension.cmake b/src/scripts/cmake/CythonExtension.cmake new file mode 100644 index 0000000..ce0ee70 --- /dev/null +++ b/src/scripts/cmake/CythonExtension.cmake @@ -0,0 +1,139 @@ +find_package(Python COMPONENTS Interpreter Development.Module REQUIRED) +get_property(PYTHON_EXTENSIONS_SOURCE_DIR GLOBAL PROPERTY PYTHON_EXTENSIONS_SOURCE_DIR) + +# --- Detect PyInterpreterState_GetID ------------------------------------------ + +include(CheckSymbolExists) + +set(SAFE_CMAKE_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES}") +set(SAFE_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}") +set(SAFE_CMAKE_REQUIRED_LINK_DIRECTORIES "${CMAKE_REQUIRED_LINK_DIRECTORIES}") +set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${Python_INCLUDE_DIRS}) +set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${Python_LIBRARIES}) +set(CMAKE_REQUIRED_LINK_DIRECTORIES ${CMAKE_REQUIRED_LINK_DIRECTORIES} ${Python_LIBRARY_DIRS}) +check_symbol_exists(PyInterpreterState_GetID "stdint.h;stdlib.h;Python.h" HAVE_PYINTERPRETERSTATE_GETID) +set(CMAKE_REQUIRED_INCLUDES "${SAFE_CMAKE_REQUIRED_INCLUDES}") +set(CMAKE_REQUIRED_LIBRARIES "${SAFE_CMAKE_REQUIRED_LIBRARIES}") +set(CMAKE_REQUIRED_LINK_DIRECTORIES "${SAFE_CMAKE_REQUIRED_LINK_DIRECTORIES}") +set(PYSTATE_PATCH_H ${CMAKE_CURRENT_LIST_DIR}/pystate_patch.h) + +# --- Prepare Cython directives and constants ---------------------------------- + +set(CYTHON_DIRECTIVES + -X cdivision=True + -X nonecheck=False + -E SSE2_BUILD_SUPPORT=$,True,False> + -E SSE4_BUILD_SUPPORT=$,True,False> + -E AVX2_BUILD_SUPPORT=$,True,False> + -E NEON_BUILD_SUPPORT=$,True,False> + -E SYS_IMPLEMENTATION_NAME=$ + -E SYS_VERSION_INFO_MAJOR=${Python_VERSION_MAJOR} + -E SYS_VERSION_INFO_MINOR=${Python_VERSION_MINOR} + -E TARGET_CPU=$ + -E PROJECT_VERSION=${CMAKE_PROJECT_VERSION} +) + +if(CMAKE_BUILD_TYPE STREQUAL Debug) + set(CYTHON_DIRECTIVES + ${CYTHON_DIRECTIVES} + -X cdivision_warnings=True + -X warn.undeclared=True + -X warn.unreachable=True + -X warn.maybe_uninitialized=True + -X warn.unused=True + -X warn.unused_arg=True + -X warn.unused_result=True + -X warn.multiple_declarators=True + ) + if(NOT Python_INTERPRETER_ID STREQUAL PyPy) + set(CYTHON_DIRECTIVES + ${CYTHON_DIRECTIVES} + -X linetrace=true + ) + endif() +else() + set(CYTHON_DIRECTIVES + ${CYTHON_DIRECTIVES} + -X boundscheck=False + -X wraparound=False + ) +endif() + +# --- Detect `scoring-matrices` folder ----------------------------------------- + +execute_process( + COMMAND ${Python_EXECUTABLE} -c "import os; import scoring_matrices; print(os.path.dirname(scoring_matrices.__path__[0]), end='')" + OUTPUT_VARIABLE SCORING_MATRICES_PATH +) + +# --- Detect `pyopal` folder --------------------------------------------------- + +execute_process( + COMMAND ${Python_EXECUTABLE} -c "import os; import pyopal; print(os.path.dirname(pyopal.__path__[0]), end='')" + OUTPUT_VARIABLE PYOPAL_PATH +) + +# --- Declare Cython extension ------------------------------------------------- + +macro(cython_extension _name) + set(multiValueArgs LINKS DIRECTIVES EXTRA_SOURCES OPTIONS) + cmake_parse_arguments(CYTHON_EXTENSION "" "" "${multiValueArgs}" ${ARGN} ) + + # Make sure that the source directory is known + if(NOT DEFINED PYTHON_EXTENSIONS_SOURCE_DIR) + message(FATAL_ERROR "The PYTHON_EXTENSIONS_SOURCE_DIR variable has not been set.") + endif() + + # Generate C file from Cython file + add_custom_command( + OUTPUT ${_name}.cpp + COMMENT + "Cythonizing ${_name}.pyx to ${_name}.cpp" + COMMAND + Python::Interpreter -m cython + "${CMAKE_CURRENT_SOURCE_DIR}/${_name}.pyx" + --output-file ${_name}.cpp + --cplus + --depfile + -I "${CYTHON_HEADERS_DIR}" + -I "${SCORING_MATRICES_PATH}" + -I "${PYOPAL_PATH}" + ${CYTHON_DIRECTIVES} + MAIN_DEPENDENCY + ${_name}.pyx + DEPFILE + ${_name}.cpp.dep + VERBATIM) + + # Build fully-qualified module name as the target name + string(REGEX REPLACE "^${PYTHON_EXTENSIONS_SOURCE_DIR}/?" "" _dest_folder ${CMAKE_CURRENT_SOURCE_DIR}) + string(REPLACE "/" "." _target ${_dest_folder}.${_name}) + + # Add Python module + python_add_library(${_target} MODULE WITH_SOABI ${_name}.pyx ${_name}.cpp ${CYTHON_EXTENSION_EXTRA_SOURCES}) + set_target_properties(${_target} PROPERTIES OUTPUT_NAME ${_name} ) + target_include_directories(${_target} AFTER PUBLIC ${PYOPAL_PATH} ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(${_target} PUBLIC ${CYTHON_EXTENSION_LINKS}) + target_precompile_headers(${_target} PRIVATE ${PYSTATE_PATCH_H}) + if(HAVE_PYINTERPRETERSTATE_GETID) + target_compile_definitions(${_target} PUBLIC HAVE_PYINTERPRETERSTATE_GETID) + endif() + + if(CMAKE_BUILD_TYPE STREQUAL Debug) + if(NOT Python_INTERPRETER_ID STREQUAL PyPy) + target_compile_definitions(${_target} PUBLIC CYTHON_TRACE_NOGIL=1) + endif() + else() + target_compile_definitions(${_target} PUBLIC CYTHON_WITHOUT_ASSERTIONS=1) + endif() + + # Preserve the relative project structure in the install directory + string(REGEX REPLACE "^${PYTHON_EXTENSIONS_SOURCE_DIR}/?" "" _dest_folder ${CMAKE_CURRENT_SOURCE_DIR}) + install(TARGETS ${_target} DESTINATION ${_dest_folder} ) + message(DEBUG "Install folder for extension ${_name}: ${_dest_folder}") + + # Add the targets to the list of Cython extensions + get_property(_ext GLOBAL PROPERTY PYRODIGAL_CYTHON_EXTENSIONS) + list(APPEND _ext ${_target}) + set_property(GLOBAL PROPERTY PYRODIGAL_CYTHON_EXTENSIONS ${_ext}) +endmacro() diff --git a/src/scripts/cmake/pystate_patch.h b/src/scripts/cmake/pystate_patch.h new file mode 100644 index 0000000..025856e --- /dev/null +++ b/src/scripts/cmake/pystate_patch.h @@ -0,0 +1,10 @@ +#ifndef HAVE_PYINTERPRETERSTATE_GETID +#define HAVE_PYINTERPRETERSTATE_GETID + +#include + +#ifndef PyInterpreterState_GetID +#define PyInterpreterState_GetID(x) (0) + +#endif +#endif \ No newline at end of file From 01de625f800d1caf22a1aeaf6c77fe72fb0056dd Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Wed, 6 Nov 2024 00:08:29 +0100 Subject: [PATCH 07/13] Implement compilation of SIMD code from FAMSA with CMake --- CMakeLists.txt | 6 ++ src/FAMSA/CMakeLists.txt | 81 +++++++++++++++++++--- src/scripts/cmake/FindAVX2.cmake | 104 +++++++++++++++++++++++++++++ src/scripts/cmake/FindAVX512.cmake | 101 ++++++++++++++++++++++++++++ src/scripts/cmake/FindNEON.cmake | 97 +++++++++++++++++++++++++++ src/scripts/cmake/FindSSE2.cmake | 100 +++++++++++++++++++++++++++ src/scripts/cmake/FindSSE4.cmake | 101 ++++++++++++++++++++++++++++ 7 files changed, 579 insertions(+), 11 deletions(-) create mode 100644 src/scripts/cmake/FindAVX2.cmake create mode 100644 src/scripts/cmake/FindAVX512.cmake create mode 100644 src/scripts/cmake/FindNEON.cmake create mode 100644 src/scripts/cmake/FindSSE2.cmake create mode 100644 src/scripts/cmake/FindSSE4.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 76626c5..737212c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,12 @@ set(CYTHON_HEADERS_DIR ${CMAKE_CURRENT_LIST_DIR}/include) # --- Add scripts for Cython --------------------------------------------------- +# include("src/scripts/cmake/FindAVX1.cmake") +include("src/scripts/cmake/FindAVX2.cmake") +# include("src/scripts/cmake/FindAVX512.cmake") +include("src/scripts/cmake/FindNEON.cmake") +include("src/scripts/cmake/FindSSE2.cmake") +include("src/scripts/cmake/FindSSE4.cmake") include("src/scripts/cmake/CythonExtension.cmake") # --- Compile code ------------------------------------------------------------- diff --git a/src/FAMSA/CMakeLists.txt b/src/FAMSA/CMakeLists.txt index b0b5069..8f6f9e9 100644 --- a/src/FAMSA/CMakeLists.txt +++ b/src/FAMSA/CMakeLists.txt @@ -1,7 +1,7 @@ set(FAMSA_SOURCES msa.cpp msa_refinement.cpp - + tree/AbstractTreeGenerator.cpp tree/Clustering.cpp tree/DistanceCalculator.cpp @@ -16,7 +16,7 @@ set(FAMSA_SOURCES utils/timer.cpp utils/log.cpp utils/utils.cpp - + core/params.cpp core/profile.cpp core/profile_par.cpp @@ -24,9 +24,6 @@ set(FAMSA_SOURCES core/sequence.cpp core/queues.cpp - lcs/lcsbp.cpp - lcs/lcsbp_classic.cpp - core/defs.h core/params.h core/profile.h @@ -69,20 +66,19 @@ set(FAMSA_SOURCES utils/utils.h msa.h - ) foreach(_file IN ITEMS ${FAMSA_SOURCES}) cmake_path(GET _file FILENAME _name) if(EXISTS ${PROJECT_SOURCE_DIR}/patches/${_name}.patch) add_custom_command( - OUTPUT + OUTPUT ${_file} COMMENT "Patching ${_file}" COMMAND - ${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/scripts/apply_patch.py - --input ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/${_file} + ${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/scripts/apply_patch.py + --input ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/${_file} --patch ${PROJECT_SOURCE_DIR}/patches/${_name}.patch --output ${CMAKE_CURRENT_BINARY_DIR}/${_file} DEPENDS @@ -91,7 +87,7 @@ foreach(_file IN ITEMS ${FAMSA_SOURCES}) ) else() add_custom_command( - OUTPUT + OUTPUT ${_file} COMMAND cmake -E copy ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/${_file} ${CMAKE_CURRENT_BINARY_DIR}/${_file} @@ -104,4 +100,67 @@ endforeach() add_library(famsa STATIC ${FAMSA_PATCHED_SOURCES}) target_include_directories(famsa PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) -target_include_directories(famsa PUBLIC ${PROJECT_SOURCE_DIR}/vendor/FAMSA/libs) # FIXME? \ No newline at end of file +target_include_directories(famsa PUBLIC ${PROJECT_SOURCE_DIR}/vendor/FAMSA/libs) # FIXME? + +if(HAVE_AVX2) + message(STATUS "Building FAMSA with AVX2 support") + add_library( + famsa_lcs + STATIC + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp_classic.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp_avx_intr.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp_avx2_intr.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/utils/utils_avx.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/utils/utils_avx2.cpp + ) + target_compile_definitions(famsa_lcs PRIVATE -DSIMD=2) + target_compile_options(famsa_lcs PRIVATE ${AVX2_C_FLAGS}) +elseif(HAVE_AVX1) + message(STATUS "Building FAMSA with AVX1 support") + add_library( + famsa_lcs + STATIC + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp_classic.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp_avx_intr.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/utils/utils_avx.cpp + ) + target_compile_definitions(famsa_lcs PRIVATE -DSIMD=1) + target_compile_options(famsa_lcs PRIVATE ${AVX1_C_FLAGS}) +elseif(HAVE_SSE4) + message(STATUS "Building FAMSA with SSE4 support") + add_library( + famsa_lcs + STATIC + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp_classic.cpp + ) + target_compile_definitions(famsa_lcs PRIVATE -DSIMD=0) + target_compile_options(famsa_lcs PRIVATE ${SSE4_C_FLAGS}) +elseif(HAVE_NEON) + message(STATUS "Building FAMSA with NEON support") + add_library( + famsa_lcs + STATIC + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp_classic.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp_neon_intr.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/utils/utils_neon.cpp + ) + target_compile_definitions(famsa_lcs PRIVATE -DSIMD=4) + target_compile_options(famsa_lcs PRIVATE ${NEON_C_FLAGS}) +else() + message(STATUS "Building FAMSA without SIMD code") + add_library( + famsa_lcs + STATIC + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp.cpp + ${PROJECT_SOURCE_DIR}/vendor/FAMSA/src/lcs/lcsbp_classic.cpp + ) + target_compile_definitions(famsa_lcs PRIVATE -DSIMD=0) +endif() + + +target_link_libraries(famsa PUBLIC famsa_lcs) + diff --git a/src/scripts/cmake/FindAVX2.cmake b/src/scripts/cmake/FindAVX2.cmake new file mode 100644 index 0000000..d2cd198 --- /dev/null +++ b/src/scripts/cmake/FindAVX2.cmake @@ -0,0 +1,104 @@ +#.rst: +# FindAVX2 +# -------- +# +# Finds AVX2 support +# +# This module can be used to detect AVX2 support in a C compiler. If +# the compiler supports AVX2, the flags required to compile with +# AVX2 support are returned in variables for the different languages. +# The variables may be empty if the compiler does not need a special +# flag to support AVX2. +# +# The following variables are set: +# +# :: +# +# AVX2_C_FLAGS - flags to add to the C compiler for AVX2 support +# AVX2_FOUND - true if AVX2 is detected +# +#============================================================================= + +set(_AVX2_REQUIRED_VARS) +set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) +set(CMAKE_REQUIRED_QUIET ${AVX2_FIND_QUIETLY}) + +# sample AVX2 source code to test +set(AVX2_C_TEST_SOURCE +" +#include +void parasail_memset___m256i(__m256i *b, __m256i c, size_t len) +{ + size_t i; + for (i=0; i +void parasail_memset___m256i(__m256i *b, __m256i c, size_t len) +{ + size_t i; + for (i=0; i +uint32x4_t double_elements(uint32x4_t input) +{ + return(vaddq_u32(input, input)); +} +int main(void) +{ + uint32x4_t one; + uint32x4_t two = double_elements(one); + return 0; +} +") + +# if these are set then do not try to find them again, +# by avoiding any try_compiles for the flags +if((DEFINED NEON_C_FLAGS) OR (DEFINED HAVE_NEON)) +else() + if(WIN32) + set(NEON_C_FLAG_CANDIDATES + #Empty, if compiler automatically accepts NEON + " ") + else() + set(NEON_C_FLAG_CANDIDATES + #Empty, if compiler automatically accepts NEON + " " + "-mfpu=neon" + "-mfpu=neon -mfloat-abi=softfp" + ) + endif() + + include(CheckCSourceCompiles) + + foreach(FLAG IN LISTS NEON_C_FLAG_CANDIDATES) + set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + set(CMAKE_REQUIRED_FLAGS "${FLAG}") + unset(HAVE_NEON CACHE) + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Try NEON C flag = [${FLAG}]") + endif() + check_c_source_compiles("${NEON_C_TEST_SOURCE}" HAVE_NEON) + set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") + if(HAVE_NEON) + set(NEON_C_FLAGS_INTERNAL "${FLAG}") + break() + endif() + endforeach() + + unset(NEON_C_FLAG_CANDIDATES) + + set(NEON_C_FLAGS "${NEON_C_FLAGS_INTERNAL}" + CACHE STRING "C compiler flags for NEON intrinsics") +endif() + +list(APPEND _NEON_REQUIRED_VARS NEON_C_FLAGS) + +set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE}) + +if(_NEON_REQUIRED_VARS) + include(FindPackageHandleStandardArgs) + + find_package_handle_standard_args(NEON + REQUIRED_VARS ${_NEON_REQUIRED_VARS}) + + mark_as_advanced(${_NEON_REQUIRED_VARS}) + + unset(_NEON_REQUIRED_VARS) +else() + message(SEND_ERROR "FindNEON requires C or CXX language to be enabled") +endif() diff --git a/src/scripts/cmake/FindSSE2.cmake b/src/scripts/cmake/FindSSE2.cmake new file mode 100644 index 0000000..81e5469 --- /dev/null +++ b/src/scripts/cmake/FindSSE2.cmake @@ -0,0 +1,100 @@ +#.rst: +# FindSSE2 +# -------- +# +# Finds SSE2 support +# +# This module can be used to detect SSE2 support in a C compiler. If +# the compiler supports SSE2, the flags required to compile with +# SSE2 support are returned in variables for the different languages. +# The variables may be empty if the compiler does not need a special +# flag to support SSE2. +# +# The following variables are set: +# +# :: +# +# SSE2_C_FLAGS - flags to add to the C compiler for SSE2 support +# SSE2_FOUND - true if SSE2 is detected +# +#============================================================================= + +set(_SSE2_REQUIRED_VARS) +set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) +set(CMAKE_REQUIRED_QUIET ${SSE2_FIND_QUIETLY}) + +# sample SSE2 source code to test +set(SSE2_C_TEST_SOURCE +" +#if defined(_MSC_VER) +#include +#else +#include +#endif +int foo() { + __m128i vOne = _mm_set1_epi16(1); + __m128i result = _mm_add_epi16(vOne,vOne); + return _mm_extract_epi16(result, 0); +} +int main(void) { return foo(); } +") + +# if these are set then do not try to find them again, +# by avoiding any try_compiles for the flags +if((DEFINED SSE2_C_FLAGS) OR (DEFINED HAVE_SSE2)) +else() + if(WIN32) + set(SSE2_C_FLAG_CANDIDATES + #Empty, if compiler automatically accepts SSE2 + " " + "/arch:SSE2") + else() + set(SSE2_C_FLAG_CANDIDATES + #Empty, if compiler automatically accepts SSE2 + " " + #clang + "-msse2" + #GNU, Intel + "-march=core2" + ) + endif() + + include(CheckCSourceCompiles) + + foreach(FLAG IN LISTS SSE2_C_FLAG_CANDIDATES) + set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + set(CMAKE_REQUIRED_FLAGS "${FLAG}") + unset(HAVE_SSE2 CACHE) + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Try SSE2 C flag = [${FLAG}]") + endif() + check_c_source_compiles("${SSE2_C_TEST_SOURCE}" HAVE_SSE2) + set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") + if(HAVE_SSE2) + set(SSE2_C_FLAGS_INTERNAL "${FLAG}") + break() + endif() + endforeach() + + unset(SSE2_C_FLAG_CANDIDATES) + + set(SSE2_C_FLAGS "${SSE2_C_FLAGS_INTERNAL}" + CACHE STRING "C compiler flags for SSE2 intrinsics") +endif() + +list(APPEND _SSE2_REQUIRED_VARS SSE2_C_FLAGS) + +set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE}) + +if(_SSE2_REQUIRED_VARS) + include(FindPackageHandleStandardArgs) + + find_package_handle_standard_args(SSE2 + REQUIRED_VARS ${_SSE2_REQUIRED_VARS}) + + mark_as_advanced(${_SSE2_REQUIRED_VARS}) + + unset(_SSE2_REQUIRED_VARS) +else() + message(SEND_ERROR "FindSSE2 requires C or CXX language to be enabled") +endif() diff --git a/src/scripts/cmake/FindSSE4.cmake b/src/scripts/cmake/FindSSE4.cmake new file mode 100644 index 0000000..918580f --- /dev/null +++ b/src/scripts/cmake/FindSSE4.cmake @@ -0,0 +1,101 @@ +#.rst: +# FindSSE4 +# -------- +# +# Finds SSE4 support +# +# This module can be used to detect SSE4 support in a C compiler. If +# the compiler supports SSE4, the flags required to compile with +# SSE4 support are returned in variables for the different languages. +# The variables may be empty if the compiler does not need a special +# flag to support SSE4. +# +# The following variables are set: +# +# :: +# +# SSE4_C_FLAGS - flags to add to the C compiler for SSE4 support +# SSE4_FOUND - true if SSE4 is detected +# +#============================================================================= + +set(_SSE4_REQUIRED_VARS) +set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) +set(CMAKE_REQUIRED_QUIET ${SSE4_FIND_QUIETLY}) + +# sample SSE4 source code to test +set(SSE4_C_TEST_SOURCE +" +#if defined(_MSC_VER) +#include +#else +#include +#endif +int foo() { + __m128i vOne = _mm_set1_epi8(1); + __m128i result = _mm_cvtepi8_epi16(vOne); + return _mm_extract_epi16(result, 0); +} +int main(void) { return foo(); } +") + +# if these are set then do not try to find them again, +# by avoiding any try_compiles for the flags +if((DEFINED SSE4_C_FLAGS) OR (DEFINED HAVE_SSE4)) +else() + if(WIN32) + set(SSE4_C_FLAG_CANDIDATES + #Empty, if compiler automatically accepts SSE4 + " " + "/arch:SSE4") + else() + set(SSE4_C_FLAG_CANDIDATES + #Empty, if compiler automatically accepts SSE4 + " " + #clang + "-msse4.1" + #GNU, Intel + "-msse4" + "-march=corei7" + ) + endif() + + include(CheckCSourceCompiles) + + foreach(FLAG IN LISTS SSE4_C_FLAG_CANDIDATES) + set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + set(CMAKE_REQUIRED_FLAGS "${FLAG}") + unset(HAVE_SSE4 CACHE) + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Try SSE4 C flag = [${FLAG}]") + endif() + check_c_source_compiles("${SSE4_C_TEST_SOURCE}" HAVE_SSE4) + set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") + if(HAVE_SSE4) + set(SSE4_C_FLAGS_INTERNAL "${FLAG}") + break() + endif() + endforeach() + + unset(SSE4_C_FLAG_CANDIDATES) + + set(SSE4_C_FLAGS "${SSE4_C_FLAGS_INTERNAL}" + CACHE STRING "C compiler flags for SSE4 intrinsics") +endif() + +list(APPEND _SSE4_REQUIRED_VARS SSE4_C_FLAGS) + +set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE}) + +if(_SSE4_REQUIRED_VARS) + include(FindPackageHandleStandardArgs) + + find_package_handle_standard_args(SSE4 + REQUIRED_VARS ${_SSE4_REQUIRED_VARS}) + + mark_as_advanced(${_SSE4_REQUIRED_VARS}) + + unset(_SSE4_REQUIRED_VARS) +else() + message(SEND_ERROR "FindSSE4 requires C or CXX language to be enabled") +endif() From bfeafbea2aec6135571d799025b57532bd313b0e Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Wed, 6 Nov 2024 00:11:49 +0100 Subject: [PATCH 08/13] Update `test.yml` Actions workflow to build package with new build system --- .github/workflows/requirements.txt | 10 ++-- .github/workflows/test.yml | 91 +++++++++++++++++------------- 2 files changed, 57 insertions(+), 44 deletions(-) diff --git a/.github/workflows/requirements.txt b/.github/workflows/requirements.txt index 1fa9e50..e80af86 100644 --- a/.github/workflows/requirements.txt +++ b/.github/workflows/requirements.txt @@ -1,8 +1,6 @@ -coverage ~=6.0 ; sys_platform != 'win32' +# coverage ~=7.0 cython ~=3.0 -semantic-version ~=2.10 -wheel -auditwheel -setuptools >=46.4.0 +# semantic-version ~=2.10 +scikit-build-core importlib-resources ; python_version < '3.9' -scoring-matrices ~=0.2.0 +scoring-matrices ~=0.3.0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f3ac5c8..3008636 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ jobs: test_linux: name: Test (Linux) - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 env: OS: Linux strategy: @@ -27,12 +27,15 @@ jobs: - python-version: '3.10' python-release: v3.10 python-impl: CPython - - python-version: '3.11' + - python-version: 3.11 python-release: v3.11 python-impl: CPython - - python-version: '3.12' + - python-version: 3.12 python-release: v3.12 python-impl: CPython + - python-version: 3.13 + python-release: v3.13 + python-impl: CPython - python-version: pypy-3.7 python-release: v3.7 python-impl: PyPy @@ -54,26 +57,26 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - name: Install CI requirements + - name: Update pip + run: python -m pip install -U pip wheel setuptools + - name: Install Python requirements run: python -m pip install -r .github/workflows/requirements.txt - - name: Install test requirements - run: python -m pip install -r pyfamsa/tests/requirements.txt - - name: Build C extension in debug mode - run: python setup.py build_ext --inplace --debug - - name: Test with coverage - run: python -m coverage run -m unittest discover -vv - - name: Upload to Codecov - if: matrix.python-impl == 'CPython' - uses: codecov/codecov-action@v4 - with: - flags: ${{ matrix.python-impl }},${{ matrix.python-release }},${{ env.OS }} - name: test-python-${{ matrix.python-version }} - fail_ci_if_error: false - token: ${{ secrets.CODECOV_TOKEN }} + - name: Build extension in debug mode + run: python -m pip install -v -e . --no-build-isolation + - name: Test extension + run: python -m unittest pyfamsa.tests -vv + # - name: Upload to Codecov + # if: matrix.python-impl == 'CPython' + # uses: codecov/codecov-action@v3 + # with: + # flags: ${{ matrix.python-impl }},${{ matrix.python-release }},${{ env.OS }} + # name: test-python-${{ matrix.python-version }} + # fail_ci_if_error: true + # token: ${{ secrets.CODECOV_TOKEN }} test_osx: name: Test (OSX) - runs-on: macos-12 + runs-on: macos-13 env: OS: OSX strategy: @@ -98,6 +101,9 @@ jobs: - python-version: '3.12' python-release: v3.12 python-impl: CPython + - python-version: '3.13' + python-release: v3.13 + python-impl: CPython - python-version: pypy-3.7 python-release: v3.7 python-impl: PyPy @@ -119,22 +125,26 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - name: Install CI requirements + - name: Setup deployment target + shell: bash + if: ${{ startsWith(matrix.python-version, 'pypy') || matrix.python-version == '3.11' || matrix.python-version == '3.12' }} + run: echo "MACOSX_DEPLOYMENT_TARGET=10.12" >> $GITHUB_ENV + - name: Update pip + run: python -m pip install -U pip wheel setuptools + - name: Install Python requirements run: python -m pip install -r .github/workflows/requirements.txt - - name: Install test requirements - run: python -m pip install -r pyfamsa/tests/requirements.txt - - name: Build C extension in debug mode - run: python setup.py build_ext --inplace --debug - - name: Test with coverage - run: python -m coverage run -m unittest discover -vv - - name: Upload to Codecov - if: matrix.python-impl == 'CPython' - uses: codecov/codecov-action@v4 - with: - flags: ${{ matrix.python-impl }},${{ matrix.python-release }},${{ env.OS }} - name: test-python-${{ matrix.python-version }} - fail_ci_if_error: false - token: ${{ secrets.CODECOV_TOKEN }} + - name: Build extension in debug mode + run: python -m pip install -v -e . --no-build-isolation + - name: Test extension + run: python -m unittest pyfamsa.tests -vv + # - name: Upload to Codecov + # if: matrix.python-impl == 'CPython' + # uses: codecov/codecov-action@v3 + # with: + # flags: ${{ matrix.python-impl }},${{ matrix.python-release }},${{ env.OS }} + # name: test-python-${{ matrix.python-version }} + # fail_ci_if_error: true + # token: ${{ secrets.CODECOV_TOKEN }} test_windows: name: Test (Windows) @@ -163,6 +173,9 @@ jobs: - python-version: '3.12' python-release: v3.12 python-impl: CPython + - python-version: '3.13' + python-release: v3.13 + python-impl: CPython - python-version: pypy-3.7 python-release: v3.7 python-impl: PyPy @@ -185,9 +198,11 @@ jobs: with: python-version: ${{ matrix.python-version }} architecture: x64 + - name: Update pip + run: python -m pip install -U pip wheel setuptools - name: Install Python requirements run: python -m pip install -r .github/workflows/requirements.txt - - name: Build C extension - run: python setup.py build_ext --inplace - - name: Test without coverage - run: python -m unittest discover -vv + - name: Build extension in debug mode + run: python -m pip install -v . --no-build-isolation + - name: Test extension + run: python -m unittest pyfamsa.tests -vv From 290d8a72ba2161c90652980c9b4c45ac30ad00ef Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Wed, 6 Nov 2024 00:12:29 +0100 Subject: [PATCH 09/13] Remove unused build dependencies from `pyproject.toml` --- pyproject.toml | 6 ++---- src/scripts/cmake/CythonExtension.cmake | 7 ------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 40b55c5..fd89a3e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,10 @@ [build-system] -requires = ['scikit-build-core', 'cython ~=3.0', 'scoring-matrices ~=0.3.0', 'semantic-version ~=2.10'] +requires = ['scikit-build-core', 'cython ~=3.0', 'scoring-matrices ~=0.3.0'] build-backend = "scikit_build_core.build" [project] name = "pyfamsa" -version = "0.6.0" - - +version = "0.5.2" [tool.scikit-build] build-dir = "build/{build_type}" diff --git a/src/scripts/cmake/CythonExtension.cmake b/src/scripts/cmake/CythonExtension.cmake index ce0ee70..2ea8922 100644 --- a/src/scripts/cmake/CythonExtension.cmake +++ b/src/scripts/cmake/CythonExtension.cmake @@ -66,13 +66,6 @@ execute_process( OUTPUT_VARIABLE SCORING_MATRICES_PATH ) -# --- Detect `pyopal` folder --------------------------------------------------- - -execute_process( - COMMAND ${Python_EXECUTABLE} -c "import os; import pyopal; print(os.path.dirname(pyopal.__path__[0]), end='')" - OUTPUT_VARIABLE PYOPAL_PATH -) - # --- Declare Cython extension ------------------------------------------------- macro(cython_extension _name) From 16612fc247069e848f0aaacdeb25bc695d7e2aeb Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Wed, 6 Nov 2024 00:52:48 +0100 Subject: [PATCH 10/13] Fix some additional compile options for the FAMSA code --- CMakeLists.txt | 23 ++++++- src/FAMSA/CMakeLists.txt | 4 ++ src/scripts/cmake/FindAVX1.cmake | 103 +++++++++++++++++++++++++++++ src/scripts/cmake/FindPOPCNT.cmake | 92 ++++++++++++++++++++++++++ 4 files changed, 219 insertions(+), 3 deletions(-) create mode 100644 src/scripts/cmake/FindAVX1.cmake create mode 100644 src/scripts/cmake/FindPOPCNT.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 737212c..727197a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,22 +3,39 @@ project(${SKBUILD_PROJECT_NAME} VERSION ${SKBUILD_PROJECT_VERSION} LANGUAGES C C set(BUILD_SHARED_LIBS OFF) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CMAKE_CXX_STANDARD 20) -set_property(GLOBAL PROPERTY PYTHON_EXTENSIONS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED TRUE) message(STATUS "Building ${SKBUILD_PROJECT_NAME} for ${CMAKE_SYSTEM_PROCESSOR}") # --- Setup include folders ---------------------------------------------------- +set_property(GLOBAL PROPERTY PYTHON_EXTENSIONS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) set(CYTHON_HEADERS_DIR ${CMAKE_CURRENT_LIST_DIR}/include) +# --- Add global C++ flags ----------------------------------------------------- + +include(CheckCXXCompilerFlag) + +check_cxx_compiler_flag(-funroll-loops HAVE_UNROLL_LOOPS) +if(HAVE_UNROLL_LOOPS) + add_compile_options(-funroll-loops) +endif() + +add_definitions(-DOLD_ATOMIC_FLAG -DNO_PROFILE_PAR) + +if(WIN32) + add_definitions(-D_WIN32) +endif() + # --- Add scripts for Cython --------------------------------------------------- -# include("src/scripts/cmake/FindAVX1.cmake") +include("src/scripts/cmake/FindAVX1.cmake") include("src/scripts/cmake/FindAVX2.cmake") # include("src/scripts/cmake/FindAVX512.cmake") include("src/scripts/cmake/FindNEON.cmake") +include("src/scripts/cmake/FindPOPCNT.cmake") include("src/scripts/cmake/FindSSE2.cmake") include("src/scripts/cmake/FindSSE4.cmake") include("src/scripts/cmake/CythonExtension.cmake") diff --git a/src/FAMSA/CMakeLists.txt b/src/FAMSA/CMakeLists.txt index 8f6f9e9..6f2d5a2 100644 --- a/src/FAMSA/CMakeLists.txt +++ b/src/FAMSA/CMakeLists.txt @@ -161,6 +161,10 @@ else() target_compile_definitions(famsa_lcs PRIVATE -DSIMD=0) endif() +if(HAVE_POPCNT) + target_compile_options(famsa_lcs PRIVATE ${POPCNT_C_FLAGS}) +endif() + target_link_libraries(famsa PUBLIC famsa_lcs) diff --git a/src/scripts/cmake/FindAVX1.cmake b/src/scripts/cmake/FindAVX1.cmake new file mode 100644 index 0000000..f8ff626 --- /dev/null +++ b/src/scripts/cmake/FindAVX1.cmake @@ -0,0 +1,103 @@ +#.rst: +# FindAVX1 +# -------- +# +# Finds AVX1 support +# +# This module can be used to detect AVX1 support in a C compiler. If +# the compiler supports AVX1, the flags required to compile with +# AVX1 support are returned in variables for the different languages. +# The variables may be empty if the compiler does not need a special +# flag to support AVX1. +# +# The following variables are set: +# +# :: +# +# AVX1_C_FLAGS - flags to add to the C compiler for AVX1 support +# AVX1_FOUND - true if AVX1 is detected +# +#============================================================================= + +set(_AVX1_REQUIRED_VARS) +set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) +set(CMAKE_REQUIRED_QUIET ${AVX1_FIND_QUIETLY}) + +# sample AVX1 source code to test +set(AVX1_C_TEST_SOURCE +" +#include +void parasail_memset___m256i(__m256i *b, __m256i c, size_t len) +{ + size_t i; + for (i=0; i +int foo(long long int a) +{ + return _popcnt64(a); +} +int main(void) { return (int)foo(0); } +") + +# if these are set then do not try to find them again, +# by avoiding any try_compiles for the flags +if((DEFINED POPCNT_C_FLAGS) OR (DEFINED HAVE_POPCNT)) +else() + if(WIN32) + # MSVC can compile AVX intrinsics without the arch flag, however it + # will detect that AVX code is found and "consider using /arch:AVX". + set(POPCNT_C_FLAG_CANDIDATES + "/arch:SSE4.2" + ) + else() + set(POPCNT_C_FLAG_CANDIDATES + #clang,GNU,Intel + "-mpopcnt" + ) + endif() + + include(CheckCSourceCompiles) + + foreach(FLAG IN LISTS POPCNT_C_FLAG_CANDIDATES) + set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + set(CMAKE_REQUIRED_FLAGS "${FLAG}") + unset(HAVE_POPCNT CACHE) + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Try POPCNT C flag = [${FLAG}]") + endif() + check_c_source_compiles("${POPCNT_C_TEST_SOURCE}" HAVE_POPCNT) + set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") + if(HAVE_POPCNT) + set(POPCNT_C_FLAGS_INTERNAL "${FLAG}") + break() + endif() + endforeach() + + unset(POPCNT_C_FLAG_CANDIDATES) + + set(POPCNT_C_FLAGS "${POPCNT_C_FLAGS_INTERNAL}" + CACHE STRING "C compiler flags for POPCNT intrinsics") +endif() + +list(APPEND _POPCNT_REQUIRED_VARS POPCNT_C_FLAGS) + +set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE}) + +if(_POPCNT_REQUIRED_VARS) + include(FindPackageHandleStandardArgs) + + find_package_handle_standard_args(POPCNT + REQUIRED_VARS ${_POPCNT_REQUIRED_VARS}) + + mark_as_advanced(${_POPCNT_REQUIRED_VARS}) + + unset(_POPCNT_REQUIRED_VARS) +else() + message(SEND_ERROR "FindPOPCNT requires C or CXX language to be enabled") +endif() From 66df923954bc6e8d1eab68b9b8b0a05e3ba3520c Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Wed, 6 Nov 2024 01:05:43 +0100 Subject: [PATCH 11/13] Add project metadata to `pyproject.toml` --- pyproject.toml | 100 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fd89a3e..98de064 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,8 +5,106 @@ build-backend = "scikit_build_core.build" [project] name = "pyfamsa" version = "0.5.2" +description = "Cython bindings and Python interface to FAMSA, an algorithm for ultra-scale multiple sequence alignments." +readme = "README.md" +requires-python = ">=3.7" +license = { file = "COPYING" } +authors = [ + { name = "Martin Larralde", email = "martin.larralde@embl.de" }, +] +platform = "any" +keywords = ["bioinformatics", "sequence", "alignment", "protein", "MSA"] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Operating System :: OS Independent", + "Programming Language :: C++", + "Programming Language :: Cython", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Topic :: Scientific/Engineering :: Bio-Informatics", + "Topic :: Scientific/Engineering :: Medical Science Apps.", + "Typing :: Typed", +] +dependencies = [ + "scoring-matrices ~=0.3.0", +] + +[project.urls] +"Homepage" = "https://github.com/althonos/pyfamsa/" +"Documentation" = "https://pyfamsa.readthedocs.io/en/stable/" +"Bug Tracker" = "https://github.com/althonos/pyfamsa/issues" +"Changelog" = "https://github.com/althonos/pyfamsa/blob/master/CHANGELOG.md" +"Coverage" = "https://codecov.io/gh/althonos/pyfamsa/" +"Builds" = "https://github.com/althonos/pyfamsa/actions" +"PyPI" = "https://pypi.org/project/pyfamsa" + +[project.optional-dependencies] +test = ["importlib-resources ; python_version < '3.9'"] [tool.scikit-build] build-dir = "build/{build_type}" editable.rebuild = true -editable.verbose = false \ No newline at end of file +editable.verbose = false + +[[tool.scikit-build.overrides]] +if.state = "editable" +cmake.build-type = "Debug" + +[[tool.scikit-build-overrides]] +if.env.SCCACHE = true +cmake.define.CMAKE_C_COMPILER_LAUNCHER = "sccache" +cmake.define.CMAKE_CXX_COMPILER_LAUNCHER = "sccache" + +[[tool.scikit-build-overrides]] +if.env.MOLD = true +cmake.define.CMAKE_LINKER_TYPE = "mold" + +[tool.cibuildwheel] +before-build = "pip install scikit-build-core cython scoring-matrices" +build-frontend = { name = "pip", args = ["--no-build-isolation"] } +build-verbosity = 1 +free-threaded-support = false +test-command = "python -m unittest pyfamsa.tests -v" +test-extras = ["test"] + +[tool.coverage.run] +plugins = ["Cython.Coverage"] + +[tool.coverage.report] +include = ["src/pyfamsa/*"] +omit = ["src/pyfamsa/tests/*"] +show_missing = true +exclude_lines = [ + "pragma: no cover", + "if typing.TYPE_CHECKING:", + "@abc.abstractmethod", + "@abc.abstractproperty", + "raise NotImplementedError", + "return NotImplemented", + "raise UnexpectedError", + "raise AllocationError", +] + +[tool.mypy] +disallow_any_decorated = true +disallow_any_generics = true +disallow_any_unimported = false +disallow_subclassing_any = false +disallow_untyped_calls = true +disallow_untyped_defs = true +ignore_missing_imports = true +warn_unused_ignores = true +warn_return_any = true + +["tool.mypy-pyfamsa.tests"] +ignore_errors = true \ No newline at end of file From f8b944ffc3da5a42ca5c4e5d611b7d77f87840e5 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Wed, 6 Nov 2024 01:05:56 +0100 Subject: [PATCH 12/13] Remove outdated `setuptools` configuration files --- MANIFEST.in | 16 - setup.cfg | 109 ------- setup.py | 901 ---------------------------------------------------- 3 files changed, 1026 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 2ed81e4..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,16 +0,0 @@ -include COPYING -include CHANGELOG.md -include CONTRIBUTING.md -include README.md - -recursive-include include *.pxd -recursive-include patches *.patch -recursive-include pyfamsa/tests *.py requirements.txt -recursive-include pyfamsa/tests/data * - -recursive-include vendor/FAMSA README.md LICENSE makefile -recursive-include vendor/FAMSA/src *.cpp *.h *.hpp -recursive-include vendor/FAMSA/libs * - -recursive-include pyfamsa *.py *.pyi *.pyx *.pxd *.h py.typed -recursive-exclude pyfamsa *.cpp *.html diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index f20b5dd..0000000 --- a/setup.cfg +++ /dev/null @@ -1,109 +0,0 @@ -[metadata] -name = pyfamsa -version = attr: pyfamsa._version.__version__ -author = Martin Larralde -author_email = martin.larralde@embl.de -url = https://github.com/althonos/pyfamsa -description = Cython bindings and Python interface to FAMSA, an algorithm for ultra-scale multiple sequence alignments. -long_description = file: README.md -long_description_content_type = text/markdown -license = GPL-3.0-only -platform = any -keywords = bioinformatics, sequence, alignment, protein, MSA -classifier = - Development Status :: 3 - Alpha - Intended Audience :: Developers - Intended Audience :: Science/Research - License :: OSI Approved :: GNU General Public License v3 (GPLv3) - Operating System :: OS Independent - Programming Language :: C - Programming Language :: Cython - 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 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: 3.12 - Programming Language :: Python :: Implementation :: CPython - Programming Language :: Python :: Implementation :: PyPy - Topic :: Scientific/Engineering :: Bio-Informatics - Topic :: Scientific/Engineering :: Medical Science Apps. - Typing :: Typed -project_urls = - Documentation = https://pyfamsa.readthedocs.io/en/stable/ - Bug Tracker = https://github.com/althonos/pyfamsa/issues - Changelog = https://github.com/althonos/pyfamsa/blob/main/CHANGELOG.md - Coverage = https://codecov.io/gh/althonos/pyfamsa/ - Builds = https://github.com/althonos/pyfamsa/actions - PyPI = https://pypi.org/project/pyfamsa - -[options] -zip_safe = false -packages = pyfamsa, pyfamsa.tests, pyfamsa.tests.data -include_package_data = false -python_requires = >=3.6 -setup_requires = - setuptools >=46.4 - cython ~=3.0 - scoring-matrices ~=0.2.0 - semantic-version ~=2.10 -install_requires = - scoring-matrices ~=0.2.0 -tests_require = - importlib-resources ; python_version < '3.9' - -# [options.entry_points] -# console_scripts = -# pyfamsa = pyfamsa.cli:main - -[options.package_data] -pyfamsa = py.typed, *.pyi -pyfamsa.tests = requirements.txt -pyfamsa.tests.data = * - -[coverage:run] -plugins = Cython.Coverage - -[coverage:report] -include = pyfamsa/* -omit = pyfamsa/tests/* -show_missing = true -exclude_lines = - pragma: no cover - if typing.TYPE_CHECKING: - @abc.abstractmethod - @abc.abstractproperty - raise NotImplementedError - return NotImplemented - raise MemoryError() - -[pydocstyle] -inherit = false -ignore = D102,D105,D200,D203,D213,D406,D407 -match-dir = (?!tests)(?!docs)[^\.].* -match = (?!test)(?!setup)[^\._].*\.py - -[mypy] -disallow_any_decorated = true -disallow_any_generics = true -disallow_any_unimported = false -disallow_subclassing_any = false -disallow_untyped_calls = true -disallow_untyped_defs = true -ignore_missing_imports = true -warn_unused_ignores = true -warn_return_any = true -exclude = pyfamsa/tests/* - -[mypy-pyfamsa.tests] -disallow_untyped_defs = false - -[isort] -known_first_party = pyfamsa, famsa -known_standard_library = cpython, cython, _unicode -known_third_party = libc, libcpp -line_length = 88 -profile = black -skip_gitignore = true -skip_glob = vendor/FAMSA/* diff --git a/setup.py b/setup.py deleted file mode 100644 index ba91ab7..0000000 --- a/setup.py +++ /dev/null @@ -1,901 +0,0 @@ -#!/usr/bin/env python3 - -import configparser -import functools -import glob -import itertools -import io -import multiprocessing.pool -import os -import platform -import re -import setuptools -import setuptools.extension -import subprocess -import sys -import sysconfig -from distutils.command.clean import clean as _clean -from distutils.errors import CompileError -from setuptools.extension import Extension -from setuptools.command.build_clib import build_clib as _build_clib -from setuptools.command.build_ext import build_ext as _build_ext -from setuptools.command.sdist import sdist as _sdist - -try: - from Cython.Build import cythonize -except ImportError as err: - cythonize = err - -try: - import semantic_version -except ImportError as err: - semantic_version = err - -# --- Constants ----------------------------------------------------------------- - -SETUP_FOLDER = os.path.relpath(os.path.realpath(os.path.join(__file__, os.pardir))) -FAMSA_FOLDER = os.path.join(SETUP_FOLDER, "vendor", "FAMSA") - -def _detect_target_machine(platform): - if platform == "win32": - return "x86" - return platform.rsplit("-", 1)[-1] - -def _detect_target_cpu(platform): - machine = _detect_target_machine(platform) - if re.match("^mips", machine): - return "mips" - elif re.match("^(aarch64|arm64)$", machine): - return "aarch64" - elif re.match("^arm", machine): - return "arm" - elif re.match("(x86_64)|(x86)|(AMD64|amd64)|(^i.86$)", machine): - return "x86" - elif re.match("^(powerpc|ppc)", machine): - return "ppc" - return None - -def _detect_target_system(platform): - if platform.startswith("win"): - return "windows" - elif platform.startswith("macosx"): - return "macos" - elif platform.startswith("linux"): - return "linux_or_android" - elif platform.startswith("freebsd"): - return "freebsd" - return None - - -# --- Utils ------------------------------------------------------------------ - -_HEADER_PATTERN = re.compile(r"^@@ -(\d+),?(\d+)? \+(\d+),?(\d+)? @@") - - -def _eprint(*args, **kwargs): - print(*args, **kwargs, file=sys.stderr) - - -def _patch_osx_compiler(compiler, machine): - # On newer OSX, Python has been compiled as a universal binary, so - # it will attempt to pass universal binary flags when building the - # extension. This will not work because the code makes use of CPU - # specific SIMD extensions. - for tool in ("compiler", "compiler_so", "linker_so"): - flags = getattr(compiler, tool) - i = next((i for i in range(1, len(flags)) if flags[i-1] == "-arch" and flags[i] != machine), None) - if i is not None: - flags.pop(i) - flags.pop(i-1) - if "-fPIC" not in flags: - flags.append("-fPIC") - while "-O3" in flags: - i = flags.index("-O3") - flags[i] = "-O2" - - -def _apply_patch(s,patch,revert=False): - # see https://stackoverflow.com/a/40967337 - s = s.splitlines(keepends=True) - p = patch.splitlines(keepends=True) - t = [] - i = 0 - sl = 0 - midx, sign = (1,'+') if not revert else (3,'-') - while i < len(p) and not p[i].startswith("@@"): - i += 1 # skip header lines - - while i < len(p): - match = _HEADER_PATTERN.match(p[i]) - if not match: - raise ValueError("Invalid line in patch: {!r}".format(p[i])) - i += 1 - l = int(match.group(midx)) - 1 + (match.group(midx+1) == '0') - t.extend(s[sl:l]) - sl = l - while i < len(p) and p[i][0] != '@': - if i+1 < len(p) and p[i+1][0] == '\\': - line = p[i][:-1] - i += 2 - else: - line = p[i] - i += 1 - if len(line) > 0: - if line[0] == sign or line[0] == ' ': - t += line[1:] - sl += (line[0] != sign) - - t.extend(s[sl:]) - return ''.join(t) - - -def _is_compiler_clang(compiler): - try: - if compiler.compiler_type == "unix": - proc = subprocess.run([compiler.compiler[0], "--version"], capture_output=True) - if proc.returncode == 0: - return any( - line.startswith(b"Apple clang") - for line in proc.stdout.splitlines() - ) - except: - pass - return False - - -def _detect_compiler_version(compiler): - try: - if compiler.compiler_type == "unix": - proc = subprocess.run([compiler.compiler[0], "-dumpversion"], capture_output=True) - if proc.returncode == 0: - return semantic_version.Version(proc.stdout.decode()) - except: - pass - return semantic_version.Version("5.0.0") # assume lowest compatibility - - -def _set_cpp_flags(compiler, extension): - # see `vendor/FAMSA/makefile` - cc_version = _detect_compiler_version(compiler) - - # check we are not using the buggy clang version - if _is_compiler_clang(compiler) and cc_version.major == 13 and cc_version.minor == 0: - raise RuntimeError( - "clang 13.0 is known to produce undefined behaviour " - "(see https://github.com/refresh-bio/FAMSA/issues/32), " - "please update or use a different compiler." - ) - - if cc_version.major <= 6: - cpp_target = "11" - defines = [("NO_PROFILE_PAR", 1), ("OLD_ATOMIC_FLAG", 1)] - elif cc_version.major == 7: - cpp_target = "14" - defines = [("NO_PROFILE_PAR", 1), ("OLD_ATOMIC_FLAG", 1)] - elif cc_version.major <= 10: - cpp_target = "2a" - defines = [("OLD_ATOMIC_FLAG", 1)] - else: - cpp_target = "20" - defines = [] - - extension.define_macros.extend(defines) - if compiler.compiler_type in {"unix", "cygwin", "mingw32"}: - if extension.language == "c++": - extension.extra_compile_args.append("-std=c++{}".format(cpp_target)) - extension.extra_compile_args.append("-pthread") - extension.extra_compile_args.append("-fPIC") - extension.extra_compile_args.append("-Wno-alloc-size-larger-than") - extension.extra_compile_args.append("-Wno-char-subscripts") - extension.extra_link_args.append("-pthread") - extension.extra_link_args.append("-fPIC") - elif compiler.compiler_type == "msvc": - if extension.language == "c++": - extension.extra_compile_args.append("/std:c{}".format(cpp_target)) - - -def _set_debug_flags(compiler, extension): - if compiler.compiler_type in {"unix", "cygwin", "mingw32"}: - extension.extra_compile_args.append("-g") - elif compiler.compiler_type == "msvc": - extension.extra_compile_args.append("/Z7") - - -# --- Extension with SIMD support -------------------------------------------- - -class Library(setuptools.extension.Library): - - def __init__(self, *args, **kwargs): - self._needs_stub = False - self.platform_sources = kwargs.pop("platform_sources", {}) - super().__init__(*args, **kwargs) - - -# --- Commands ------------------------------------------------------------------ - -class sdist(_sdist): - """A `sdist` that generates a `pyproject.toml` on the fly. - """ - - def run(self): - # build `pyproject.toml` from `setup.cfg` - c = configparser.ConfigParser() - c.add_section("build-system") - c.set("build-system", "requires", str(self.distribution.setup_requires)) - c.set("build-system", 'build-backend', '"setuptools.build_meta"') - with open("pyproject.toml", "w") as pyproject: - c.write(pyproject) - # run the rest of the packaging - _sdist.run(self) - - -class build_ext(_build_ext): - """A `build_ext` that disables optimizations if compiled in debug mode. - """ - - # --- Compatibility with `setuptools.Command` - - user_options = _build_ext.user_options + [ - ("disable-avx", None, "Force compiling the extension without AVX instructions"), - ("disable-avx2", None, "Force compiling the extension without AVX2 instructions"), - ("disable-neon", None, "Force compiling the extension without NEON instructions"), - ] - - def initialize_options(self): - _build_ext.initialize_options(self) - self.disable_avx = False - self.disable_avx2 = False - self.disable_neon = False - self.plat_name = sysconfig.get_platform() - - def finalize_options(self): - _build_ext.finalize_options(self) - # detect platform options - self.target_machine = _detect_target_machine(self.plat_name) - self.target_system = _detect_target_system(self.plat_name) - self.target_cpu = _detect_target_cpu(self.plat_name) - # force-disable AVX2 on MacOS (no OS support for runtime detection) - if self.target_system == "macos": - self.disable_avx2 = True - # transfer arguments to the build_clib method - self._clib_cmd = self.get_finalized_command("build_clib") - self._clib_cmd.debug = self.debug - self._clib_cmd.force = self.force - self._clib_cmd.verbose = self.verbose - self._clib_cmd.define = self.define - self._clib_cmd.include_dirs = self.include_dirs - self._clib_cmd.compiler = self.compiler - self._clib_cmd.parallel = self.parallel - self._clib_cmd.disable_avx = self.disable_avx - self._clib_cmd.disable_avx2 = self.disable_avx2 - self._clib_cmd.disable_neon = self.disable_neon - self._clib_cmd.plat_name = self.plat_name - self._clib_cmd.target_machine = self.target_machine - self._clib_cmd.target_system = self.target_system - self._clib_cmd.target_cpu = self.target_cpu - - # --- Autotools-like helpers --- - - def _check_getid(self): - _eprint('checking whether `PyInterpreterState_GetID` is available') - - base = "have_getid" - testfile = os.path.join(self.build_temp, "{}.c".format(base)) - objects = [] - - self.mkpath(self.build_temp) - with open(testfile, "w") as f: - f.write(""" - #include - #include - #include - - int main(int argc, char *argv[]) {{ - PyInterpreterState_GetID(NULL); - return 0; - }} - """) - - if self.compiler.compiler_type == "msvc": - flags = ["/WX"] - else: - flags = ["-Werror=implicit-function-declaration"] - - try: - self.mkpath(self.build_temp) - objects = self.compiler.compile([testfile], extra_postargs=flags) - except CompileError: - _eprint("no") - return False - else: - _eprint("yes") - return True - finally: - os.remove(testfile) - for obj in filter(os.path.isfile, objects): - os.remove(obj) - - # --- Build code --- - - def build_extension(self, ext): - # show the compiler being used - _eprint("building", ext.name, "with", self.compiler.compiler_type, "compiler") - - # add debug symbols if we are building in debug mode - if self.debug: - _set_debug_flags(self.compiler, ext) - if sys.implementation.name == "cpython": - ext.define_macros.append(("CYTHON_TRACE_NOGIL", 1)) - else: - ext.define_macros.append(("CYTHON_WITHOUT_ASSERTIONS", 1)) - - # add C++11 flags - _set_cpp_flags(self.compiler, ext) - - # add Windows flags - if self.target_system == "windows" and self.compiler.compiler_type == "msvc": - ext.define_macros.append(("WIN32", 1)) - - # update link and include directories - for name in ext.libraries: - lib = self._clib_cmd.get_library(name) - if lib is not None: - libfile = self.compiler.library_filename( - lib.name, output_dir=self._clib_cmd.build_clib - ) - ext.depends.append(libfile) - ext.extra_objects.append(libfile) - ext.extra_objects.extend(lib.extra_objects) - ext.define_macros.extend(lib.define_macros) - - # make sure `PyInterpreterState_GetID` is available - if self._check_getid(): - ext.define_macros.append(("HAS_PYINTERPRETERSTATE_GETID", 1)) - - # build the rest of the extension as normal - ext._needs_stub = False - _build_ext.build_extension(self, ext) - - def build_extensions(self): - # check `cythonize` is available - if isinstance(cythonize, ImportError): - raise RuntimeError("Cython is required to run `build_ext` command") from cythonize - - # remove universal compilation flags for OSX - if self.target_system == "Darwin": - _patch_osx_compiler(self.compiler, self.target_machine) - - # use debug directives with Cython if building in debug mode - cython_args = { - "include_path": ["include"], - "compiler_directives": { - "cdivision": True, - "nonecheck": False, - }, - "compile_time_env": { - "SYS_IMPLEMENTATION_NAME": sys.implementation.name, - "SYS_VERSION_INFO_MAJOR": sys.version_info.major, - "SYS_VERSION_INFO_MINOR": sys.version_info.minor, - "SYS_VERSION_INFO_MICRO": sys.version_info.micro, - "DEFAULT_BUFFER_SIZE": io.DEFAULT_BUFFER_SIZE, - "TARGET_CPU": self.target_cpu, - "TARGET_SYSTEM": self.target_system, - } - } - if self.force: - cython_args["force"] = True - if self.debug: - cython_args["annotate"] = True - cython_args["compiler_directives"]["cdivision_warnings"] = True - cython_args["compiler_directives"]["warn.undeclared"] = True - cython_args["compiler_directives"]["warn.unreachable"] = True - cython_args["compiler_directives"]["warn.maybe_uninitialized"] = True - cython_args["compiler_directives"]["warn.unused"] = True - cython_args["compiler_directives"]["warn.unused_arg"] = True - cython_args["compiler_directives"]["warn.unused_result"] = True - cython_args["compiler_directives"]["warn.multiple_declarators"] = True - else: - cython_args["compiler_directives"]["boundscheck"] = False - cython_args["compiler_directives"]["wraparound"] = False - - # compile the C library - if not self.distribution.have_run.get("build_clib", False): - self._clib_cmd.run() - - # add the include dirs from the `build_clib` command - for ext in self.extensions: - for library in self.distribution.libraries: - ext.include_dirs.extend(library.include_dirs) - - # cythonize the extensions and build normally - self.extensions = cythonize(self.extensions, **cython_args) - _build_ext.build_extensions(self) - - -class build_clib(_build_clib): - """A custom `build_clib` that makes all C++ class attributes public. - """ - - # --- Compatibility with `setuptools.Command` - - user_options = _build_clib.user_options + [ - ("parallel=", "j", "number of parallel build jobs"), - ("disable-avx", None, "Force compiling the library without AVX instructions"), - ("disable-avx2", None, "Force compiling the library without AVX2 instructions"), - ("disable-neon", None, "Force compiling the library without NEON instructions"), - ] - - def initialize_options(self): - _build_clib.initialize_options(self) - self.parallel = None - self.disable_avx = False - self.disable_avx2 = False - self.disable_neon = False - self.plat_name = sysconfig.get_platform() - - def finalize_options(self): - _build_clib.finalize_options(self) - if self.parallel is not None: - self.parallel = int(self.parallel) - # detect platform options - self.target_machine = _detect_target_machine(self.plat_name) - self.target_system = _detect_target_system(self.plat_name) - self.target_cpu = _detect_target_cpu(self.plat_name) - # force-disable AVX2 on MacOS (no OS support for runtime detection) - if self.target_system == "macos": - self.disable_avx2 = True - # record SIMD-specific options - self._simd_supported = dict(AVX=False, AVX2=False, NEON=False) - self._simd_defines = dict(AVX=[], AVX2=[], NEON=[]) - self._simd_flags = dict(AVX=[], AVX2=[], NEON=[]) - self._simd_disabled = { - "AVX": self.disable_avx, - "AVX2": self.disable_avx2, - "NEON": self.disable_neon, - } - - # --- Autotools-like helpers --- - - def _patch_file(self, input, output): - basename = os.path.basename(input) - patchname = os.path.realpath(os.path.join(__file__, os.pardir, "patches", "{}.patch".format(basename))) - _eprint("patching", os.path.relpath(input), "with", os.path.relpath(patchname)) - with open(patchname, "r") as patchfile: - patch = patchfile.read() - with open(input, "r") as src: - srcdata = src.read() - with open(output, "w") as dst: - dst.write(_apply_patch(srcdata, patch)) - - def _check_simd_generic(self, name, flags, header, vector, set, op, extract, result=1): - _eprint('checking whether compiler can build', name, 'code', end="... ") - - base = "have_{}".format(name) - testfile = os.path.join(self.build_temp, "{}.c".format(base)) - binfile = self.compiler.executable_filename(base, output_dir=self.build_temp) - objects = [] - - self.mkpath(self.build_temp) - with open(testfile, "w") as f: - f.write(""" - #include <{}> - int main() {{ - {} a = {}(1); - a = {}(a); - short x = {}(a, 1); - return (x == 1) ? 0 : 1; - }} - """.format(header, vector, set, op, extract)) - - try: - self.mkpath(self.build_temp) - objects = self.compiler.compile([testfile], extra_preargs=flags) - self.compiler.link_executable(objects, base, output_dir=self.build_temp) - subprocess.run([binfile], check=True) - except CompileError: - _eprint("no") - return False - except (subprocess.SubprocessError, OSError): - _eprint("yes, but cannot run code") - return True # assume we are cross-compiling, and still build - else: - if not flags: - _eprint("yes") - else: - _eprint("yes, with {}".format(" ".join(flags))) - return True - finally: - os.remove(testfile) - for obj in filter(os.path.isfile, objects): - os.remove(obj) - if os.path.isfile(binfile): - os.remove(binfile) - - def _avx_flags(self): - if self.compiler.compiler_type == "msvc": - return ["/arch:AVX2"] - return ["-mavx", "-mpopcnt", "-funroll-loops"] - - def _check_avx(self): - return self._check_simd_generic( - "AVX", - self._avx_flags(), - header="immintrin.h", - vector="__m256i", - set="_mm256_set1_epi16", - op="", - extract="_mm256_extract_epi16", - ) - - def _avx2_flags(self): - if self.compiler.compiler_type == "msvc": - return ["/arch:AVX2"] - return ["-mavx2", "-mpopcnt", "-funroll-loops"] - - def _check_avx2(self): - return self._check_simd_generic( - "AVX2", - self._avx2_flags(), - header="immintrin.h", - vector="__m256i", - set="_mm256_set1_epi16", - op="_mm256_abs_epi32", - extract="_mm256_extract_epi16", - ) - - def _neon_flags(self): - return ["-mfpu=neon"] if self.target_cpu == "arm" else [] - - def _check_neon(self): - return self._check_simd_generic( - "NEON", - self._neon_flags(), - header="arm_neon.h", - vector="int16x8_t", - set="vdupq_n_s16", - op="vabsq_s16", - extract="vgetq_lane_s16" - ) - - # --- Compatibility with base `build_clib` command --- - - def check_library_list(self, libraries): - pass - - def get_library_names(self): - return [ lib.name for lib in self.libraries ] - - def get_source_files(self): - return [ source for lib in self.libraries for source in lib.sources ] - - def get_library(self, name): - return next((lib for lib in self.libraries if lib.name == name), None) - - # --- Build code --- - - def build_simd_code(self, library): - # build platform-specific code - for simd, sources in library.platform_sources.items(): - sources = [ - os.path.join(self.build_temp, "FAMSA", os.path.relpath(source, FAMSA_FOLDER)) - for source in sources - ] - if self._simd_supported[simd] and not self._simd_disabled[simd]: - objects = [ - s.replace(".cpp", self.compiler.obj_extension) - for s in sources - ] - for source, object in zip(sources, objects): - self.make_file( - [source], - object, - self.compiler.compile, - ( - [source], - None, - library.define_macros + self._simd_defines[simd], - library.include_dirs, - self.debug, - library.extra_compile_args + self._simd_flags[simd], - None, - library.depends - ) - ) - library.extra_objects.extend(objects) - - def build_libraries(self, libraries): - # check `semantic_version` is available - if isinstance(semantic_version, ImportError): - raise RuntimeError("`semantic_version` is required to run `build_ext` command") from semantic_version - - # check for functions required for libcpu_features on OSX - if self.target_system == "macos": - _patch_osx_compiler(self.compiler, self.target_machine) - - # check if we can build platform-specific code - if self.target_cpu == "x86": - if not self._simd_disabled["AVX"] and self._check_avx(): - self._simd_supported["AVX"] = True - self._simd_flags["AVX"].extend(self._avx_flags()) - if not self._simd_disabled["AVX2"] and self._check_avx2(): - self._simd_supported["AVX2"] = True - self._simd_flags["AVX2"].extend(self._avx2_flags()) - elif self.target_cpu == "arm" or self.target_cpu == "aarch64": - if not self._simd_disabled["NEON"] and self._check_neon(): - self._simd_supported["NEON"] = True - self._simd_flags["NEON"].extend(self._neon_flags()) - if self.target_cpu == "arm": - self._simd_defines["NEON"].append(("__ARM_NEON", 1)) - - # setup dispatcher of SIMD extensions - for library in libraries: - if self._simd_supported["AVX2"]: - library.define_macros.append(("SIMD", 2)) - elif self._simd_supported["AVX"]: - library.define_macros.append(("SIMD", 1)) - elif self._simd_supported["NEON"]: - library.define_macros.append(("SIMD", 4)) - else: - library.define_macros.append(("SIMD", 0)) - - # build each library only if the sources are outdated - self.mkpath(self.build_clib) - for library in libraries: - libname = self.compiler.library_filename(library.name, output_dir=self.build_clib) - # self.make_file(library.sources, libname, self.build_library, (library,)) - self.build_library(library) - - def build_library(self, library): - # show the compiler being used - _eprint("building", library.name, "with", self.compiler.compiler_type, "compiler") - - # add debug flags if we are building in debug mode - if self.debug: - _set_debug_flags(self.compiler, library) - # add C++11 flags - if library.name == "famsa": - _set_cpp_flags(self.compiler, library) - - # add Windows flags - if self.target_system == "windows" and self.compiler.compiler_type == "msvc": - library.define_macros.append(("WIN32", 1)) - - # copy source code to build directory - self.mkpath(os.path.join(self.build_clib, "FAMSA")) - for dirpath, dirnames, filenames in os.walk(FAMSA_FOLDER): - base = os.path.relpath(dirpath, FAMSA_FOLDER) - self.mkpath(os.path.join(self.build_clib, "FAMSA", base)) - for filename in filenames: - infile = os.path.join(dirpath, filename) - outfile = os.path.join(self.build_clib, "FAMSA", base, filename) - if os.path.exists(os.path.join(SETUP_FOLDER, "patches", "{}.patch".format(filename))): - self.make_file([infile], outfile, self._patch_file, (infile, outfile)) - else: - self.copy_file(infile, outfile) - - # fix library source paths - for i, source in enumerate(library.sources): - base = os.path.relpath(source, FAMSA_FOLDER) - library.sources[i] = os.path.join(self.build_temp, "FAMSA", base) - # fix include dirs to use the build directory folders - for i, include_dir in enumerate(library.include_dirs): - if include_dir.startswith(FAMSA_FOLDER): - base = os.path.relpath(include_dir, FAMSA_FOLDER) - library.include_dirs[i] = os.path.join(self.build_temp, "FAMSA", base) - - # store compile args - compile_args = ( - None, - library.define_macros, - library.include_dirs + [self.build_clib], - self.debug, - library.extra_compile_args, - None, - library.depends, - ) - # manually prepare sources and get the names of object files - objects = [ - re.sub(r'(\.cpp|\.c)$', self.compiler.obj_extension, s) - for s in library.sources - ] - # compile outdated files in parallel - with multiprocessing.pool.ThreadPool(self.parallel) as pool: - pool.starmap( - functools.partial(self._compile_file, compile_args=compile_args), - zip(library.sources, objects) - ) - - # build platform-specific code - self.build_simd_code(library) - - # link into a static library - libfile = self.compiler.library_filename( - library.name, - output_dir=self.build_clib, - ) - self.make_file( - objects,# + library.extra_objects, - libfile, - self.compiler.create_static_lib, - (objects, library.name, self.build_clib, None, self.debug) - ) - - def _compile_file(self, source, object, compile_args): - self.make_file( - [source], - object, - self.compiler.compile, - ([source], *compile_args) - ) - - -class clean(_clean): - """A `clean` that removes intermediate files created by Cython. - """ - - def run(self): - - source_dir = os.path.join(os.path.dirname(__file__), "pyfamsa") - - patterns = ["*.html"] - if self.all: - patterns.extend(["*.so", "*.c", "*.cpp"]) - - for pattern in patterns: - for file in glob.glob(os.path.join(source_dir, pattern)): - _eprint("removing {!r}".format(file)) - os.remove(file) - - _clean.run(self) - - -# --- Setup --------------------------------------------------------------------- - -setuptools.setup( - libraries=[ - Library( - "mimalloc", - language="c", - sources=[ - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "libs", "mimalloc", "src", "static.c"), - ], - include_dirs=[ - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "libs", "mimalloc", "include"), - ], - depends=[ - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "libs", "mimalloc", "include", "mimalloc.h"), - ] - ), - # NOTE(@althonos): libdeflate is only needed for `IOService`, but we - # don't use the FAMSA I/O so we don't have to build - # it and link to it, as long as we're not building - # `io_service.cpp` either - Library( - "famsa", - language="c++", - sources=[ - # COMMON_OBJS - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "msa.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "msa_refinement.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree","AbstractTreeGenerator.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree","Clustering.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree","DistanceCalculator.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree","FastTree.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree","GuideTree.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree","MSTPrim.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree","NeighborJoining.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree","NewickParser.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree","SingleLinkage.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree","UPGMA.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "timer.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "log.cpp"), - # os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "io_service.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "params.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "profile.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "profile_par.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "profile_seq.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "sequence.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "queues.cpp"), - # LCS_OBJS - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "lcs", "lcsbp.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "lcs", "lcsbp_classic.cpp"), - ], - include_dirs=[ - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "lcs"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "libs", "mimalloc", "include"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "libs"), - os.path.join(SETUP_FOLDER, "include"), - ], - depends=[ - # core - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "defs.h"), - # os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "io_service.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "params.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "profile.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "queues.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "sequence.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "core", "version.h"), - # lcs - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "lcs", "lcsbp_avx_intr.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "lcs", "lcsbp_avx2_intr.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "lcs", "lcsbp_classic.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "lcs", "lcsbp_neon_intr.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "lcs", "lcsbp.h"), - # tree - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "AbstractTreeGenerator.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "AbstractTreeGenerator.hpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "Chained.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "Clustering.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "DistanceCalculator.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "FastTree.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "GuideTree.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "IPartialGenerator.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "MSTPrim.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "NeighborJoining.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "NewickParser.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "SingleLinkage.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "SingleLinkageQueue.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "TreeDefs.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "tree", "UPGMA.h"), - # utils - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "array.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "conversion.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "cpuid.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "deterministic_random.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "log.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "memory_monotonic.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "meta_oper.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "pooled_threads.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "statistics.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "timer.h"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "utils.h"), - # msa - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "msa.h"), - ], - platform_sources={ - "AVX": [ - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "utils_avx.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "lcs", "lcsbp_avx_intr.cpp"), - ], - "AVX2": [ - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "utils_avx2.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "lcs", "lcsbp_avx2_intr.cpp"), - ], - "NEON": [ - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "utils_neon.cpp"), - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "lcs", "lcsbp_neon_intr.cpp"), - ] - }, - ), - ], - ext_modules=[ - Extension( - "pyfamsa._famsa", - language="c++", - sources=[ - # for some reason, if this file is not compiled in the extension - # this causes the `clear_mem` symbol to be missing from the - # final shared object - os.path.join(SETUP_FOLDER, "vendor", "FAMSA", "src", "utils", "utils.cpp"), - os.path.join(SETUP_FOLDER, "pyfamsa", "_famsa.pyx"), - ], - include_dirs=[ - os.path.join(SETUP_FOLDER, "include"), - ], - libraries=[ - "mimalloc", - "famsa", - ], - ), - ], - cmdclass={ - "sdist": sdist, - "build_ext": build_ext, - "build_clib": build_clib, - "clean": clean - } -) From f0ccb5f3405217c7ef1bc440e03f7ff429a73dc0 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Wed, 6 Nov 2024 01:08:18 +0100 Subject: [PATCH 13/13] Update some information in `README.md` --- CONTRIBUTING.md | 4 ++-- README.md | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 01a56ff..bc345b3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,13 +20,13 @@ the standard library. Running them requires the extension to be built locally: ```console -$ python setup.py build_ext --debug --inplace +$ python -m pip install -v -e . --no-build-isolation $ python -m unittest discover -vv ``` ## Coding guidelines -This project targets Python 3.6 or later. +This project targets Python 3.7 or later. Python objects should be typed; since it is not supported by Cython, you must manually declare types in type stubs (`.pyi` files). In Python diff --git a/README.md b/README.md index 2af5f57..b5c357c 100644 --- a/README.md +++ b/README.md @@ -43,16 +43,16 @@ the following advantages: - **friendly interface**: The different guide tree build methods and heuristics can be selected from the Python code with a simple keyword argument when configuring a new [`Aligner`](https://pyfamsa.readthedocs.io/en/stable/api/aligner.html#pyfamsa.Aligner). -- **custom scoring matrices**: You can use any custom scoring matrix from +- **custom scoring matrices**: You can use any custom scoring matrix from the [`scoring-matrices`](https://pypi.org/project/scoring-matrices) library - in addition to the default MIQS to score the alignment. + in addition to the default MIQS to score the alignment. ## 🔧 Installing PyFAMSA can be installed directly from [PyPI](https://pypi.org/project/pyfamsa/), -which hosts some pre-built wheels for the x86-64 architecture (Linux/OSX) -and the Aarch64 architecture (Linux only), as well as the code required to -compile from source with Cython: +which hosts some pre-built wheels for the x86-64 and Aarch architectures +for Linux, MacOS and Windows, as well as the code required to compile from +source with Cython: ```console $ pip install pyfamsa ``` @@ -63,7 +63,7 @@ package: $ conda install -c bioconda pyfamsa ``` -Otherwise, have a look at the [Installation page](https://pyfamsa.readthedocs.io/en/stable/install.html) of the [online documentation](https://pyfamsa.readthedocs.io/) +Otherwise, have a look at the [Installation page](https://pyfamsa.readthedocs.io/en/stable/guide/install.html) of the [online documentation](https://pyfamsa.readthedocs.io/) ## 💡 Example