diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 0083daac64..154e092f7a 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -53,7 +53,7 @@ jobs: - name: Build C module if: env.MAKE_TARGET - run: make $MAKE_TARGET + run: cd python && meson setup build && meson compile -C build - name: Build Docs run: | diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 30b1c1b5f3..8bc89db5b8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -74,11 +74,12 @@ jobs: working-directory: python if: matrix.os == 'windows-latest' run: | - rm -r lib - mkdir lib - cp -r --dereference ../c/subprojects lib/. - cp -r --dereference ../c/tskit lib/. - cp ../c/tskit.h lib/. + rm subprojects/libtskit + mkdir -p subprojects/libtskit + cp -r --dereference ../c/subprojects subprojects/libtskit/. + cp -r --dereference ../c/tskit subprojects/libtskit/. + cp ../c/meson.build subprojects/libtskit/ + cp ../c/VERSION.txt subprojects/libtskit/ - name: Fix windows .profile if: steps.cache.outputs.cache-hit != 'true' && matrix.os == 'windows-latest' @@ -104,7 +105,13 @@ jobs: run: | source ~/.profile conda activate anaconda-client-env - python setup.py build_ext --inplace + if [[ "${{ matrix.os }}" == "windows-latest" ]]; then + meson setup build --vsenv --backend=vs + else + meson setup build + fi + meson compile -C build + mv build/_tskit*.so . - name: Minidom test working-directory: python @@ -165,7 +172,9 @@ jobs: - name: Build module working-directory: python run: | - python setup.py build_ext --inplace + meson setup build + meson compile -C build + mv build/_tskit*.so . - name: Run tests with numpy 1.x working-directory: python diff --git a/python/_tskitmodule.c b/python/_tskitmodule.c index cab445e5d0..951d9b9f33 100644 --- a/python/_tskitmodule.c +++ b/python/_tskitmodule.c @@ -14714,7 +14714,7 @@ static struct PyModuleDef tskitmodule = { .m_methods = tskit_methods, }; -PyObject * +PyMODINIT_FUNC PyInit__tskit(void) { PyObject *module; diff --git a/python/flake.lock b/python/flake.lock new file mode 100644 index 0000000000..0230c28820 --- /dev/null +++ b/python/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1753115646, + "narHash": "sha256-yLuz5cz5Z+sn8DRAfNkrd2Z1cV6DaYO9JMrEz4KZo/c=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "92c2e04a475523e723c67ef872d8037379073681", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/python/flake.nix b/python/flake.nix new file mode 100644 index 0000000000..81bdc0fd0e --- /dev/null +++ b/python/flake.nix @@ -0,0 +1,26 @@ +{ + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; + outputs = + { self, nixpkgs }@inputs: + let + system = "x86_64-linux"; + pkgs = import inputs.nixpkgs { inherit system; }; + in + { + devShells.${system}.default = + (pkgs.buildFHSEnv { + name = "python"; + targetPkgs = pkgs: [ + pkgs.gcc + pkgs.gsl + pkgs.gsl.dev + pkgs.libz + pkgs.meson + pkgs.ninja + pkgs.pkg-config + pkgs.python313Full + ]; + runScript = "fish"; + }).env; + }; +} diff --git a/python/lib b/python/lib deleted file mode 120000 index 9e8cf0c2ee..0000000000 --- a/python/lib +++ /dev/null @@ -1 +0,0 @@ -../c/ \ No newline at end of file diff --git a/python/meson.build b/python/meson.build new file mode 100644 index 0000000000..329479878a --- /dev/null +++ b/python/meson.build @@ -0,0 +1,29 @@ +project( + 'tskit', 'c', + version: run_command(['tskit' / '_version.py'], check: true).stdout().strip(), + default_options: ['c_std=c99', 'cpp_std=c++11'] +) + +subdir('tskit') +py = import('python').find_installation(pure: false) +py.install_sources(src, subdir: 'tskit') + +deps = [ + subproject( + 'libtskit', default_options: ['werror=false'] + ).get_variable('tskit_dep'), + declare_dependency( + include_directories: run_command( + py, '-c', 'import numpy;print(numpy.get_include())', + check: true + ).stdout().strip() + ) +] + +py.extension_module( + '_tskit', + '_tskitmodule.c', + dependencies: deps, + include_directories: 'lwt_interface', + install: true, +) diff --git a/python/pyproject.toml b/python/pyproject.toml index 80b9cc1f78..3922e80a76 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,10 @@ [build-system] -requires = ["setuptools>=45", "wheel", "numpy>=2.0"] -build-backend = "setuptools.build_meta" +requires = ["meson-python", "numpy>=2.0"] +build-backend = "mesonpy" + +[tool.meson-python.args] +setup = ["--default-library=static"] +install = ["--skip-subprojects"] [project] name = "tskit" @@ -56,12 +60,6 @@ GitHub = "https://github.com/tskit-dev/tskit/" [project.scripts] tskit = "tskit.cli:tskit_main" -[tool.setuptools] -packages = ["tskit"] - -[tool.setuptools.dynamic] -version = {attr = "tskit._version.tskit_version"} - [tool.pytest.ini_options] addopts = "-n 4" testpaths = ["tests"] diff --git a/python/requirements/CI-complete/requirements.txt b/python/requirements/CI-complete/requirements.txt index 8920fa33ca..2b6e281a87 100644 --- a/python/requirements/CI-complete/requirements.txt +++ b/python/requirements/CI-complete/requirements.txt @@ -1,3 +1,5 @@ +meson==1.8.2 +ninja==1.11.1.4 biopython==1.85 coverage==7.7.0 dendropy==5.0.1 diff --git a/python/requirements/CI-docs/requirements.txt b/python/requirements/CI-docs/requirements.txt index 09877a41dd..3b4c746f10 100644 --- a/python/requirements/CI-docs/requirements.txt +++ b/python/requirements/CI-docs/requirements.txt @@ -1,3 +1,5 @@ +meson==1.8.2 +ninja==1.11.1.4 jupyter-book==1.0.4.post1 breathe==4.35.0 sphinx-autodoc-typehints==2.3.0 @@ -5,4 +7,4 @@ sphinx-issues==5.0.0 sphinx-argparse==0.5.2 msprime==1.3.3 sphinx-book-theme -pandas==2.2.3 \ No newline at end of file +pandas==2.2.3 diff --git a/python/requirements/CI-tests-pip/requirements.txt b/python/requirements/CI-tests-pip/requirements.txt index 2e162f68d7..6c711f71d9 100644 --- a/python/requirements/CI-tests-pip/requirements.txt +++ b/python/requirements/CI-tests-pip/requirements.txt @@ -1,3 +1,5 @@ +meson==1.8.2 +ninja==1.11.1.4 lshmm==0.0.8 pytest==8.3.5 pytest-cov==6.0.0 @@ -11,4 +13,4 @@ networkx==3.2.1 msgpack==1.1.0 newick==1.10.0 kastore==0.3.3 -jsonschema==4.23.0 \ No newline at end of file +jsonschema==4.23.0 diff --git a/python/setup.py b/python/setup.py deleted file mode 100644 index 0f8e77abdb..0000000000 --- a/python/setup.py +++ /dev/null @@ -1,45 +0,0 @@ -import os -import platform - -import numpy -from setuptools import Extension -from setuptools import setup - -IS_WINDOWS = platform.system() == "Windows" - - -libdir = "lib" -kastore_dir = os.path.join(libdir, "subprojects", "kastore") -tsk_source_files = [ - "core.c", - "tables.c", - "trees.c", - "genotypes.c", - "stats.c", - "convert.c", - "haplotype_matching.c", -] -sources = ( - ["_tskitmodule.c"] - + [os.path.join(libdir, "tskit", f) for f in tsk_source_files] - + [os.path.join(kastore_dir, "kastore.c")] -) - -defines = [] -libraries = [] -if IS_WINDOWS: - libraries.append("Advapi32") - defines.append(("WIN32", None)) - -_tskit_module = Extension( - "_tskit", - sources=sources, - extra_compile_args=["-std=c99"], - libraries=libraries, - define_macros=defines, - include_dirs=["lwt_interface", libdir, kastore_dir, numpy.get_include()], -) - -setup( - ext_modules=[_tskit_module], -) diff --git a/python/subprojects/libtskit b/python/subprojects/libtskit new file mode 120000 index 0000000000..2fcc51115e --- /dev/null +++ b/python/subprojects/libtskit @@ -0,0 +1 @@ +../../c \ No newline at end of file diff --git a/python/tskit/_version.py b/python/tskit/_version.py old mode 100644 new mode 100755 index 9caefdbdab..1528fe2ed0 --- a/python/tskit/_version.py +++ b/python/tskit/_version.py @@ -1,4 +1,8 @@ +#!/usr/bin/env python3 # Definitive location for the version number. # During development, should be x.y.z.devN # For beta should be x.y.zbN tskit_version = "0.6.5.dev0" + +if __name__ == "__main__": + print(tskit_version) diff --git a/python/tskit/meson.build b/python/tskit/meson.build new file mode 100644 index 0000000000..cb21b34726 --- /dev/null +++ b/python/tskit/meson.build @@ -0,0 +1,18 @@ +src = files( + 'cli.py', + 'combinatorics.py', + 'drawing.py', + 'exceptions.py', + 'genotypes.py', + '__init__.py', + 'intervals.py', + '__main__.py', + 'metadata.py', + 'provenance.py', + 'stats.py', + 'tables.py', + 'text_formats.py', + 'trees.py', + 'util.py', + 'vcf.py', +)