From 7577f1b17f103e853b2b4b3cb9a45a59108aabe8 Mon Sep 17 00:00:00 2001 From: Johannes Spies <13813209+johannes-spies@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:05:08 +0200 Subject: [PATCH 1/8] Build the library in metatomic-core Python package --- .github/workflows/build-wheels.yml | 105 ++++++++- metatomic-core/CMakeLists.txt | 11 + .../cmake/metatomic-config.in.cmake | 16 +- metatomic-core/cmake/nlohmann_json.cmake | 3 + python/metatomic_ase/setup.py | 7 +- python/metatomic_core/CMakeLists.txt | 62 ++++++ python/metatomic_core/MANIFEST.in | 2 + python/metatomic_core/setup.py | 200 +++++++++++++++++- python/metatomic_torch/setup.py | 7 +- python/metatomic_torchsim/setup.py | 7 +- .../gcc11-manylinux_2_28_aarch64/Dockerfile | 9 - .../gcc11-manylinux_2_28_x86_64/Dockerfile | 9 - .../rustc-manylinux_2_28_aarch64/Dockerfile | 18 ++ .../rustc-manylinux_2_28_x86_64/Dockerfile | 18 ++ scripts/git-version-info.py | 9 +- scripts/package-core.sh | 54 +++++ 16 files changed, 496 insertions(+), 41 deletions(-) delete mode 100644 python/scripts/gcc11-manylinux_2_28_aarch64/Dockerfile delete mode 100644 python/scripts/gcc11-manylinux_2_28_x86_64/Dockerfile create mode 100644 python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile create mode 100644 python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile create mode 100755 scripts/package-core.sh diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 70f3043e8..34f8b3c1b 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -24,6 +24,79 @@ concurrency: jobs: + build-core-wheels: + runs-on: ${{ matrix.os }} + name: ${{ matrix.name }} + strategy: + matrix: + include: + - name: x86_64 Linux + os: ubuntu-24.04 + rust-target: x86_64-unknown-linux-gnu + cibw-arch: x86_64 + - name: arm64 Linux + os: ubuntu-24.04-arm + rust-target: aarch64-unknown-linux-gnu + cibw-arch: aarch64 + - name: arm64 macOS + os: macos-15 + rust-target: aarch64-apple-darwin + cibw-arch: arm64 + - name: x86_64 Windows + os: windows-2022 + rust-target: x86_64-pc-windows-msvc + cibw-arch: AMD64 + steps: + - uses: actions/checkout@v7 + with: + fetch-depth: 0 + + - name: setup rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + target: ${{ matrix.rust-target }} + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.14" + + - name: install dependencies + run: python -m pip install cibuildwheel twine + + - name: build custom manylinux docker images + if: matrix.os == 'ubuntu-24.04' || matrix.os == 'ubuntu-24.04-arm' + run: | + docker buildx build \ + -t rustc-manylinux_2_28_${{ matrix.cibw-arch }} \ + python/scripts/rustc-manylinux_2_28_${{ matrix.cibw-arch }} + + - name: build metatomic-core wheel + run: python -m cibuildwheel python/metatomic_core + env: + CIBW_BUILD: cp311-* + CIBW_SKIP: "*musllinux*" + CIBW_ARCHS: ${{ matrix.cibw-arch }} + CIBW_BUILD_VERBOSITY: 1 + CIBW_MANYLINUX_X86_64_IMAGE: rustc-manylinux_2_28_x86_64 + CIBW_MANYLINUX_AARCH64_IMAGE: rustc-manylinux_2_28_aarch64 + CIBW_ENVIRONMENT: > + MACOSX_DEPLOYMENT_TARGET=11 + # do not complain for missing shared libraries provided by other packages + CIBW_REPAIR_WHEEL_COMMAND_MACOS: | + delocate-wheel --ignore-missing-dependencies --require-archs {delocate_archs} -w {dest_dir} -v {wheel} + CIBW_REPAIR_WHEEL_COMMAND_LINUX: | + auditwheel repair --exclude libmetatensor.so -w {dest_dir} {wheel} + + - name: check wheels with twine + run: twine check wheelhouse/*.whl + + - uses: actions/upload-artifact@v7 + with: + name: core-wheel-${{ matrix.os }}-${{ matrix.cibw-arch }} + path: ./wheelhouse/*.whl + build-torch-wheels: runs-on: ${{ matrix.os }} name: ${{ matrix.name }} (torch v${{ matrix.torch-version }}) @@ -89,8 +162,8 @@ jobs: if: matrix.os == 'ubuntu-24.04' || matrix.os == 'ubuntu-24.04-arm' run: | docker buildx build \ - -t gcc11-manylinux_2_28_${{ matrix.cibw-arch }} \ - python/scripts/gcc11-manylinux_2_28_${{ matrix.cibw-arch }} + -t rustc-manylinux_2_28_${{ matrix.cibw-arch }} \ + python/scripts/rustc-manylinux_2_28_${{ matrix.cibw-arch }} - name: build metatomic-torch wheel run: python -m cibuildwheel python/metatomic_torch @@ -99,8 +172,8 @@ jobs: CIBW_SKIP: "*musllinux*" CIBW_ARCHS: ${{ matrix.cibw-arch }} CIBW_BUILD_VERBOSITY: 1 - CIBW_MANYLINUX_X86_64_IMAGE: gcc11-manylinux_2_28_x86_64 - CIBW_MANYLINUX_AARCH64_IMAGE: gcc11-manylinux_2_28_aarch64 + CIBW_MANYLINUX_X86_64_IMAGE: rustc-manylinux_2_28_x86_64 + CIBW_MANYLINUX_AARCH64_IMAGE: rustc-manylinux_2_28_aarch64 # METATOMIC_NO_LOCAL_DEPS is set to 1 when building a tag of # metatomic-torch, which will force to use the version of # metatomic-core already released on PyPI. Otherwise, this will use @@ -214,6 +287,9 @@ jobs: - name: install dependencies run: python -m pip install wheel build twine + - name: build metatomic-core sdist + run: python -m build python/metatomic_core --sdist --outdir=dist/ + - name: build metatomic-torch sdist run: python -m build python/metatomic_torch --sdist --outdir=dist/ @@ -231,6 +307,7 @@ jobs: - name: create C++ tarballs run: | + ./scripts/package-core.sh dist/cxx/ ./scripts/package-torch.sh dist/cxx/ - uses: actions/upload-artifact@v7 @@ -243,12 +320,19 @@ jobs: merge-and-release: name: Merge and release wheels/sdists - needs: [merge-torch-wheels, build-others] + needs: [build-core-wheels, merge-torch-wheels, build-others] runs-on: ubuntu-24.04 permissions: contents: write pull-requests: write steps: + - name: Download metatomic-core wheels + uses: actions/download-artifact@v8 + with: + path: wheels + pattern: core-wheel-* + merge-multiple: true + - name: Download metatomic-torch wheels uses: actions/download-artifact@v8 with: @@ -277,6 +361,17 @@ jobs: name: wheels description: ⚙️ Download Python wheels for this pull-request (you can install these with pip) + - name: upload to GitHub release (metatomic-core) + if: startsWith(github.ref, 'refs/tags/metatomic-core-v') + uses: softprops/action-gh-release@v3 + with: + files: | + wheels/cxx/metatomic-core-cxx-*.tar.gz + wheels/metatomic_core-* + prerelease: ${{ contains(github.ref, '-rc') }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: upload to GitHub release (metatomic) if: startsWith(github.ref, 'refs/tags/metatomic-v') uses: softprops/action-gh-release@v3 diff --git a/metatomic-core/CMakeLists.txt b/metatomic-core/CMakeLists.txt index 0eb97f20f..c80d7e658 100644 --- a/metatomic-core/CMakeLists.txt +++ b/metatomic-core/CMakeLists.txt @@ -461,3 +461,14 @@ install(FILES ${PROJECT_BINARY_DIR}/metatomic-config.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/metatomic ) + +if (NOT nlohmann_json_FOUND) + # nlohmann_json was fetched and vendored by us: install its headers (used + # by metatomic's own public headers), but remove the CMake package config + # and pkg-config files it installs, since we don't want to advertise a + # system-wide nlohmann_json package to external users. + install(CODE " + file(REMOVE_RECURSE \"\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/cmake/nlohmann_json\") + file(REMOVE \"\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/pkgconfig/nlohmann_json.pc\") + ") +endif() diff --git a/metatomic-core/cmake/metatomic-config.in.cmake b/metatomic-core/cmake/metatomic-config.in.cmake index 4bccc34ba..cda12fbbe 100644 --- a/metatomic-core/cmake/metatomic-config.in.cmake +++ b/metatomic-core/cmake/metatomic-config.in.cmake @@ -15,8 +15,16 @@ enable_language(CXX) set(REQUIRED_METATENSOR_VERSION @REQUIRED_METATENSOR_VERSION@) find_package(metatensor ${REQUIRED_METATENSOR_VERSION} CONFIG REQUIRED) -# Find nlohmann_json dependency -find_dependency(nlohmann_json 3.11.0) +# nlohmann_json is either vendored by us (its headers are installed alongside +# metatomic's own, in the same include directory, but not its CMake package +# config) or was found as a system package when building metatomic; only look +# for the system package in the latter case. +if (@nlohmann_json_FOUND@) + find_dependency(nlohmann_json 3.11.0) + set(METATOMIC_NLOHMANN_JSON_LIBRARY "nlohmann_json::nlohmann_json") +else() + set(METATOMIC_NLOHMANN_JSON_LIBRARY "") +endif() get_filename_component(METATOMIC_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/@PACKAGE_RELATIVE_PATH@" ABSOLUTE) @@ -49,7 +57,7 @@ if (@METATOMIC_INSTALL_BOTH_STATIC_SHARED@ OR @BUILD_SHARED_LIBS@) ) target_compile_features(metatomic::shared INTERFACE cxx_std_17) - target_link_libraries(metatomic::shared INTERFACE metatensor nlohmann_json::nlohmann_json) + target_link_libraries(metatomic::shared INTERFACE metatensor ${METATOMIC_NLOHMANN_JSON_LIBRARY}) if (WIN32) if (NOT EXISTS ${METATOMIC_IMPLIB_LOCATION}) @@ -80,7 +88,7 @@ if (@METATOMIC_INSTALL_BOTH_STATIC_SHARED@ OR NOT @BUILD_SHARED_LIBS@) target_compile_features(metatomic::static INTERFACE cxx_std_17) target_link_libraries(metatomic::static INTERFACE metatensor) - target_link_libraries(metatomic::static INTERFACE nlohmann_json::nlohmann_json) + target_link_libraries(metatomic::static INTERFACE ${METATOMIC_NLOHMANN_JSON_LIBRARY}) if(APPLE) target_link_libraries(metatomic::static INTERFACE diff --git a/metatomic-core/cmake/nlohmann_json.cmake b/metatomic-core/cmake/nlohmann_json.cmake index 39fd371fc..00934673b 100644 --- a/metatomic-core/cmake/nlohmann_json.cmake +++ b/metatomic-core/cmake/nlohmann_json.cmake @@ -31,6 +31,9 @@ else() ) set(JSON_BuildTests OFF CACHE INTERNAL "") + # We need nlohmann_json's headers to be installed alongside metatomic's own + # (they are used in our public headers), but not its own CMake package + # config / pkg-config files, which we strip after install below. set(JSON_Install ON CACHE INTERNAL "") FetchContent_MakeAvailable(nlohmann_json) diff --git a/python/metatomic_ase/setup.py b/python/metatomic_ase/setup.py index da391eb47..9c4b1f606 100644 --- a/python/metatomic_ase/setup.py +++ b/python/metatomic_ase/setup.py @@ -77,12 +77,15 @@ def git_version_info(): f"stdout: {output.stdout}\n" f"stderr: {output.stderr}\n" ) - elif output.stderr: + if output.stderr: print(output.stderr, file=sys.stderr) + + lines = output.stdout.splitlines() + if len(lines) < 2: + # the script gave up early (cf. `warn_and_exit`) n_commits = 0 git_hash = "" else: - lines = output.stdout.splitlines() n_commits = int(lines[0].strip()) git_hash = lines[1].strip() diff --git a/python/metatomic_core/CMakeLists.txt b/python/metatomic_core/CMakeLists.txt index e69de29bb..02b9f407d 100644 --- a/python/metatomic_core/CMakeLists.txt +++ b/python/metatomic_core/CMakeLists.txt @@ -0,0 +1,62 @@ +# This file allow the python module in metatomic-core to either use an +# externally-provided version of the shared metatomic library; or to build the +# code from source and bundle the shared library inside the wheel. +# +# The first case is used when distributing the code in conda (since we have a +# separate libmetatomic package), the second one is used everywhere else (for +# local development builds and for the PyPI distribution). + +cmake_minimum_required(VERSION 3.22) +project(metatomic-python NONE) + +option(METATOMIC_CORE_PYTHON_USE_EXTERNAL_LIB "Force the usage of an external version of metatomic-core" OFF) +set(METATOMIC_CORE_SOURCE_DIR "" CACHE PATH "Path to the sources of metatomic-core") + +file(REMOVE ${CMAKE_INSTALL_PREFIX}/_external.py) + +set(REQUIRED_METATOMIC_VERSION "0.1.0") +if(${METATOMIC_CORE_PYTHON_USE_EXTERNAL_LIB}) + # when building a source checkout, update version to include git information + # this will not apply when building a sdist + if (EXISTS ${CMAKE_SOURCE_DIR}/../../metatomic-core/cmake/dev-versions.cmake) + include(${CMAKE_SOURCE_DIR}/../../metatomic-core/cmake/dev-versions.cmake) + create_development_version("${REQUIRED_METATOMIC_VERSION}" REQUIRED_METATOMIC_VERSION "metatomic-core-v") + # strip any -dev/-rc suffix on the version since find_package does not support it + string(REGEX REPLACE "([0-9]*)\\.([0-9]*)\\.([0-9]*).*" "\\1.\\2.\\3" REQUIRED_METATOMIC_VERSION ${REQUIRED_METATOMIC_VERSION}) + endif() + + find_package(metatomic ${REQUIRED_METATOMIC_VERSION} REQUIRED) + + get_target_property(METATOMIC_LOCATION metatomic::shared LOCATION) + message(STATUS "Using external metatomic-core v${metatomic_VERSION} at ${METATOMIC_LOCATION}") + + # Get the prefix to use as cmake_prefix_path when trying to load this + # version of the library again + get_filename_component(METATOMIC_PREFIX "${METATOMIC_LOCATION}" DIRECTORY) + get_filename_component(METATOMIC_PREFIX "${METATOMIC_PREFIX}" DIRECTORY) + + file(WRITE ${CMAKE_INSTALL_PREFIX}/_external.py + "EXTERNAL_METATOMIC_PATH = \"${METATOMIC_LOCATION}\"\n\n" + ) + file(APPEND ${CMAKE_INSTALL_PREFIX}/_external.py + "EXTERNAL_METATOMIC_PREFIX = \"${METATOMIC_PREFIX}\"\n" + ) + + install(CODE "message(STATUS \"nothing to install\")") +else() + if ("${METATOMIC_CORE_SOURCE_DIR}" STREQUAL "") + message(FATAL_ERROR + "Missing METATOMIC_CORE_SOURCE_DIR, please specify where to \ + find the source code for metatomic-core" + ) + endif() + + message(STATUS "Using internal metatomic-core from ${METATOMIC_CORE_SOURCE_DIR}") + + set(BUILD_SHARED_LIBS ON) + set(METATOMIC_INSTALL_BOTH_STATIC_SHARED OFF) + # strip dynamic library for smaller wheels to download/install + set(EXTRA_RUST_FLAGS "-Cstrip=symbols") + + add_subdirectory("${METATOMIC_CORE_SOURCE_DIR}" metatomic-core) +endif() diff --git a/python/metatomic_core/MANIFEST.in b/python/metatomic_core/MANIFEST.in index 02404051b..17a63224a 100644 --- a/python/metatomic_core/MANIFEST.in +++ b/python/metatomic_core/MANIFEST.in @@ -4,3 +4,5 @@ include AUTHORS include LICENSE include git_version_info + +include metatomic-core-cxx-*.tar.gz diff --git a/python/metatomic_core/setup.py b/python/metatomic_core/setup.py index 905fb5c23..9e9c3b1dd 100644 --- a/python/metatomic_core/setup.py +++ b/python/metatomic_core/setup.py @@ -1,18 +1,19 @@ +import glob import os import pathlib import subprocess import sys import packaging.version -from setuptools import setup +from setuptools import Extension, setup from setuptools.command.bdist_egg import bdist_egg +from setuptools.command.bdist_wheel import bdist_wheel +from setuptools.command.build_ext import build_ext from setuptools.command.sdist import sdist ROOT = pathlib.Path(__file__).parent.resolve() -METATOMIC_CORE_VERSION = "0.1.0" - METATOMIC_BUILD_TYPE = os.environ.get("METATOMIC_BUILD_TYPE", "release") if METATOMIC_BUILD_TYPE not in ["debug", "release"]: raise Exception( @@ -20,6 +21,108 @@ "expected 'debug' or 'release'" ) +# the root path to the _native_ source code of metatomic (Rust source, but built with +# cmake) +METATOMIC_CORE_SRC = os.path.join(ROOT, "..", "..", "metatomic-core") + + +class universal_wheel(bdist_wheel): + # When building the wheel, the `wheel` package assumes that if we have a + # binary extension then we are linking to `libpython.so`; and thus the wheel + # is only usable with a single python version. This is not the case for + # here, and the wheel will be compatible with any Python >=3. This is + # tracked in https://github.com/pypa/wheel/issues/185, but until then we + # manually override the wheel tag. + def get_tag(self): + tag = bdist_wheel.get_tag(self) + # tag[2:] contains the os/arch tags, we want to keep them + return ("py3", "none") + tag[2:] + + +class cmake_ext(build_ext): + """ + Build the native library using cmake + """ + + def finalize_options(self): + if self.editable_mode: + raise RuntimeError( + "metatensor-core does not support editable installation yet" + ) + return super().finalize_options() + + def run(self): + import metatensor + + source_dir = ROOT + build_dir = os.path.join(ROOT, "build", "cmake-build") + install_dir = os.path.join(os.path.realpath(self.build_lib), "metatomic") + + os.makedirs(build_dir, exist_ok=True) + + use_external_lib = os.environ.get( + "METATOMIC_CORE_PYTHON_USE_EXTERNAL_LIB", "OFF" + ) + + cmake_options = [ + "-DCMAKE_VERBOSE_MAKEFILE=ON", + f"-DCMAKE_INSTALL_PREFIX={install_dir}", + f"-DMETATOMIC_CORE_SOURCE_DIR={METATOMIC_CORE_SRC}", + "-DCMAKE_INSTALL_LIBDIR=lib", + f"-DCMAKE_BUILD_TYPE={METATOMIC_BUILD_TYPE}", + f"-DMETATOMIC_CORE_PYTHON_USE_EXTERNAL_LIB={use_external_lib}", + f"-DCMAKE_PREFIX_PATH={metatensor.utils.cmake_prefix_path}", + ] + + if "CARGO" in os.environ: + cmake_options.append(f"-DCARGO_EXE={os.environ['CARGO']}") + + # Handle cross-compilation by detecting cibuildwheels environnement + # variables + if sys.platform.startswith("darwin"): + # ARCHFLAGS is set by cibuildwheels + ARCHFLAGS = os.environ.get("ARCHFLAGS") + if ARCHFLAGS is not None: + archs = filter( + lambda u: bool(u), + ARCHFLAGS.strip().split("-arch "), + ) + archs = list(archs) + assert len(archs) == 1 + arch = archs[0].strip() + + if arch == "x86_64": + cmake_options.append("-DRUST_BUILD_TARGET=x86_64-apple-darwin") + elif arch == "arm64": + cmake_options.append("-DRUST_BUILD_TARGET=aarch64-apple-darwin") + else: + raise ValueError(f"unknown arch: {arch}") + + elif sys.platform.startswith("linux"): + # we set RUST_BUILD_TARGET in our custom docker image + RUST_BUILD_TARGET = os.environ.get("RUST_BUILD_TARGET") + if RUST_BUILD_TARGET is not None: + cmake_options.append(f"-DRUST_BUILD_TARGET={RUST_BUILD_TARGET}") + + elif sys.platform.startswith("win32"): + # CARGO_BUILD_TARGET is set by cibuildwheels + CARGO_BUILD_TARGET = os.environ.get("CARGO_BUILD_TARGET") + if CARGO_BUILD_TARGET is not None: + cmake_options.append(f"-DRUST_BUILD_TARGET={CARGO_BUILD_TARGET}") + + else: + raise ValueError(f"unknown platform: {sys.platform}") + + subprocess.run( + ["cmake", source_dir, *cmake_options], + cwd=build_dir, + check=True, + ) + subprocess.run( + ["cmake", "--build", build_dir, "--parallel", "--target", "install"], + check=True, + ) + class bdist_egg_disabled(bdist_egg): """Disabled version of bdist_egg @@ -47,10 +150,58 @@ def run(self): with open("git_version_info", "w") as fd: fd.write(f"{n_commits}\n{git_hash}\n") + generate_cxx_tar() + # run original sdist super().run() os.unlink("git_version_info") + for path in glob.glob("metatomic-core-cxx-*.tar.gz"): + os.unlink(path) + + +def generate_cxx_tar(): + script = os.path.join(ROOT, "..", "..", "scripts", "package-core.sh") + assert os.path.exists(script) + + try: + output = subprocess.run( + ["bash", "--version"], + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + encoding="utf8", + ) + except Exception as e: + raise RuntimeError("could not run `bash`, is it installed?") from e + + output = subprocess.run( + ["bash", script, os.getcwd()], + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + encoding="utf8", + ) + if output.returncode != 0: + stderr = output.stderr + stdout = output.stdout + raise RuntimeError( + "failed to collect C++ sources for Python sdist\n" + f"stdout:\n {stdout}\n\nstderr:\n {stderr}" + ) + + +def get_rust_version(): + # read version from Cargo.toml + with open(os.path.join(METATOMIC_CORE_SRC, "Cargo.toml")) as fd: + for line in fd: + if line.startswith("version"): + _, version = line.split(" = ") + # remove quotes + version = version[1:-2] + # take the first version in the file, this should be the right + # version + break + + return version def git_version_info(): @@ -58,7 +209,7 @@ def git_version_info(): If git is available and we are building from a checkout, get the number of commits since the last tag & full hash of the code. Otherwise, this always returns (0, ""). """ - TAG_PREFIX = "metatomic-v" + TAG_PREFIX = "metatomic-core-v" if (ROOT / "git_version_info").exists(): # we are building from a sdist, without git available, but the git @@ -83,12 +234,16 @@ def git_version_info(): f"stdout: {output.stdout}\n" f"stderr: {output.stderr}\n" ) - elif output.stderr: + if output.stderr: print(output.stderr, file=sys.stderr) + + lines = output.stdout.splitlines() + if len(lines) < 2: + # the script gave up early (cf. `warn_and_exit`), and only printed + # the number of commits n_commits = 0 git_hash = "" else: - lines = output.stdout.splitlines() n_commits = int(lines[0].strip()) git_hash = lines[1].strip() @@ -124,6 +279,27 @@ def create_version_number(version): if __name__ == "__main__": + if not os.path.exists(METATOMIC_CORE_SRC): + # we are building from a sdist, which should include metatomic-core Rust + # sources as a tarball + tarballs = glob.glob(os.path.join(ROOT, "metatomic-core-*.tar.gz")) + + if not len(tarballs) == 1: + raise RuntimeError( + "expected a single 'metatomic-core-*.tar.gz' file containing " + "metatomic-core Rust sources. remove all files and re-run " + "scripts/package-core.sh" + ) + + METATOMIC_CORE_SRC = os.path.realpath(tarballs[0]) + subprocess.run( + ["cmake", "-E", "tar", "xf", METATOMIC_CORE_SRC], + cwd=ROOT, + check=True, + ) + + METATOMIC_CORE_SRC = ".".join(METATOMIC_CORE_SRC.split(".")[:-2]) + with open(ROOT / "AUTHORS") as fd: authors = fd.read().splitlines() @@ -137,11 +313,21 @@ def create_version_number(version): ] setup( - version=create_version_number(METATOMIC_CORE_VERSION), + version=create_version_number(get_rust_version()), author=", ".join(authors), + ext_modules=[Extension(name="metatomic", sources=[])], install_requires=install_requires, cmdclass={ + "build_ext": cmake_ext, "bdist_egg": bdist_egg if "bdist_egg" in sys.argv else bdist_egg_disabled, + "bdist_wheel": universal_wheel, "sdist": sdist_generate_data, }, + package_data={ + "metatomic-core": [ + "metatomic/lib/*", + "metatomic/include/*", + "metatomic/include/metatomic/*", + ] + }, ) diff --git a/python/metatomic_torch/setup.py b/python/metatomic_torch/setup.py index 58f8e3125..bbf11bd6f 100644 --- a/python/metatomic_torch/setup.py +++ b/python/metatomic_torch/setup.py @@ -200,12 +200,15 @@ def git_version_info(): f"stdout: {output.stdout}\n" f"stderr: {output.stderr}\n" ) - elif output.stderr: + if output.stderr: print(output.stderr, file=sys.stderr) + + lines = output.stdout.splitlines() + if len(lines) < 2: + # the script gave up early (cf. `warn_and_exit`) n_commits = 0 git_hash = "" else: - lines = output.stdout.splitlines() n_commits = int(lines[0].strip()) git_hash = lines[1].strip() diff --git a/python/metatomic_torchsim/setup.py b/python/metatomic_torchsim/setup.py index 913b2abd2..3d62963c8 100644 --- a/python/metatomic_torchsim/setup.py +++ b/python/metatomic_torchsim/setup.py @@ -62,12 +62,15 @@ def git_version_info(): f"stdout: {output.stdout}\n" f"stderr: {output.stderr}\n" ) - elif output.stderr: + if output.stderr: print(output.stderr, file=sys.stderr) + + lines = output.stdout.splitlines() + if len(lines) < 2: + # the script gave up early (cf. `warn_and_exit`) n_commits = 0 git_hash = "" else: - lines = output.stdout.splitlines() n_commits = int(lines[0].strip()) git_hash = lines[1].strip() diff --git a/python/scripts/gcc11-manylinux_2_28_aarch64/Dockerfile b/python/scripts/gcc11-manylinux_2_28_aarch64/Dockerfile deleted file mode 100644 index 3d22bae84..000000000 --- a/python/scripts/gcc11-manylinux_2_28_aarch64/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -# Use manylinux docker image as a base -FROM quay.io/pypa/manylinux_2_28_aarch64 - -# Install an older compiler. The default compiler (gcc-14) introduces calls to -# `__cxa_call_terminate` which is not available in ubuntu 22.04 libstdc++ -ARG DEVTOOLSET_VERSION=11 -RUN yum install -y gcc-toolset-${DEVTOOLSET_VERSION}-toolchain -ENV PATH=/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/bin:$PATH -ENV LD_LIBRARY_PATH=/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/lib64:/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/lib:$LD_LIBRARY_PATH diff --git a/python/scripts/gcc11-manylinux_2_28_x86_64/Dockerfile b/python/scripts/gcc11-manylinux_2_28_x86_64/Dockerfile deleted file mode 100644 index 5fe558f38..000000000 --- a/python/scripts/gcc11-manylinux_2_28_x86_64/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -# Use manylinux docker image as a base -FROM quay.io/pypa/manylinux_2_28_x86_64 - -# Install an older compiler. The default compiler (gcc-14) introduces calls to -# `__cxa_call_terminate` which is not available in ubuntu 22.04 libstdc++ -ARG DEVTOOLSET_VERSION=11 -RUN yum install -y gcc-toolset-${DEVTOOLSET_VERSION}-toolchain -ENV PATH=/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/bin:$PATH -ENV LD_LIBRARY_PATH=/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/lib64:/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/lib:$LD_LIBRARY_PATH diff --git a/python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile b/python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile new file mode 100644 index 000000000..9a62eb6ef --- /dev/null +++ b/python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile @@ -0,0 +1,18 @@ +# Use manylinux docker image as a base +FROM quay.io/pypa/manylinux_2_28_aarch64 + +RUN yum install git -y +RUN git config --global --add safe.directory /code + +# Download rustup-init asn install +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain 1.96 + +ENV PATH="/root/.cargo/bin:${PATH}" +ENV RUST_BUILD_TARGET="aarch64-unknown-linux-gnu" + +# Install an older C++ compiler. The default compiler (gcc-14) introduces calls +# to `__cxa_call_terminate` which is not available in ubuntu 22.04 libstdc++ +ARG DEVTOOLSET_VERSION=11 +RUN yum install -y gcc-toolset-${DEVTOOLSET_VERSION}-toolchain +ENV PATH=/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/bin:$PATH +ENV LD_LIBRARY_PATH=/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/lib64:/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/lib:$LD_LIBRARY_PATH diff --git a/python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile b/python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile new file mode 100644 index 000000000..59da62a1a --- /dev/null +++ b/python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile @@ -0,0 +1,18 @@ +# Use manylinux docker image as a base +FROM quay.io/pypa/manylinux_2_28_x86_64 + +RUN yum install git -y +RUN git config --global --add safe.directory /code + +# Download rustup-init asn install +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain 1.96 + +ENV PATH="/root/.cargo/bin:${PATH}" +ENV RUST_BUILD_TARGET="x86_64-unknown-linux-gnu" + +# Install an older C++ compiler. The default compiler (gcc-14) introduces calls +# to `__cxa_call_terminate` which is not available in ubuntu 22.04 libstdc++ +ARG DEVTOOLSET_VERSION=11 +RUN yum install -y gcc-toolset-${DEVTOOLSET_VERSION}-toolchain +ENV PATH=/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/bin:$PATH +ENV LD_LIBRARY_PATH=/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/lib64:/opt/rh/gcc-toolset-${DEVTOOLSET_VERSION}/root/usr/lib:$LD_LIBRARY_PATH diff --git a/scripts/git-version-info.py b/scripts/git-version-info.py index db7253223..87d384540 100755 --- a/scripts/git-version-info.py +++ b/scripts/git-version-info.py @@ -174,7 +174,14 @@ def git_hash_all_code(): git_env = os.environ.copy() git_env["GIT_INDEX_FILE"] = tmp.name - run_subprocess(["git", "add", "--all"], env=git_env, cwd=worktree) + # `core.safecrlf=false` since we are only staging files to compute a hash, + # and never write them back to the working tree: the end-of-line warnings + # git would emit here (on Windows) are only noise. + run_subprocess( + ["git", "-c", "core.safecrlf=false", "add", "--all"], + env=git_env, + cwd=worktree, + ) output = run_subprocess(["git", "write-tree"], env=git_env, cwd=worktree) short_hash = output.stdout[:7] diff --git a/scripts/package-core.sh b/scripts/package-core.sh new file mode 100755 index 000000000..6d66f5a24 --- /dev/null +++ b/scripts/package-core.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +# This script creates an archive containing the sources for the metatomic-core +# Rust crate, and copy it to the path given as argument + +set -eux + +OUTPUT_DIR="$1" +mkdir -p "$OUTPUT_DIR" +OUTPUT_DIR=$(cd "$OUTPUT_DIR" 2>/dev/null && pwd) + +ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd) + +rm -rf "$ROOT_DIR/target/package" +cd "$ROOT_DIR/metatomic-core" + +# print the version of cargo we use for debugging purposes. +cargo --version + +# Package metatomic-core using cargo tools, and add a file for +# `n_commits_since_last_tag` +cargo package --allow-dirty --no-verify + +TMP_DIR=$(mktemp -d) + +cd "$TMP_DIR" +tar xf "$ROOT_DIR"/target/package/metatomic-core-*.crate +ARCHIVE_NAME=$(ls) + +# extract the version part of the package from the .crate file name +VERSION=${ARCHIVE_NAME:15} +ARCHIVE_NAME="metatomic-core-cxx-$VERSION" + +mv metatomic-core-* "$ARCHIVE_NAME" +cp "$ROOT_DIR/LICENSE" "$TMP_DIR/$ARCHIVE_NAME" +cp "$ROOT_DIR/AUTHORS" "$TMP_DIR/$ARCHIVE_NAME" +cp "$ROOT_DIR/README.md" "$TMP_DIR/$ARCHIVE_NAME" + +# Get the git version information, this is used when building the +# code to change the version for development builds +cd "$ROOT_DIR" +./scripts/git-version-info.py "metatomic-core-v" > "$TMP_DIR/$ARCHIVE_NAME/cmake/git_version_info" + +cd "$TMP_DIR" +# Compile metatomic-core as it's own Cargo workspace (otherwise we can not the +# use metatomic rust crate in a project using workspaces). +echo "[workspace]" >> "$ARCHIVE_NAME/Cargo.toml" + +cargo generate-lockfile --manifest-path "$ARCHIVE_NAME/Cargo.toml" + +tar --dereference --create --file "$ARCHIVE_NAME.tar" "$ARCHIVE_NAME" +gzip -9 "$ARCHIVE_NAME.tar" + +cp "$TMP_DIR/$ARCHIVE_NAME.tar.gz" "$OUTPUT_DIR/" From 7064a519ffe98003029dcc1786eb821cc793a322 Mon Sep 17 00:00:00 2001 From: Johannes Spies <13813209+johannes-spies@users.noreply.github.com> Date: Thu, 3 Sep 2026 17:14:00 +0200 Subject: [PATCH 2/8] Update python/metatomic_core/setup.py Co-authored-by: Rocco Meli --- python/metatomic_core/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/metatomic_core/setup.py b/python/metatomic_core/setup.py index 9e9c3b1dd..7d83595cc 100644 --- a/python/metatomic_core/setup.py +++ b/python/metatomic_core/setup.py @@ -47,7 +47,7 @@ class cmake_ext(build_ext): def finalize_options(self): if self.editable_mode: raise RuntimeError( - "metatensor-core does not support editable installation yet" + "metatomic-core does not support editable installation yet" ) return super().finalize_options() From 700169f3bddc7bcfbce8f0e05233a743a1f5a56c Mon Sep 17 00:00:00 2001 From: Johannes Spies <13813209+johannes-spies@users.noreply.github.com> Date: Thu, 3 Sep 2026 17:14:16 +0200 Subject: [PATCH 3/8] Update scripts/package-core.sh Co-authored-by: Rocco Meli --- scripts/package-core.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/package-core.sh b/scripts/package-core.sh index 6d66f5a24..76cbc2f1d 100755 --- a/scripts/package-core.sh +++ b/scripts/package-core.sh @@ -42,8 +42,8 @@ cd "$ROOT_DIR" ./scripts/git-version-info.py "metatomic-core-v" > "$TMP_DIR/$ARCHIVE_NAME/cmake/git_version_info" cd "$TMP_DIR" -# Compile metatomic-core as it's own Cargo workspace (otherwise we can not the -# use metatomic rust crate in a project using workspaces). +# Compile metatomic-core as it's own Cargo workspace (otherwise we can not use +# the metatomic rust crate in a project using workspaces). echo "[workspace]" >> "$ARCHIVE_NAME/Cargo.toml" cargo generate-lockfile --manifest-path "$ARCHIVE_NAME/Cargo.toml" From 0bb4f951445543022d0535753390cd1cfaa594ac Mon Sep 17 00:00:00 2001 From: Johannes Spies <13813209+johannes-spies@users.noreply.github.com> Date: Thu, 3 Sep 2026 17:14:26 +0200 Subject: [PATCH 4/8] Update python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile Co-authored-by: Rocco Meli --- python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile b/python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile index 59da62a1a..41c34dbd3 100644 --- a/python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile +++ b/python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile @@ -4,7 +4,7 @@ FROM quay.io/pypa/manylinux_2_28_x86_64 RUN yum install git -y RUN git config --global --add safe.directory /code -# Download rustup-init asn install +# Download rustup-init and install RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain 1.96 ENV PATH="/root/.cargo/bin:${PATH}" From 0aa1897149f90b362858e74d1c68312358904105 Mon Sep 17 00:00:00 2001 From: Johannes Spies <13813209+johannes-spies@users.noreply.github.com> Date: Thu, 3 Sep 2026 17:14:36 +0200 Subject: [PATCH 5/8] Update python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile Co-authored-by: Rocco Meli --- python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile b/python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile index 9a62eb6ef..9bb10a49a 100644 --- a/python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile +++ b/python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile @@ -4,7 +4,7 @@ FROM quay.io/pypa/manylinux_2_28_aarch64 RUN yum install git -y RUN git config --global --add safe.directory /code -# Download rustup-init asn install +# Download rustup-init and install RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain 1.96 ENV PATH="/root/.cargo/bin:${PATH}" From 25d8f18df985e26e99310c3ea2f36d47d82c5331 Mon Sep 17 00:00:00 2001 From: Johannes Spies <13813209+johannes-spies@users.noreply.github.com> Date: Fri, 4 Sep 2026 00:37:15 +0200 Subject: [PATCH 6/8] Include as header-only library without metadata --- metatomic-core/CMakeLists.txt | 11 ----------- metatomic-core/cmake/nlohmann_json.cmake | 13 +++++++++---- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/metatomic-core/CMakeLists.txt b/metatomic-core/CMakeLists.txt index c80d7e658..0eb97f20f 100644 --- a/metatomic-core/CMakeLists.txt +++ b/metatomic-core/CMakeLists.txt @@ -461,14 +461,3 @@ install(FILES ${PROJECT_BINARY_DIR}/metatomic-config.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/metatomic ) - -if (NOT nlohmann_json_FOUND) - # nlohmann_json was fetched and vendored by us: install its headers (used - # by metatomic's own public headers), but remove the CMake package config - # and pkg-config files it installs, since we don't want to advertise a - # system-wide nlohmann_json package to external users. - install(CODE " - file(REMOVE_RECURSE \"\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/cmake/nlohmann_json\") - file(REMOVE \"\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/pkgconfig/nlohmann_json.pc\") - ") -endif() diff --git a/metatomic-core/cmake/nlohmann_json.cmake b/metatomic-core/cmake/nlohmann_json.cmake index 00934673b..58f8d1039 100644 --- a/metatomic-core/cmake/nlohmann_json.cmake +++ b/metatomic-core/cmake/nlohmann_json.cmake @@ -31,10 +31,15 @@ else() ) set(JSON_BuildTests OFF CACHE INTERNAL "") - # We need nlohmann_json's headers to be installed alongside metatomic's own - # (they are used in our public headers), but not its own CMake package - # config / pkg-config files, which we strip after install below. - set(JSON_Install ON CACHE INTERNAL "") + # Don't use nlohmann_json's own install rules, they would also install its + # CMake package config and pkg-config files, and we don't want to advertise + # a system-wide nlohmann_json package to external users. + set(JSON_Install OFF CACHE INTERNAL "") FetchContent_MakeAvailable(nlohmann_json) + + # nlohmann_json is header-only, so we can install the headers ourselves, + # alongside metatomic's own (they are used in our public headers). + install(DIRECTORY "${nlohmann_json_SOURCE_DIR}/include/nlohmann" + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) endif() From 522fdaad7ab722e5fd271c2c4f630c42ccad8919 Mon Sep 17 00:00:00 2001 From: Johannes Spies <13813209+johannes-spies@users.noreply.github.com> Date: Fri, 4 Sep 2026 00:47:55 +0200 Subject: [PATCH 7/8] Bump Python version to 3.11 and use tomllib --- .github/workflows/python-tests.yml | 6 +++--- .github/workflows/torch-tests.yml | 4 ++-- pyproject.toml | 2 +- python/metatomic_ase/pyproject.toml | 2 +- python/metatomic_core/pyproject.toml | 2 +- python/metatomic_core/setup.py | 15 ++++----------- python/metatomic_torch/pyproject.toml | 2 +- python/metatomic_torchsim/pyproject.toml | 2 +- 8 files changed, 14 insertions(+), 21 deletions(-) diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index f0368a45d..dfe22f5cd 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -18,14 +18,14 @@ jobs: matrix: include: - os: ubuntu-24.04 - python-version: "3.10" + python-version: "3.11" torch-version: "2.3" numpy-version-pin: "<2.0" - # Do not run docs-tests with python 3.10 since torch-sim-atomistic + # Do not run docs-tests with python 3.11 since torch-sim-atomistic # is not available for this version of python tox-envs: lint,torch-tests - os: ubuntu-24.04 - python-version: "3.10" + python-version: "3.11" torch-version: "2.13" # See above tox-envs: lint,torch-tests diff --git a/.github/workflows/torch-tests.yml b/.github/workflows/torch-tests.yml index cd9ba1528..21dd5d598 100644 --- a/.github/workflows/torch-tests.yml +++ b/.github/workflows/torch-tests.yml @@ -47,9 +47,9 @@ jobs: apt update apt install -y software-properties-common add-apt-repository ppa:deadsnakes/ppa - apt install -y cmake make gcc g++ git curl python3.10 python3.10-venv + apt install -y cmake make gcc g++ git curl python3.11 python3.11-venv - update-alternatives --install /usr/local/bin/python python /usr/bin/python3.10 1 + update-alternatives --install /usr/local/bin/python python /usr/bin/python3.11 1 - uses: actions/checkout@v7 with: diff --git a/pyproject.toml b/pyproject.toml index 2db00795e..31ffa78e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "metatomic" version = "0.1.0" dynamic = ["authors", "optional-dependencies"] -requires-python = ">=3.10" +requires-python = ">=3.11" readme = "README.md" license = "BSD-3-Clause" diff --git a/python/metatomic_ase/pyproject.toml b/python/metatomic_ase/pyproject.toml index 184462e69..1e83306b4 100644 --- a/python/metatomic_ase/pyproject.toml +++ b/python/metatomic_ase/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "metatomic-ase" dynamic = ["version", "authors", "dependencies"] -requires-python = ">=3.10" +requires-python = ">=3.11" readme = "README.md" license = "BSD-3-Clause" diff --git a/python/metatomic_core/pyproject.toml b/python/metatomic_core/pyproject.toml index b2320ca33..6f6725d58 100644 --- a/python/metatomic_core/pyproject.toml +++ b/python/metatomic_core/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "metatomic-core" dynamic = ["version", "authors", "dependencies"] -requires-python = ">=3.10" +requires-python = ">=3.11" # readme = "TODO" license = "BSD-3-Clause" diff --git a/python/metatomic_core/setup.py b/python/metatomic_core/setup.py index 7d83595cc..09fba7da8 100644 --- a/python/metatomic_core/setup.py +++ b/python/metatomic_core/setup.py @@ -3,6 +3,7 @@ import pathlib import subprocess import sys +import tomllib import packaging.version from setuptools import Extension, setup @@ -191,17 +192,9 @@ def generate_cxx_tar(): def get_rust_version(): # read version from Cargo.toml - with open(os.path.join(METATOMIC_CORE_SRC, "Cargo.toml")) as fd: - for line in fd: - if line.startswith("version"): - _, version = line.split(" = ") - # remove quotes - version = version[1:-2] - # take the first version in the file, this should be the right - # version - break - - return version + with open(os.path.join(METATOMIC_CORE_SRC, "Cargo.toml"), "rb") as fd: + cargo_toml = tomllib.load(fd) + return cargo_toml["package"]["version"] def git_version_info(): diff --git a/python/metatomic_torch/pyproject.toml b/python/metatomic_torch/pyproject.toml index a5ff0280a..1bfb2d679 100644 --- a/python/metatomic_torch/pyproject.toml +++ b/python/metatomic_torch/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "metatomic-torch" dynamic = ["version", "authors", "dependencies"] -requires-python = ">=3.10" +requires-python = ">=3.11" readme = "README.rst" license = "BSD-3-Clause" diff --git a/python/metatomic_torchsim/pyproject.toml b/python/metatomic_torchsim/pyproject.toml index 62c55dc3b..7dd83c12e 100644 --- a/python/metatomic_torchsim/pyproject.toml +++ b/python/metatomic_torchsim/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "metatomic-torchsim" dynamic = ["version", "authors", "dependencies"] -requires-python = ">=3.10" +requires-python = ">=3.11" readme = "README.md" license = "BSD-3-Clause" From 69b2af1dfa78ad8b759954a6f3d55a9b48cff12e Mon Sep 17 00:00:00 2001 From: Johannes Spies <13813209+johannes-spies@users.noreply.github.com> Date: Fri, 4 Sep 2026 00:58:21 +0200 Subject: [PATCH 8/8] Make Rust version ARG --- python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile | 3 ++- python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile b/python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile index 9bb10a49a..8aca91391 100644 --- a/python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile +++ b/python/scripts/rustc-manylinux_2_28_aarch64/Dockerfile @@ -5,7 +5,8 @@ RUN yum install git -y RUN git config --global --add safe.directory /code # Download rustup-init and install -RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain 1.96 +ARG RUST_TOOLCHAIN_VERSION=1.96 +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain ${RUST_TOOLCHAIN_VERSION} ENV PATH="/root/.cargo/bin:${PATH}" ENV RUST_BUILD_TARGET="aarch64-unknown-linux-gnu" diff --git a/python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile b/python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile index 41c34dbd3..22f7a1448 100644 --- a/python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile +++ b/python/scripts/rustc-manylinux_2_28_x86_64/Dockerfile @@ -5,7 +5,8 @@ RUN yum install git -y RUN git config --global --add safe.directory /code # Download rustup-init and install -RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain 1.96 +ARG RUST_TOOLCHAIN_VERSION=1.96 +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain ${RUST_TOOLCHAIN_VERSION} ENV PATH="/root/.cargo/bin:${PATH}" ENV RUST_BUILD_TARGET="x86_64-unknown-linux-gnu"