Skip to content

Commit

Permalink
Install recent cmake version for Python Backend build and automatical…
Browse files Browse the repository at this point in the history
…ly select GLIBC version for wheel name
  • Loading branch information
jkosek committed May 8, 2024
1 parent 627e7a9 commit b02911e
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 5 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ limitations under the License.

## unreleased
- Change: limited the `tritonclient` pacakge extras to http and grpc only
- Build scripts update
- upgrade cmake version during build
- automatically configure wheel name based on `glibc` version

## 0.5.5 (2024-04-15)

Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ dev = [
"nvidia-pytriton[doc]",
"build >= 0.8, <1.0.0", # to support --plat-name for multiarch build
"ipython >= 8.12", # Python 3.8 maximum for 24.02
"packaging ~= 24.0",
"pudb >= 2024.1",
"pip >= 24.0", # to support editable installation
"ruff >= 0.3.0",
"twine >= 5.0",

]

[build-system]
Expand Down
9 changes: 9 additions & 0 deletions scripts/Dockerfile.build
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ ENV PYTHON_VERSIONS=$PYTHON_VERSIONS
ARG MAKEFLAGS=""
ENV MAKEFLAGS=$MAKEFLAGS

# Latest cmake installation - https://apt.kitware.com
RUN apt-get update -y \
&& apt-get install ca-certificates gpg wget \
&& test -f /usr/share/doc/kitware-archive-keyring/copyright || wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null \
&& echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/kitware.list >/dev/null \
&& apt-get update -y \
&& test -f /usr/share/doc/kitware-archive-keyring/copyright || rm /usr/share/keyrings/kitware-archive-keyring.gpg \
&& apt-get install -y kitware-archive-keyring

RUN apt update -y && apt install -y build-essential \
cmake \
make \
Expand Down
12 changes: 8 additions & 4 deletions scripts/add_libs_to_wheel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ if [[ "$DOCKER_ARCH" == "amd64" ]]; then
elif [[ "$DOCKER_ARCH" == "arm64" ]]; then
WHEEL_ARCH=aarch64
fi
WHEEL_PLATFORM=manylinux_2_35_${WHEEL_ARCH}

DOCKER_CONTAINER_ID=$(docker create --rm --platform "${DOCKER_PLATFORM}" -w "${PWD}" "${PYTRITON_IMAGE_NAME}" bash -c "sleep 1h")
docker start "${DOCKER_CONTAINER_ID}"
Expand All @@ -42,9 +41,14 @@ docker exec "${DOCKER_CONTAINER_ID}" mkdir -p "$(dirname "${TRITON_LOCAL_DIR}")"
docker cp "${WHEEL_PATH}" "${DOCKER_CONTAINER_ID}:${WHEEL_PATH}"
docker cp "${TRITON_LOCAL_DIR}" "${DOCKER_CONTAINER_ID}:${TRITON_LOCAL_DIR}"

# The setuptools are necessary for Python 3.12
# pyproject.toml also contains the setuptools version so please update it accordingly
docker exec "${DOCKER_CONTAINER_ID}" pip install auditwheel==5.3.0 patchelf==0.17.2 setuptools==69.2.0
# The setuptools and packaging are necessary for Python 3.12
# pyproject.toml also contains the setuptools and packaging versions so please update it accordingly
docker exec "${DOCKER_CONTAINER_ID}" pip install auditwheel==5.3.0 patchelf==0.17.2 setuptools==69.2.0 packaging==24.0

docker cp "${SCRIPTS_DIR}/manylinux_version.py" "${DOCKER_CONTAINER_ID}:/tmp/"
MANYLINUX_VERSION=$(docker exec "${DOCKER_CONTAINER_ID}" bash -c "/tmp/manylinux_version.py --triton-path ${TRITON_LOCAL_DIR}")
WHEEL_PLATFORM=manylinux_${MANYLINUX_VERSION}_${WHEEL_ARCH}

docker cp "${SCRIPTS_DIR}/auditwheel_patched.py" "${DOCKER_CONTAINER_ID}:/tmp/"
docker exec "${DOCKER_CONTAINER_ID}" bash -c "LD_LIBRARY_PATH=${TRITON_LOCAL_DIR}/external_libs /tmp/auditwheel_patched.py -vvvv repair --plat ${WHEEL_PLATFORM} ${WHEEL_PATH}"

Expand Down
2 changes: 1 addition & 1 deletion scripts/auditwheel_patched.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

# Policies to ignore attaching Python libraries to wheel during fixing dependencies
for p in POLICIES:
for version in ["3.8", "3.9", "3.10", "3.11"]:
for version in ["3.8", "3.9", "3.10", "3.11", "3.12"]:
p["lib_whitelist"].append(f"libpython{version}.so.1.0")

if __name__ == "__main__":
Expand Down
89 changes: 89 additions & 0 deletions scripts/manylinux_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/usr/bin/env python3
# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Script that match the current GLIBC version with the manylinux options."""

import argparse
import logging
import pathlib
import subprocess
from typing import Set, Union

from packaging.version import parse

LOGGER = logging.getLogger("manylinux_version")

# Policy list for auditwheel: https://github.com/pypa/auditwheel/blob/main/src/auditwheel/policy/manylinux-policy.json
MANYLINUX_GLIBC_VERSIONS = ["2.5", "2.12", "2.17", "2.24", "2.27", "2.28", "2.31", "2.34", "2.35"]


def _glibc_library_version(file_path: Union[pathlib.Path, str]) -> Set[str]:
LOGGER.info(f"Collecting GLIBC version for {file_path}")
cmd = f"objdump -T {file_path} | grep GLIBC_ | sed 's/.*GLIBC_\\([.0-9]*\\).*/\\1/g' | sort -u"
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, _ = proc.communicate()
if stdout == b"\x01\n": # WAR for unrecognized character
LOGGER.info("GLIBC version not found.")
return set()

# Convert output and strip string
output = stdout.decode("utf-8").strip()
if not output:
LOGGER.info("GLIBC version not found.")
return set()

# Split versions string to list and update set
versions = set(output.splitlines())
LOGGER.info(f"Collected versions: {versions}")
return versions


def glibc_to_manylinux_version():
"""Find the minimal required GLIBC version supported by MANYLINUX version.
The script parse the libraries and binaries located in --triton-path catalog.
"""
argparser = argparse.ArgumentParser(add_help=False, allow_abbrev=False)
argparser.add_argument("--triton-path", type=pathlib.Path, required=True)

args = argparser.parse_args()

glibc_versions = set()
for file_path in args.triton_path.glob("**/*"):
# Filter unsupported files for
if file_path.is_dir() or (file_path.suffixes and ".so" not in file_path.suffixes):
continue

file_glibc_versions = _glibc_library_version(file_path)
glibc_versions.update(file_glibc_versions)

LOGGER.info(f"Collected GLIBC versions {glibc_versions}")

# Convert GLIBC and Manylinux version to semver supported comparison
glibc_version = max(map(parse, glibc_versions))
manylinux_glibc_versions = map(parse, MANYLINUX_GLIBC_VERSIONS)

# Obtain the smallest compatible version based version obtained from libraries
manylinux_glibc = min(filter(lambda i: i >= glibc_version, manylinux_glibc_versions))

# Convert to wheel name format
manylinux_version = str(manylinux_glibc).replace(".", "_")

LOGGER.info(f"Selected manylinux versions {manylinux_version}")
# Print output to collect value in shell
print(manylinux_version) # noqa: T201


if __name__ == "__main__":
glibc_to_manylinux_version()

0 comments on commit b02911e

Please sign in to comment.