diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 139e23bc3f..cfe47a1e53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,6 +131,7 @@ jobs: TENSORRT_PYTHON_BRANCH: auto L4T_APT_RELEASE: r39.2 JETSON_SOC_REPO: som + PIP_IGNORE_INSTALLED: "--ignore-installed" uses: docker/bake-action@v7 with: source: . diff --git a/docker/main/Dockerfile b/docker/main/Dockerfile index 5c34b3c3f4..636f716be3 100644 --- a/docker/main/Dockerfile +++ b/docker/main/Dockerfile @@ -12,6 +12,11 @@ ARG SLIM_BASE=debian:12-slim # A hook that allows us to inject commands right after the base images ARG BASE_HOOK= +# Extra flags for pip/get-pip. Empty for every stock image; set to --ignore-installed only for +# the JetPack 7 / Ubuntu 24.04 (noble) TensorRT base, whose distro pip/setuptools/wheel ship with +# no RECORD file and would otherwise abort get-pip/`pip install -U` with "uninstall-no-record-file". +ARG PIP_IGNORE_INSTALLED= + FROM ${BASE_IMAGE} AS base ARG PIP_BREAK_SYSTEM_PACKAGES ARG BASE_HOOK @@ -87,9 +92,7 @@ RUN apt-get -qq update \ && apt-get -qq install -y wget python3 python3-dev python3-distutils gcc pkg-config libhdf5-dev \ && wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \ && sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \ - # --ignore-installed: the Ubuntu 24.04 (noble) JP7 base ships a distro pip with no RECORD - # file, so get-pip.py's default reinstall dies with "uninstall-no-record-file". Harmless on JP6. - && python3 get-pip.py --ignore-installed "pip" \ + && python3 get-pip.py "pip" \ && pip3 install -r /requirements-ov.txt # Get OpenVino Model @@ -159,6 +162,7 @@ FROM base AS wheels ARG DEBIAN_FRONTEND ARG TARGETARCH ARG DEBUG=false +ARG PIP_IGNORE_INSTALLED # Use a separate container to build wheels to prevent build dependencies in final image RUN apt-get -qq update \ @@ -183,11 +187,9 @@ RUN apt-get -qq update \ RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1 -# --ignore-installed: the Ubuntu 24.04 (noble) JP7 base ships a distro pip with no RECORD file, -# so get-pip.py's default reinstall dies with "uninstall-no-record-file". Harmless on JP6. RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \ && sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \ - && python3 get-pip.py --ignore-installed "pip" + && python3 get-pip.py ${PIP_IGNORE_INSTALLED} "pip" COPY docker/main/requirements.txt /requirements.txt COPY docker/main/requirements-dev.txt /requirements-dev.txt @@ -226,6 +228,7 @@ COPY docker/main/rootfs/ / FROM slim-base AS deps ARG TARGETARCH ARG BASE_IMAGE +ARG PIP_IGNORE_INSTALLED ARG DEBIAN_FRONTEND # http://stackoverflow.com/questions/48162574/ddg#49462622 @@ -272,18 +275,12 @@ RUN --mount=type=bind,source=docker/main/install_deps.sh,target=/deps/install_de ENV DEFAULT_FFMPEG_VERSION="8.0" ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:7.0:5.0" -# --ignore-installed: the Ubuntu 24.04 (noble) JP7 base ships a distro pip with no RECORD file, -# so get-pip.py's default reinstall dies with "uninstall-no-record-file". Harmless on JP6. RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \ && sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \ - && python3 get-pip.py --ignore-installed "pip" + && python3 get-pip.py ${PIP_IGNORE_INSTALLED} "pip" -# --ignore-installed: on the Ubuntu 24.04 (noble) JP7 base, `pip3 install -U` tries to upgrade -# distro-managed packages (e.g. wheel 0.42.0) that ship without a RECORD file, which fails with -# "uninstall-no-record-file". Installing over them into /usr/local without uninstalling avoids -# that; harmless on JP6 where these come from pip and have RECORD files. RUN --mount=type=bind,from=wheels,source=/wheels,target=/deps/wheels \ - pip3 install -U --ignore-installed /deps/wheels/*.whl + pip3 install -U ${PIP_IGNORE_INSTALLED} /deps/wheels/*.whl # Install Axera Engine RUN pip3 install https://github.com/AXERA-TECH/pyaxengine/releases/download/0.1.3-frigate/axengine-0.1.3-py3-none-any.whl diff --git a/docker/tensorrt/detector/rootfs/etc/s6-overlay/s6-rc.d/trt-model-prepare/run b/docker/tensorrt/detector/rootfs/etc/s6-overlay/s6-rc.d/trt-model-prepare/run index 559c4d42c1..42397c1ca3 100755 --- a/docker/tensorrt/detector/rootfs/etc/s6-overlay/s6-rc.d/trt-model-prepare/run +++ b/docker/tensorrt/detector/rootfs/etc/s6-overlay/s6-rc.d/trt-model-prepare/run @@ -15,7 +15,7 @@ OUTPUT_FOLDER="${MODEL_CACHE_DIR}/${TRT_VER}" YOLO_MODELS=${YOLO_MODELS:-""} # Create output folder -mkdir -p "${OUTPUT_FOLDER}" +mkdir -p ${OUTPUT_FOLDER} FIRST_MODEL=true MODEL_DOWNLOAD="" @@ -29,9 +29,9 @@ fi for model in ${YOLO_MODELS//,/ } do # Remove old link in case path/version changed - rm -f "${MODEL_CACHE_DIR}/${model}.trt" + rm -f ${MODEL_CACHE_DIR}/${model}.trt - if [[ ! -f "${OUTPUT_FOLDER}/${model}.trt" ]]; then + if [[ ! -f ${OUTPUT_FOLDER}/${model}.trt ]]; then if [[ ${FIRST_MODEL} = true ]]; then MODEL_DOWNLOAD="${model%-dla}"; MODEL_CONVERT="${model}" @@ -41,7 +41,7 @@ do MODEL_CONVERT+=",${model}"; fi else - ln -s "${OUTPUT_FOLDER}/${model}.trt" "${MODEL_CACHE_DIR}/${model}.trt" + ln -s ${OUTPUT_FOLDER}/${model}.trt ${MODEL_CACHE_DIR}/${model}.trt fi done @@ -51,8 +51,8 @@ if [[ -z ${MODEL_CONVERT} ]]; then fi # Setup ENV to select GPU for conversion -if [ -n "${TRT_MODEL_PREP_DEVICE+x}" ]; then - if [ -n "${CUDA_VISIBLE_DEVICES+x}" ]; then +if [ ! -z ${TRT_MODEL_PREP_DEVICE+x} ]; then + if [ ! -z ${CUDA_VISIBLE_DEVICES+x} ]; then PREVIOUS_CVD="$CUDA_VISIBLE_DEVICES" unset CUDA_VISIBLE_DEVICES fi @@ -70,30 +70,20 @@ if [[ "$(arch)" == "aarch64" ]]; then exit 1 fi - TRT_LIB_DIR=/usr/lib/aarch64-linux-gnu - REQUIRED_TRT_LIBS=( - "${TRT_LIB_DIR}/libnvinfer.so.${TRT_MAJOR}" - "${TRT_LIB_DIR}/libnvinfer_plugin.so.${TRT_MAJOR}" - "${TRT_LIB_DIR}/libnvonnxparser.so.${TRT_MAJOR}" - ) - - if (( TRT_MAJOR < 10 )) || [[ -e "${TRT_LIB_DIR}/libnvparsers.so.${TRT_MAJOR}" ]]; then - REQUIRED_TRT_LIBS+=("${TRT_LIB_DIR}/libnvparsers.so.${TRT_MAJOR}") + # Library sonames are versioned by the TensorRT major (.so.8 on JP6, .so.10 on JP7). libnvparsers + # was removed in TensorRT 10, so only require it on older majors. + REQUIRED_TRT_LIBS=(libnvinfer libnvinfer_plugin libnvonnxparser) + if (( TRT_MAJOR < 10 )); then + REQUIRED_TRT_LIBS+=(libnvparsers) fi - MISSING_TRT_LIBS=() - for TRT_LIB in "${REQUIRED_TRT_LIBS[@]}"; do - if [[ ! -e "${TRT_LIB}" ]]; then - MISSING_TRT_LIBS+=("${TRT_LIB}") + for lib in "${REQUIRED_TRT_LIBS[@]}"; do + if [[ ! -e /usr/lib/aarch64-linux-gnu/${lib}.so.${TRT_MAJOR} ]]; then + echo "ERROR: Missing TensorRT ${TRT_MAJOR} runtime library ${lib}.so.${TRT_MAJOR}" + echo " Install the matching TensorRT ${TRT_MAJOR} runtime packages and nvidia-container on the HOST" + exit 1 fi done - - if (( ${#MISSING_TRT_LIBS[@]} > 0 )); then - echo "ERROR: Missing TensorRT runtime libraries:" - printf ' %s\n' "${MISSING_TRT_LIBS[@]}" - echo "ERROR: Install the matching TensorRT ${TRT_MAJOR} runtime packages and nvidia-container on the HOST." - exit 1 - fi fi echo "Generating the following TRT Models: ${MODEL_CONVERT}" @@ -102,33 +92,33 @@ echo "Generating the following TRT Models: ${MODEL_CONVERT}" cd /usr/local/src/tensorrt_demos/yolo echo "Downloading yolo weights" -./download_yolo.sh "${MODEL_DOWNLOAD}" 2> /dev/null +./download_yolo.sh $MODEL_DOWNLOAD 2> /dev/null for model in ${MODEL_CONVERT//,/ } do - python3 yolo_to_onnx.py -m "${model%-dla}" > /dev/null + python3 yolo_to_onnx.py -m ${model%-dla} > /dev/null echo -e "\nGenerating ${model}.trt. This may take a few minutes.\n"; start=$(date +%s) if [[ $model == *-dla ]]; then - cmd=(python3 onnx_to_tensorrt.py -m "${model%-dla}" --dla_core 0) + cmd="python3 onnx_to_tensorrt.py -m ${model%-dla} --dla_core 0" else - cmd=(python3 onnx_to_tensorrt.py -m "${model}") + cmd="python3 onnx_to_tensorrt.py -m ${model}" fi - "${cmd[@]}" > /tmp/onnx_to_tensorrt.log || { cat /tmp/onnx_to_tensorrt.log && continue; } + $cmd > /tmp/onnx_to_tensorrt.log || { cat /tmp/onnx_to_tensorrt.log && continue; } - mv "${model%-dla}.trt" "${OUTPUT_FOLDER}/${model}.trt"; - ln -s "${OUTPUT_FOLDER}/${model}.trt" "${MODEL_CACHE_DIR}/${model}.trt" + mv ${model%-dla}.trt ${OUTPUT_FOLDER}/${model}.trt; + ln -s ${OUTPUT_FOLDER}/${model}.trt ${MODEL_CACHE_DIR}/${model}.trt echo "Generated ${model}.trt in $(($(date +%s)-start)) seconds" done # Restore ENV after conversion -if [ -n "${TRT_MODEL_PREP_DEVICE+x}" ]; then +if [ ! -z ${TRT_MODEL_PREP_DEVICE+x} ]; then unset CUDA_VISIBLE_DEVICES - if [ -n "${PREVIOUS_CVD+x}" ]; then + if [ ! -z ${PREVIOUS_CVD+x} ]; then export CUDA_VISIBLE_DEVICES="$PREVIOUS_CVD" fi fi # Print which models exist in output folder echo "Available tensorrt models:" -cd "${OUTPUT_FOLDER}" && ls -- *.trt; +cd ${OUTPUT_FOLDER} && ls *.trt; diff --git a/docker/tensorrt/trt.hcl b/docker/tensorrt/trt.hcl index fb958feead..6ff9fec887 100644 --- a/docker/tensorrt/trt.hcl +++ b/docker/tensorrt/trt.hcl @@ -31,6 +31,9 @@ variable "L4T_APT_RELEASE" { variable "JETSON_SOC_REPO" { default = "" } +variable "PIP_IGNORE_INSTALLED" { + default = "" +} variable "BASE_HOOK" { # Ensure an up-to-date python 3.11 is available in jetson images default = <