How to Build Linux ARM32 and Aarch64 Barcode QR Scanner in Docker Container

If you want to build and test barcode QR code scanner applications for embedded and IoT devices, such as Raspberry Pi, Arduino, Jetson Nano and so on, a physical device is not must-have for development. This article shows how to use Dynamsoft Barcode SDK to build barcode QR code reading applications for Linux ARM32 and Aarch64 (also called ARM64) in Docker container. The sample code is written in C++ and Python.

Docker Images for Running Linux ARM32 and Aarch64

Since there are many existing Docker images for Linux ARM32 and Aarch64, we do not need to build them from scratch. The arm32v7/gcc and arm64v8/gcc have provided a full GCC environment. We can use them as the base images.

docker pull arm32v7/gcc
docker pull arm64v8/gcc

multiarch/qemu-user-static is required for emulating ARM32 and Aarch64 instructions on x86_64 Linux.

docker run --rm --privileged multiarch/qemu-user-static:register --reset

C++ Barcode QR Code Scanner for Linux ARM32 and Aarch64

Get the C++ sample code developed with Dynamsoft Barcode SDK that supports Windows (x86_64), macOS(x86_64), and Linux(x86_64, ARM32, and ARM64).

git clone https://github.com/yushulx/cmake-cpp-barcode-qrcode.git

We mount the project folder to the Docker container rather than copy it to the container. It is convenient for later distribution.

docker run --platform linux/arm/v7 -it --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp arm32v7/gcc 

docker run --platform linux/arm64/v8 -it --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp arm64v8/gcc 

Then install cmake and build the project:

apt install -y cmake
mkdir build 
cmake -B build 
cmake --build build --config release 
cmake --install build

The executable file and the shared libraries will be copied to the dist folder after running the --install command. We can run the application by:

./dist/BarcodeReader ./images/AllSupportedBarcodeTypes.png ./license-key.txt

aarch64 barcode qrcode scanner

Get the 30-day trial license key and save it to the license-key.txt file.

Python Barcode QR Code Scanner for Linux ARM32 and Aarch64

Get the source code of the Python barcode QR code sample.

git clone https://github.com/yushulx/python-barcode-qrcode-sdk.git

The GCC Docker images have contained Python environment without pip.

We install pip firstly, and then install other required Python packages for building the wheel file inside the Docker container.

apt install python3-pip -y
pip3 install auditwheel patchelf-wrapper

Build the Python wheel file and repair it with auditwheel. Only the manylinux-supported wheel file can be uploaded to PyPI.

python3 setup_setuptools.py bdist_wheel
auditwheel repair wheelhouse/{*.whl} --plat manylinux2014_$(uname -m)

We can install and test the Python barcode QR code scanner SDK as follows:

pip3 install wheelhouse/{*.whl}
python3 test.py

GitHub Actions for Building Linux ARM32 and Aarch64 Barcode QR Code Scanner

GitHub Actions is a tool for automating the build and release of software. We can configure action workflow to build, test and distribute our Linux ARM32 and Aarch64 barcode QR code scanner applications.

GitHub Actions for Building CMake Project

We create two jobs: one for arm32 and one for arm64. The basic steps include:

  1. Clone the project from GitHub repository.
  2. Set up the QEMU user-static image.
  3. Run Docker container to build and test the project.
  4. Use zip tool to compress the dist folder.
  5. Make the package downloadable as an artifact file.

    GitHub build and download

name: CMake

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

env:
  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
  BUILD_TYPE: Release

jobs:
  arm32_build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3  
    
    - name: Set up QEMU
      uses: docker/setup-qemu-action@v2
        
    - name: CMake build and run
      run: |
        docker run --platform linux/arm/v7 --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp arm32v7/gcc bash -c "apt update && apt install -y cmake; mkdir build && cmake -B build && cmake --build build --config $ && cmake --install build; ./dist/BarcodeReader ./images/AllSupportedBarcodeTypes.png ./license-key.txt"
        
    - name: Archive Release
      uses: thedoctor0/zip-release@main
      with:
        type: 'zip'
        filename: arm32.zip
        exclusions: '*.git* /*node_modules/* .editorconfig'
        path: $/dist

    - uses: actions/upload-artifact@v2
      with:
        path: ./*.zip

  arm64_build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3  
    
    - name: Set up QEMU
      uses: docker/setup-qemu-action@v2
        
    - name: CMake build and run
      run: |
        docker run --platform linux/arm64/v8 --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp arm64v8/gcc bash -c "apt update && apt install -y cmake; mkdir build && cmake -B build && cmake --build build --config $ && cmake --install build; ./dist/BarcodeReader ./images/AllSupportedBarcodeTypes.png ./license-key.txt"
        
    - name: Archive Release
      uses: thedoctor0/zip-release@main
      with:
        type: 'zip'
        filename: arm64.zip
        exclusions: '*.git* /*node_modules/* .editorconfig'
        path: $/dist

    - uses: actions/upload-artifact@v2
      with:
        path: ./*.zip

GitHub Actions for Building Python Wheel

The cibuildwheel is the official tool to build Python wheel file. It supports manylinux2014 aarch64 Docker image.

Here we only build the aarch64 wheel file with cibuildwheel.

  1. Clone the project from GitHub repository.
  2. Set up the Python environment.
  3. Set up the QEMU user-static image.
  4. Build the Python wheel file with cibuildwheel in Docker container.
  5. Test the Python barcode QR code scanner SDK.
  6. Package all Python wheel files to artifact.
  7. Upload all Python wheel files to PyPI.

    upload python wheel to pypi

name: Build and upload to PyPI

on: [push, pull_request]

jobs:
  build_wheels:
    name: Build wheels on $
    runs-on: $
    strategy:
      matrix:
        os: [ubuntu-20.04]

    steps:
      - uses: actions/checkout@v2

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.x'
          
      - name: Set up QEMU
        if: runner.os == 'Linux'
        uses: docker/setup-qemu-action@v2
        with:
          platforms: all
      
      - name: Build wheels
        uses: pypa/cibuildwheel@v2.6.1
        env:
          CIBW_ARCHS_LINUX: aarch64 
      
      - name: Run test.py in develop mode
        run: |
          python setup_setuptools.py develop
          python -m pip install opencv-python
          python --version
          python test.py
      - uses: actions/upload-artifact@v2
        with:
          path: ./wheelhouse/*.whl

  build_sdist:
    name: Build source distribution
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Build sdist
        run: pipx run build --sdist

      - uses: actions/upload-artifact@v2
        with:
          path: dist/*.tar.gz
          
  upload_pypi:
    needs: [build_wheels, build_sdist]
    runs-on: ubuntu-latest
    # upload to PyPI on every tag starting with 'v'
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
    # alternatively, to publish when a GitHub Release is created, use the following rule:
    # if: github.event_name == 'release' && github.event.action == 'published'
    steps:
      - uses: actions/download-artifact@v2
        with:
          name: artifact
          path: dist

      - uses: pypa/gh-action-pypi-publish@v1.4.2
        with:
          user: __token__
          password: $
          skip_existing: true