From 7ff90bfbdbfeb94560f2ccd97104b0593fad8595 Mon Sep 17 00:00:00 2001 From: Fangjun Kuang Date: Wed, 8 Jul 2026 17:35:54 +0800 Subject: [PATCH] Build docker image to setup the QNN SDK environment --- .github/scripts/export-qnn/Dockerfile-2.40 | 110 ++++++++++++++++++++ .github/workflows/qnn-sdk-docker-build.yaml | 46 ++++++++ .github/workflows/test-qnn-sdk-docker.yaml | 70 +++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 .github/scripts/export-qnn/Dockerfile-2.40 create mode 100644 .github/workflows/qnn-sdk-docker-build.yaml create mode 100644 .github/workflows/test-qnn-sdk-docker.yaml diff --git a/.github/scripts/export-qnn/Dockerfile-2.40 b/.github/scripts/export-qnn/Dockerfile-2.40 new file mode 100644 index 0000000000..50535ec8c3 --- /dev/null +++ b/.github/scripts/export-qnn/Dockerfile-2.40 @@ -0,0 +1,110 @@ +FROM ubuntu:22.04 + +ARG QNN_SDK_VERSION=2.40.0.251030 +ARG QNN_TOOLKIT_URL=https://huggingface.co/csukuangfj/qnn-toolkit/resolve/main/v${QNN_SDK_VERSION}.zip + +ENV DEBIAN_FRONTEND=noninteractive + +# Use bash as default shell (envsetup.sh requires bash syntax) +SHELL ["/bin/bash", "-c"] + +# Install basic system dependencies (Ubuntu 22.04 ships Python 3.10 natively) +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + unzip \ + software-properties-common \ + lsb-release \ + adb \ + clang \ + libc++-dev \ + libc++abi-dev \ + libclang-dev \ + libsndfile1 \ + python3 \ + python3-pip \ + python3-venv \ + python3-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install Android NDK r29 (placed early so failures surface quickly) +ARG ANDROID_NDK_VERSION=29.0.14206865 +ARG ANDROID_NDK_REVISION=r29 +RUN curl -SL -o /tmp/ndk.zip https://dl.google.com/android/repository/android-ndk-${ANDROID_NDK_REVISION}-linux.zip \ + && unzip -q /tmp/ndk.zip -d /opt \ + && rm -f /tmp/ndk.zip +ENV ANDROID_NDK_LATEST_HOME=/opt/android-ndk-${ANDROID_NDK_REVISION} +ENV PATH=${ANDROID_NDK_LATEST_HOME}:${PATH} + +# Verify NDK is set up correctly +RUN ndk-build --help + +# Download, install QNN SDK toolkit, then remove the zip in the same layer +WORKDIR /opt +RUN curl -SL -O ${QNN_TOOLKIT_URL} \ + && unzip v${QNN_SDK_VERSION}.zip \ + && rm -f v${QNN_SDK_VERSION}.zip + +# Set QNN SDK environment variables +ENV QNN_SDK_ROOT=/opt/qairt/${QNN_SDK_VERSION} +ENV PATH=${QNN_SDK_ROOT}/bin/x86_64-linux-clang:${QNN_SDK_ROOT}/bin:${PATH} +ENV LD_LIBRARY_PATH=${QNN_SDK_ROOT}/lib/x86_64-linux-clang:${LD_LIBRARY_PATH} + +# Install linux dependencies required by QNN SDK (source envsetup.sh first, matching workflow) +RUN cd ${QNN_SDK_ROOT}/bin && . envsetup.sh \ + && yes | ${QNN_SDK_ROOT}/bin/check-linux-dependency.sh || true \ + && rm -rf /var/lib/apt/lists/* + +# Create and activate a Python 3.10 virtual environment +RUN python3 -m venv /opt/py310 +ENV VIRTUAL_ENV=/opt/py310 +ENV PATH=/opt/py310/bin:${PATH} + +# Install all Python dependencies in a single layer to minimize image size +# The virtual environment is already active via ENV PATH above +RUN . /opt/py310/bin/activate && \ + pip install --no-cache-dir --upgrade pip && \ + pip install --no-cache-dir \ + mock \ + numpy \ + opencv-python \ + optuna \ + packaging \ + pandas \ + paramiko \ + pathlib2 \ + pillow \ + plotly \ + protobuf \ + psutil \ + pydantic \ + pytest \ + pyyaml \ + rich \ + scikit-optimize \ + scipy \ + six \ + tabulate \ + typing-extensions \ + xlsxwriter \ + && python3 "${QNN_SDK_ROOT}/bin/check-python-dependency" || true \ + && pip install --no-cache-dir \ + torch==2.0.0+cpu -f https://download.pytorch.org/whl/torch \ + kaldi_native_fbank \ + "numpy<2" \ + onnx==1.17.0 \ + onnxruntime \ + soundfile \ + librosa \ + onnxsim \ + sentencepiece \ + pyyaml \ + && pip cache purge 2>/dev/null || true + +# Verify QNN tools are accessible (source envsetup.sh first, matching workflow) +RUN cd ${QNN_SDK_ROOT}/bin && . envsetup.sh \ + && qnn-onnx-converter --help \ + && qnn-model-lib-generator --help \ + && qnn-net-run --help + +WORKDIR /workspace diff --git a/.github/workflows/qnn-sdk-docker-build.yaml b/.github/workflows/qnn-sdk-docker-build.yaml new file mode 100644 index 0000000000..af99b98861 --- /dev/null +++ b/.github/workflows/qnn-sdk-docker-build.yaml @@ -0,0 +1,46 @@ +name: Build docker image for qnn SDK + +on: + push: + branches: + - docker-qnn-2 + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Buildx is required for cache + multi-platform correctness + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build + env: + HF_TOKEN: ${{ secrets.HF_TOKEN }} + uses: docker/build-push-action@v5 + with: + context: ./.github/scripts/export-qnn + file: ./.github/scripts/export-qnn/Dockerfile-2.40 + platforms: linux/amd64 + push: true + tags: | + ghcr.io/${{ github.repository_owner }}/qnn-sdk:2.40 + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/test-qnn-sdk-docker.yaml b/.github/workflows/test-qnn-sdk-docker.yaml new file mode 100644 index 0000000000..194a065fba --- /dev/null +++ b/.github/workflows/test-qnn-sdk-docker.yaml @@ -0,0 +1,70 @@ +name: test-qnn-sdk-docker + +on: + push: + branches: + - docker-qnn + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + container: + image: ghcr.io/${{ github.repository_owner }}/qnn-sdk:2.40 + + steps: + - uses: actions/checkout@v4 + + - name: Show system information + shell: bash + run: | + df -h + + pwd + id + cat /etc/*version + ls -lh + + - name: Show Python version + shell: bash + run: | + python3 --version + which python3 + + - name: Show environment variables + shell: bash + run: | + echo "ANDROID_NDK_LATEST_HOME: $ANDROID_NDK_LATEST_HOME" + echo "PATH: $PATH" + echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH" + echo "QNN_SDK_ROOT: $QNN_SDK_ROOT" + + - name: qnn-onnx-converter show help + shell: bash + run: | + pushd $QNN_SDK_ROOT/bin + source envsetup.sh + popd + + which qnn-onnx-converter + qnn-onnx-converter --help + + - name: qnn-model-lib-generator help + shell: bash + run: | + pushd $QNN_SDK_ROOT/bin + source envsetup.sh + popd + + which qnn-model-lib-generator + echo "qnn-model-lib-generator --help" + + - name: qnn-net-run help + shell: bash + run: | + pushd $QNN_SDK_ROOT/bin + source envsetup.sh + popd + + which qnn-net-run + qnn-net-run --help