diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1a2c217..645eba3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-22.04 + - os: ubuntu-20.04 arch: "x86_64" - os: ubuntu-22.04 arch: "i686" @@ -78,12 +78,23 @@ jobs: name: cibw-wheels-${{ matrix.os }}-${{ matrix.arch }} path: ./wheelhouse/*.whl + - name: Install Ubuntu Python 2.7 + if: matrix.os == 'ubuntu-20.04' + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends python2 python3-virtualenv + virtualenv -p python2 ${HOME}/cp27 + ${HOME}/cp27/bin/python -m pip install -U pip + ${HOME}/cp27/bin/python -m pip install -U setuptools wheel + echo "${HOME}/cp27/bin" >> $GITHUB_PATH + - name: Test wheel on host Linux if: runner.os == 'Linux' && matrix.arch == 'x86_64' run: | pip install wheelhouse/*manylinux*x86_64*.whl ninja --version python -m ninja --version + python --version build_sdist: name: Build source distribution @@ -105,43 +116,26 @@ jobs: test_sdist: name: Test SDist with python ${{ matrix.python }} needs: [build_sdist] - # 22.04 doesn't have 2.7 or 3.6 - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: - python: ["2.7", "3.6", "3.12"] + python: ["3.7", "3.12"] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 name: Install Python ${{ matrix.python }} - if: matrix.python != '2.7' with: python-version: ${{ matrix.python }} - - name: Install Ubuntu Python 2.7 - if: matrix.python == '2.7' - run: | - sudo apt-get update - sudo apt-get install -y --no-install-recommends python2 python3-virtualenv - virtualenv -p python2 ${HOME}/cp27 - ${HOME}/cp27/bin/python -m pip install -U pip - ${HOME}/cp27/bin/python -m pip install -U setuptools wheel - echo "${HOME}/cp27/bin" >> $GITHUB_PATH - - uses: actions/download-artifact@v4 with: name: cibw-sdist path: sdist - name: Install SDist - env: - SKBUILD_CONFIGURE_OPTIONS: "-DBUILD_CMAKE_FROM_SOURCE:BOOL=OFF" - run: pip install sdist/*.tar.gz - - - name: Install test dependencies - run: pip install -r requirements-test.txt + run: pip install $(ls sdist/*.tar.gz)[test] -Ccmake.define.BUILD_CMAKE_FROM_SOURCE=OFF - name: Test installed SDist run: pytest ./tests diff --git a/CMakeLists.txt b/CMakeLists.txt index d0ad97f..5f79690 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,9 +11,6 @@ set(ARCHIVE_DOWNLOAD_DIR "${CMAKE_BINARY_DIR}" CACHE PATH "Directory where to do include(NinjaUrls) -#----------------------------------------------------------------------------- -# Which archives ? -#----------------------------------------------------------------------------- function(check_archive_var archive_var) if(NOT DEFINED "${archive_var}_url") message(FATAL_ERROR "Failed to determine which archive to download: '${archive_var}_url' variable is not defined") @@ -29,9 +26,6 @@ if(WIN32) endif() check_archive_var("${src_archive}") -#----------------------------------------------------------------------------- -# Summary -#----------------------------------------------------------------------------- message(STATUS "*********************************************") message(STATUS "Ninja Python Distribution") message(STATUS "") @@ -45,9 +39,6 @@ message(STATUS " _url : ${${src_archive}_url}") message(STATUS " _sha256 : ${${src_archive}_sha256}") message(STATUS "*********************************************") -#----------------------------------------------------------------------------- -include(ExternalProject) - set(ep_download_no_progress_args) if(NOT BUILD_VERBOSE) set(ep_download_no_progress_args @@ -55,95 +46,15 @@ if(NOT BUILD_VERBOSE) ) endif() -#----------------------------------------------------------------------------- -# Download source -#----------------------------------------------------------------------------- -if(NOT DEFINED Ninja_SOURCE_DIR) - set(Ninja_SOURCE_DIR "${CMAKE_SOURCE_DIR}/Ninja-src") - - # Download selected source archive - ExternalProject_add(download_ninja_source - SOURCE_DIR ${Ninja_SOURCE_DIR} - URL ${${src_archive}_url} - URL_HASH SHA256=${${src_archive}_sha256} - DOWNLOAD_DIR ${ARCHIVE_DOWNLOAD_DIR} - USES_TERMINAL_DOWNLOAD 1 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - BUILD_IN_SOURCE 1 - INSTALL_COMMAND "" - ${ep_download_no_progress_args} - ) - message(STATUS "download_ninja_source - URL: ${${src_archive}_url}") -elseif(NOT EXISTS ${Ninja_SOURCE_DIR}) - message(FATAL_ERROR "Ninja_SOURCE_DIR is set to a nonexistent directory") -endif() - -#----------------------------------------------------------------------------- -# Build from source -#----------------------------------------------------------------------------- -set(Ninja_BINARY_DIR ${CMAKE_BINARY_DIR}/Ninja-build) -# cache arguments -set(_cache_args ) -foreach(var_name IN ITEMS - CMAKE_BUILD_TYPE - CMAKE_TOOLCHAIN_FILE - CMAKE_BUILD_PARALLEL_LEVEL - CMAKE_JOB_POOLS - CMAKE_JOB_POOL_COMPILE - CMAKE_JOB_POOL_LINK - CMAKE_OSX_DEPLOYMENT_TARGET - CMAKE_OSX_ARCHITECTURES - CMAKE_OSX_SYSROOT - ) - if(DEFINED ${var_name}) - list(APPEND _cache_args -D${var_name}:STRING=${${var_name}}) - message(STATUS "SuperBuild - ${var_name}: ${${var_name}}") - endif() -endforeach() - -# _cache_args should not be empty -list(APPEND _cache_args -DNINJA_SUPERBUILD:BOOL=true) -ExternalProject_add(build_ninja - SOURCE_DIR ${Ninja_SOURCE_DIR} - BINARY_DIR ${Ninja_BINARY_DIR} - DOWNLOAD_COMMAND "" - UPDATE_COMMAND "" - BUILD_ALWAYS 1 - USES_TERMINAL_CONFIGURE 1 - USES_TERMINAL_BUILD 1 - INSTALL_COMMAND "" - CMAKE_CACHE_ARGS ${_cache_args} - DEPENDS - download_ninja_source - ) -set(ninja_executable ${Ninja_BINARY_DIR}/ninja${CMAKE_EXECUTABLE_SUFFIX}) -set(NINJA_BUILD_LAST_STEP "build") - -# This should not be stripped or tested if cross-compiling on Windows -if(CMAKE_CROSS_COMPILE OR NOT DEFINED ENV{DIST_EXTRA_CONFIG}) - find_program(STRIP_EXECUTABLE strip) - if(STRIP_EXECUTABLE) - ExternalProject_Add_Step(build_ninja strip_executables - DEPENDEES ${NINJA_BUILD_LAST_STEP} - COMMENT "Stripping CMake executables" - COMMAND ${STRIP_EXECUTABLE} ${ninja_executable} - USES_TERMINAL 1 - ) - set(NINJA_BUILD_LAST_STEP "strip_executables") - endif() - - if(RUN_NINJA_TEST) - ExternalProject_Add_Step(build_ninja run_ninja_test_suite - DEPENDEES ${NINJA_BUILD_LAST_STEP} - COMMENT "Running Ninja test suite" - COMMAND ${Ninja_BINARY_DIR}/ninja_test${CMAKE_EXECUTABLE_SUFFIX} - WORKING_DIRECTORY ${Ninja_BINARY_DIR} - USES_TERMINAL 1 - ) - set(NINJA_BUILD_LAST_STEP "run_ninja_test_suite") - endif() -endif() - -install(FILES ${Ninja_SOURCE_DIR}/misc/ninja_syntax.py DESTINATION src/ninja) -install(PROGRAMS ${ninja_executable} DESTINATION src/ninja/data/bin) +include(FetchContent) +FetchContent_Declare( + ninja + URL ${${src_archive}_url} + URL_HASH SHA256=${${src_archive}_sha256} + DOWNLOAD_DIR ${ARCHIVE_DOWNLOAD_DIR} + ${ep_download_no_progress_args} +) +FetchContent_MakeAvailable(ninja) + +install(TARGETS ninja COMPONENT python DESTINATION "${SKBUILD_SCRIPTS_DIR}") +install(FILES "${ninja_SOURCE_DIR}/misc/ninja_syntax.py" COMPONENT python DESTINATION ninja) diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index f4adf95..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,14 +0,0 @@ -include CMakeLists.txt -include NinjaUrls.cmake -include requirements-test.txt -include HISTORY.rst -include README.rst -include LICENSE_Apache_20 - -recursive-exclude _skbuild * -recursive-exclude Ninja-src * - -include src/ninja/_version.py -include src/ninja/_version.pyi -include src/ninja/__init__.pyi -include src/ninja/py.typed diff --git a/constraints-ci.txt b/constraints-ci.txt deleted file mode 100644 index 806e700..0000000 --- a/constraints-ci.txt +++ /dev/null @@ -1,2 +0,0 @@ -cmake==3.22.6 -ninja==1.11.1.1 diff --git a/pyproject.toml b/pyproject.toml index be49ce6..3e85911 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,23 +1,88 @@ [build-system] -requires = [ - "setuptools >=42", - "setuptools-scm[toml]", - "scikit-build", +requires = ["scikit-build-core"] +build-backend = "scikit_build_core.build" + +[project] +name = "ninja" +dynamic = ["version", "readme"] +description = "Ninja is a small build system with a focus on speed" +authors = [ + { name = "Jean-Christophe Fillion-Robin", email = "scikit-build@googlegroups.com" }, + { name = "Henry Schreiner", email = "henryfs@princeton.edu" }, +] +keywords = [ + "build", + "c++", + "cross-compilation", + "cross-platform", + "fortran", + "ninja", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: C", + "Programming Language :: C++", + "Programming Language :: Fortran", + "Programming Language :: Python", + "Topic :: Software Development :: Build Tools", + "Typing :: Typed", ] -build-backend = "setuptools.build_meta" + +[project.optional-dependencies] +test = [ + "coverage>=4.2", + "importlib_metadata>=2.0", + "pytest-cov>=2.7.1", + "pytest>=4.5.0", +] + +[project.urls] +"Bug Tracker" = "https://github.com/scikit-build/ninja-python-distributions/issues" +Documentation = "https://github.com/scikit-build/ninja-python-distributions#readme" +Download = "https://github.com/ninja-build/ninja/releases" +Homepage = "http://ninja-build.org/" +"Mailing list" = "https://groups.google.com/forum/#!forum/scikit-build" +"Source Code" = "https://github.com/scikit-build/ninja-python-distributions" + +[tool.scikit-build] +minimum-version = "0.9" +build-dir = "build/{wheel_tag}" +wheel.py-api = "py2.py3" +wheel.expand-macos-universal-tags = true +metadata.version.provider = "scikit_build_core.metadata.setuptools_scm" +metadata.readme.provider = "scikit_build_core.metadata.fancy_pypi_readme" +install.components = ["python"] + + +[[tool.scikit-build.generate]] +path = "ninja/_version.py" +template = ''' +version = "${version}" +''' [tool.setuptools_scm] -write_to = "src/ninja/_version.py" + +[tool.hatch.metadata.hooks.fancy-pypi-readme] +content-type = "text/x-rst" + +[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] +path = "README.rst" + +[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] +path = "HISTORY.rst" + +[[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]] +pattern = ".. :changelog:" +replacement = "" + [tool.cibuildwheel] build = "cp39-*" build-verbosity = 1 -before-all = [ - 'pipx install -f --pip-args="-c {project}/constraints-ci.txt" cmake', - 'cmake --version', -] -before-build = "pip install -r requirements-repair.txt" -repair-wheel-command = "python scripts/repair_wheel.py -w {dest_dir} {wheel}" test-extras = "test" test-command = "pytest {project}/tests" test-skip = ["*-win_arm64", "*-macosx_universal2:arm64"] @@ -25,29 +90,22 @@ environment-pass = ["SETUPTOOLS_SCM_PRETEND_VERSION"] [[tool.cibuildwheel.overrides]] select = "*-manylinux_{x86_64,i686}" -manylinux-x86_64-image = "manylinux1" -manylinux-i686-image = "manylinux1" +manylinux-x86_64-image = "manylinux2010" +manylinux-i686-image = "manylinux2010" environment = { LDFLAGS = "-static-libstdc++" } [tool.cibuildwheel.macos.environment] MACOSX_DEPLOYMENT_TARGET = "10.9" -[tool.cibuildwheel.windows] -before-all = [ - 'pipx install -f --pip-args="-c {project}/constraints-ci.txt" cmake', - 'cmake --version', - 'pipx install -f --pip-args="-c {project}/constraints-ci.txt" ninja', - 'ninja --version', -] - [[tool.cibuildwheel.overrides]] select = "*-musllinux_*" environment = { LDFLAGS = "-static-libstdc++ -static-libgcc" } - [tool.ruff] -select = [ - "E", "F", "W", # flake8 +src = ["src"] + +[tool.ruff.lint] +extend-select = [ "B", # flake8-bugbear "I", # isort "ARG", # flake8-unused-arguments @@ -66,21 +124,19 @@ select = [ "NPY", # NumPy specific rules "PD", # pandas-vet ] -extend-ignore = [ +ignore = [ "PLR", # Design related pylint codes "E501", # Line too long "RUF005", # Python 3 needed "B904", # Python 3 needed # "SIM105", # Python 3 needed ] -src = ["src"] -unfixable = [ - "T20", # Removes print statements - "F841", # Removes unused variables -] -exclude = ["src/ninja/version.py"] flake8-unused-arguments.ignore-variadic-names = true -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "*.pyi" = ["ARG001"] "noxfile.py" = ["PLW0603"] # Could be fixed if Python 2 dropped + +[tool.pytest.ini_config] +testpaths = ["tests"] +addopts = ["-v", "--cov", "--cov-report", "xml"] diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index d26e2fb..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,5 +0,0 @@ --r requirements-test.txt --r requirements-repair.txt -scikit-build>=0.10.0 -setuptools>=28.0.0 -wheel>=0.34 diff --git a/requirements-repair.txt b/requirements-repair.txt deleted file mode 100644 index de121f3..0000000 --- a/requirements-repair.txt +++ /dev/null @@ -1 +0,0 @@ -wheel>=0.40.0 diff --git a/requirements-test.txt b/requirements-test.txt deleted file mode 100644 index bd793e9..0000000 --- a/requirements-test.txt +++ /dev/null @@ -1,4 +0,0 @@ -coverage>=4.2 -importlib_metadata>=2.0 -pytest>=4.5.0 -pytest-cov>=2.7.1 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 0cd9906..0000000 --- a/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[tool:pytest] -testpaths = tests -addopts = -v --cov --cov-report xml diff --git a/setup.py b/setup.py deleted file mode 100755 index ab7c4a9..0000000 --- a/setup.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from distutils.text_file import TextFile - -from skbuild import setup - -with open('README.rst', 'r') as fp: - readme = fp.read() - -with open('HISTORY.rst', 'r') as fp: - history = fp.read().replace('.. :changelog:', '') - - -def parse_requirements(filename): - with open(filename, 'r') as file: - return TextFile(filename, file).readlines() - - -requirements = [] -test_requirements = parse_requirements('requirements-test.txt') - - -setup( - name='ninja', - - author='Jean-Christophe Fillion-Robin', - author_email='scikit-build@googlegroups.com', - - package_dir={'': 'src'}, - packages=['ninja'], - package_data={"ninja": ["py.typed"]}, - - entry_points={ - 'console_scripts': [ - 'ninja=ninja:ninja' - ] - }, - - url=r'http://ninja-build.org/', - download_url=r'https://github.com/ninja-build/ninja/releases', - project_urls={ - "Documentation": "https://github.com/scikit-build/ninja-python-distributions#readme", - "Source Code": "https://github.com/scikit-build/ninja-python-distributions", - "Mailing list": "https://groups.google.com/forum/#!forum/scikit-build", - "Bug Tracker": "https://github.com/scikit-build/ninja-python-distributions/issues", - }, - - description=r'Ninja is a small build system with a focus on speed', - - long_description=readme + '\n\n' + history, - long_description_content_type='text/x-rst', - - classifiers=[ - 'License :: OSI Approved :: Apache Software License', - 'License :: OSI Approved :: BSD License', - 'Programming Language :: C', - 'Programming Language :: C++', - 'Programming Language :: Fortran', - 'Programming Language :: Python', - 'Operating System :: OS Independent', - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Topic :: Software Development :: Build Tools', - 'Typing :: Typed', - ], - - license='Apache 2.0', - - keywords='ninja build c++ fortran cross-platform cross-compilation', - - extras_require={"test": test_requirements}, -) diff --git a/src/ninja/__init__.py b/src/ninja/__init__.py index d2c3a24..ec23419 100644 --- a/src/ninja/__init__.py +++ b/src/ninja/__init__.py @@ -1,54 +1,55 @@ # -*- coding: utf-8 -*- import os -import platform import subprocess import sys +import sysconfig from ._version import version as __version__ +from .ninja_syntax import Writer, escape, expand -__all__ = ["__version__", "DATA", "BIN_DIR", "ninja"] +__all__ = ["__version__", "DATA", "BIN_DIR", "ninja", "Writer", "escape", "expand"] def __dir__(): return __all__ -try: - from .ninja_syntax import Writer, escape, expand -except ImportError: - # Support importing `ninja_syntax` from the source tree - if not os.path.exists( - os.path.join(os.path.dirname(__file__), 'ninja_syntax.py')): - sys.path.insert(0, os.path.abspath(os.path.join( - os.path.dirname(__file__), '../../Ninja-src/misc'))) - from ninja_syntax import Writer, escape, expand # noqa: F401 +def _get_ninja_dir(): + ninja_exe = "ninja" + sysconfig.get_config_var("EXE") -DATA = os.path.join(os.path.dirname(__file__), 'data') + # Default path + path = os.path.join(sysconfig.get_path("scripts"), ninja_exe) + if os.path.isfile(path): + return os.path.dirname(path) -# Support running tests from the source tree -if not os.path.exists(DATA): - from skbuild.constants import CMAKE_INSTALL_DIR as SKBUILD_CMAKE_INSTALL_DIR - from skbuild.constants import set_skbuild_plat_name + # User path + if sys.version_info >= (3, 10): + user_scheme = sysconfig.get_preferred_scheme("user") + elif os.name == "nt": + user_scheme = "nt_user" + elif sys.platform.startswith("darwin") and sys._framework: + user_scheme = "osx_framework_user" + else: + user_scheme = "posix_user" - if platform.system().lower() == "darwin": - # Since building the project specifying --plat-name or CMAKE_OSX_* variables - # leads to different SKBUILD_DIR, the code below attempt to guess the most - # likely plat-name. - _skbuild_dirs = os.listdir(os.path.join(os.path.dirname(__file__), '..', '..', '_skbuild')) - if _skbuild_dirs: - _likely_plat_name = '-'.join(_skbuild_dirs[0].split('-')[:3]) - set_skbuild_plat_name(_likely_plat_name) + path = sysconfig.get_path("scripts", scheme=user_scheme) - _data = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', SKBUILD_CMAKE_INSTALL_DIR(), 'src/ninja/data')) - if os.path.exists(_data): - DATA = _data + if os.path.isfile(os.path.join(path, ninja_exe)): + return path -BIN_DIR = os.path.join(DATA, 'bin') + # Fallback to python location + path = os.path.dirname(sys.executable) + if os.path.isfile(os.path.join(path, ninja_exe)): + return path + return "" + + +BIN_DIR = _get_ninja_dir() def _program(name, args): - return subprocess.call([os.path.join(BIN_DIR, name)] + args, close_fds=False) + cmd = os.path.join(BIN_DIR, name) + return subprocess.call([cmd] + args, close_fds=False) def ninja():