Skip to main content

RPI4 Cross Compile for libcamera-app on Mac Pro (with docker) (2): Setup chroot

 

RPI4 Cross Compile for libcamera-app on Mac Pro (with docker) (2): Setup chroot

Why am I doing this

After reading the camera app instructions, I thought of starting the development by modifying the libcamera-apps. Therefore, the first step is to build the original repo; after that, I can add my stuff to the official standard version.

It looks easy. The code-building instructions are well-documented on the official website, but there is a catch in my mind. I bought an expensive, neat, and tidy Macbook Pro after quitting my job as a mind-comforting geek gadget to compensate for losing my working life, so I don't want to build the code on a small RPI board. Instead, I want to build the code and develop things on my new laptop, which is why I got into this over tons of unexpected things just popping up in my sight…

Preface

  1. Create a docker container where I can cross-compile the libcamera-apps.
    1. Setup chroot <-
    2. Setup toolchain
    3. Build libcamera-apps <-
  2. The docker container should include the development environment I like.
    1. Setup vim
  3. Develop and debug for the self-built libcamera-apps
  4. My GitHub repository

Goals for setup chroot

  • Look for environment information
  • Setup Dockerfile
  • Build Docker image
  • Start the Docker container and test the "sbuild-apt install"

Look for environment information

We can read [CrossCompiing from the Debian wiki] first to understand how the system setting works, and all my instruction is inspired by the [Earthly, A. Bhattacharyea]. Still, I did it in a docker environment instead of a clean Ubuntu system.
  1. Before the chroot setting, I checked the architecture and the release version on the RPI.

    # for architecture 
    pi@raspberrypi:~ $ dpkg --print-architecture
    arm64
    
    # for release
    pi@raspberrypi:~ $ cat /etc/os-release
    PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
    NAME="Debian GNU/Linux"
    VERSION_ID="11"
    VERSION="11 (bullseye)"
    VERSION_CODENAME=bullseye
    ID=debian
    HOME_URL="<https://www.debian.org/>"
    SUPPORT_URL="<https://www.debian.org/support>"
    BUG_REPORT_URL="<https://bugs.debian.org/>"
    
  2. Check the APT setting on the RPI

    pi@raspberrypi:~ $ sudo cat /etc/apt/sources.list
    deb <http://deb.debian.org/debian> bullseye main contrib non-free
    deb <http://security.debian.org/debian-security> bullseye-security main contrib non-free
    deb <http://deb.debian.org/debian> bullseye-updates main contrib non-free
    # Uncomment deb-src lines below then 'apt-get update' to enable 'apt-get source'
    #deb-src <http://deb.debian.org/debian> bullseye main contrib non-free
    #deb-src <http://security.debian.org/debian-security> bullseye-security main contrib non-free
    #deb-src <http://deb.debian.org/debian> bullseye-updates main contrib non-free
    

    However, the source.list does not show all the source we need, which lacks of http://archive.raspberrypi.org/debian. I found out this after I could not pull the libcamera-dev package (E: Unable to locate package libcamera-dev) for the sysroot later on, and it can be shown by using apt policy in the RPI board:

    pi@raspberrypi:~ $ apt policy libcamera-dev
    libcamera-dev:
      Installed: 0~git20230720+bde9b04f-1
      Candidate: 0~git20230720+bde9b04f-1
      Version table:
     *** 0~git20230720+bde9b04f-1 500
            500 <http://archive.raspberrypi.org/debian> bullseye/main arm64 Packages
            100 /var/lib/dpkg/status
    
  3. Find out the gpg key for the repositories above

Setup Dockerfile

  1. Put all the above information in a Dockerfile
    • Dockerfile [github link]

      # syntax=docker/dockerfile:1-labs
      FROM ubuntu:22.04
      ARG DEBIAN_FRONTEND=noninteractive
      RUN apt-get update
      
      # chroots setting -- install required packages
      RUN apt-get install wget -y
      
          # Note: the setting of localtime is to prevent from the interaction prompt when building mk-sbuild
      RUN ln -fs /usr/share/zoneinfo/Asia/Taipei /etc/localtime
      RUn apt-get install tzdata -y
      RUN apt-get install ubuntu-dev-tools cmake curl -y
      RUN apt-get install -y \\
                          pkg-config \\
                          libglib2.0-dev \\
                          libgtk2.0-dev \\
                          libtool \\
                          g++
      RUN apt-get install git -y
      RUN apt-get install vim -y
      RUN apt-get install libboost-all-dev -y
      RUN apt-get install zip -y
      RUN apt-get install gdb -y
      RUN apt-get install ssh -y
      RUN apt-get install -y gcc g++ gperf bison flex texinfo help2man make libncurses5-dev \\
          python3-dev autoconf automake libtool libtool-bin gawk wget bzip2 xz-utils unzip \\
          patch libstdc++6 rsync git meson ninja-build
      RUN apt-get install -y apt-utils autodep8 autopkgtest \\
          libemail-date-format-perl libfilesys-df-perl libmime-lite-perl \\
          libmime-types-perl libsbuild-perl schroot-common deborphan kmod sbuild
      
      # chroots setting -- set the default repository and gpg keyring for mk-sbuild
      RUN curl -sL <https://ftp-master.debian.org/keys/release-11.asc> | gpg --import -
      RUN gpg --export 605C66F00D6C9793 > $HOME/raspbian-archive-keyring.gpg
      RUN <<EOF cat >> $HOME/rpi.sources
      deb <http://deb.debian.org/debian> bullseye main contrib non-free
      deb <http://security.debian.org/debian-security> bullseye-security main contrib non-free
      deb <http://deb.debian.org/debian> bullseye-updates main contrib non-free
      deb <http://archive.raspberrypi.org/debian/> bullseye main
      # Uncomment deb-src lines below then 'apt-get update' to enable 'apt-get source'
      #deb-src <http://deb.debian.org/debian> bullseye main contrib non-free
      #deb-src <http://security.debian.org/debian-security> bullseye-security main contrib non-free
      #deb-src <http://deb.debian.org/debian> bullseye-updates main contrib non-free
      EOF
      RUN <<EOF cat >> $HOME/.mk-sbuild.rc
      SOURCE_CHROOTS_DIR="$HOME/sys/chroots"
      DEBOOTSTRAP_KEYRING="$HOME/raspbian-archive-keyring.gpg"
      TEMPLATE_SOURCES="$HOME/rpi.sources"
      SKIP_UPDATES="1"
      SKIP_PROPOSED="1"
      SKIP_SECURITY="1"
      EATMYDATA="1"
      EOF
      
      # build chroots - set user and the global environment 
      RUN usermod -a -G sbuild root
      RUN newgrp sbuild
      ENV ARCH=arm64
      ENV RELEASE=bullseye
      ENV TC=aarch64-rpi4-linux-gnu
      
      # build chroots - build
      RUN --security=insecure mk-sbuild --arch=$ARCH $RELEASE \\
          --debootstrap-mirror=http://deb.debian.org/debian/ \\
          --name=rpi-$RELEASE
      
      # build chroots - add <http://archive.raspberrypi.org> key in the previous built chroot 
      RUN --security=insecure sbuild-apt rpi-$RELEASE-$ARCH apt-get install curl
      RUN --security=insecure echo "curl -sL <http://archive.raspberrypi.org/debian/raspberrypi.gpg.key> | gpg --import -" | sbuild-shell rpi-$RELEASE-$ARCH
      RUN --security=insecure echo "gpg -a --export 82B129927FA3303E | apt-key add -" | sbuild-shell rpi-$RELEASE-$ARCH
      RUN --security=insecure sbuild-apt rpi-$RELEASE-$ARCH apt-get update
      COPY ./entrypoint.sh /entrypoint.sh
      
      ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
      
    • entrypoint.sh

      #!/bin/bash
      export PATH="/opt/x-tools/$TC/bin:$PATH"
      /bin/bash
      
    • Dockerfile explanation

      • The flow of the Dockerfile is:
        1. Install the packages that will be used later
        2. Set the default Debian repository and its GPG keyring for the mk-sbuild process
          • However, we have to install two keys. One is for http://deb.debian.org/debian and the other is for http://archive.raspberrypi.org/debian. Unfortunately, I did not find the instruction for adding two keys for the chroot building, so I came up with the workaround: manually adding the raspberry pi key after the first chroot build.
        3. Add the raspberry pi key by using sbuild-shell

Build Docker image

  1. Build the Docker image
    • Build docker images

      docker buildx create --use --name insecure-builder --buildkitd-flags '--allow-insecure-entitlement security.insecure'
      docker buildx build --allow security.insecure -t aarch64-rpi4-bullseye-cross-compiler-2204:v0.1.3 --load .
      
      • The commands of sbuild-apt, mk-sbuild, sbuild-shell are insecure when building the image, which mean that I cannot use the regular docker build command to build this image. Instead, the docker buildx can help to deal with our needs. The docker buildx create command will start a specific docker container for building docker images under this circumstance, in our usage, which is create a builder capable of building the Dockerfile with insecure commands.

      • For the insecure build, some lines should be put in the Dockerfile.

        • # syntax=docker/dockerfile:1-labs should be added in the first line
        • Add --security=insecure in front of each command with sbuild-apt, mk-sbuild, sbuild-shell
        • Example:
        RUN --security=insecure mk-sbuild --arch=$ARCH $RELEASE \\
            --debootstrap-mirror=http://deb.debian.org/debian/ \\
            --name=rpi-$RELEASE
        
      • Note: the below lines will be shown after a successful build

        I: Target architecture can be executed
        I: Retrieving InRelease
        I: Checking Release signature
        ...
        ...
        Done building rpi-bullseye-arm64.
        
         To CHANGE the golden image: sudo schroot -c source:rpi-bullseye-arm64 -u root
         To ENTER an image snapshot: schroot -c rpi-bullseye-arm64
         To BUILD within a snapshot: sbuild -A -d rpi-bullseye-arm64 PACKAGE*.dsc

Start the Docker container and test the "sbuild-apt install"

  1. Start the docker container and install packages to test the chroot

    1. Container running script

      #!/bin/bash
      _source=$SOURCE_CODE_DIR
      _docker_source=/root/main
      _test_source=$SOURCE_CODE_EXTRA_DATA_DIR
      _docker_test_source=/root/test_data
      
      _docker_image=aarch64-rpi4-bullseye-cross-compiler-2204:v0.1.3
      _docker_volume=docker_build_rpi
      _docker_volume_toolchain=rpi4-toolchain
      _docker_volume_crosstool_ng=crosstoll_ng
      
      docker run -it --rm \\
                 --privileged=true \\
                 --cap-add=SYS_ADMIN --security-opt apparmor:unconfined \\
                 -v $_docker_volume:/root/build \\
                 -v $_docker_volume_toolchain:/opt \\
                 -v $_docker_volume_crosstool_ng:/root/crosstool_ng \\
                 -v $_source:$_docker_source:delegated \\
                 -v $_test_source:$_docker_test_source:delegated \\
                 --net=host \\
                 $_docker_image bash
      
    2. Install libgmp-dev for testing http://deb.debian.org/debian

      root@docker-desktop:/ sbuild-apt rpi-$RELEASE-$ARCH apt-get install libgmp-dev
      I: apt-get -oAPT::Get::Assume-Yes=true install libgmp-dev
      Reading package lists... Done
      Building dependency tree... Done
      Reading state information... Done
      The following additional packages will be installed:
        libgmpxx4ldbl
      Suggested packages:
        gmp-doc libgmp10-doc libmpfr-dev
      The following NEW packages will be installed:
        libgmp-dev libgmpxx4ldbl
      0 upgraded, 2 newly installed, 0 to remove and 12 not upgraded.
      Need to get 962 kB of archives.
      After this operation, 2316 kB of additional disk space will be used.
      Get:1 <http://deb.debian.org/debian> bullseye/main arm64 libgmpxx4ldbl arm64 2:6.2.1+dfsg-1+deb11u1 [337 kB]
      Get:2 <http://deb.debian.org/debian> bullseye/main arm64 libgmp-dev arm64 2:6.2.1+dfsg-1+deb11u1 [625 kB]
      Fetched 962 kB in 1s (1440 kB/s)
      Selecting previously unselected package libgmpxx4ldbl:arm64.
      (Reading database ... 12914 files and directories currently installed.)
      Preparing to unpack .../libgmpxx4ldbl_2%3a6.2.1+dfsg-1+deb11u1_arm64.deb ...
      Unpacking libgmpxx4ldbl:arm64 (2:6.2.1+dfsg-1+deb11u1) ...
      Selecting previously unselected package libgmp-dev:arm64.
      Preparing to unpack .../libgmp-dev_2%3a6.2.1+dfsg-1+deb11u1_arm64.deb ...
      Unpacking libgmp-dev:arm64 (2:6.2.1+dfsg-1+deb11u1) ...
      Setting up libgmpxx4ldbl:arm64 (2:6.2.1+dfsg-1+deb11u1) ...
      Setting up libgmp-dev:arm64 (2:6.2.1+dfsg-1+deb11u1) ...
      Processing triggers for libc-bin (2.31-13+deb11u6) ...
      
    3. Install libcamera-dev for testing http://archive.raspberrypi.org/debian

      root@docker-desktop:/ sbuild-apt rpi-$RELEASE-$ARCH apt-get install libcamera-dev
      I: apt-get -oAPT::Get::Assume-Yes=true install libcamera-dev
      Reading package lists... Done
      Building dependency tree... Done
      Reading state information... Done
      The following additional packages will be installed:
        iso-codes libcamera0 libcap2 libcap2-bin libdw1 libelf1 libglib2.0-0 libgstreamer-plugins-base1.0-0 libgstreamer1.0-0 liborc-0.4-0 libunwind8 libyaml-0-2 raspberrypi-kernel
      Suggested packages:
        isoquery libvisual-0.4-plugins gstreamer1.0-tools
      Recommended packages:
        libpam-cap libglib2.0-data shared-mime-info xdg-user-dirs gstreamer1.0-plugins-base
      The following NEW packages will be installed:
        iso-codes libcamera-dev libcamera0 libcap2 libcap2-bin libdw1 libelf1 libglib2.0-0 libgstreamer-plugins-base1.0-0 libgstreamer1.0-0 liborc-0.4-0 libunwind8 libyaml-0-2 raspberrypi-kernel
      0 upgraded, 14 newly installed, 0 to remove and 12 not upgraded.
      Need to get 36.9 MB of archives.
      After this operation, 74.0 MB of additional disk space will be used.
      Get:1 <http://deb.debian.org/debian> bullseye/main arm64 iso-codes all 4.6.0-1 [2824 kB]
      ...
      Setting up libcap2:arm64 (1:2.44-1) ...
      Setting up libcap2-bin (1:2.44-1) ...
      Setting up liborc-0.4-0:arm64 (1:0.4.32-1) ...
      Setting up libelf1:arm64 (0.183-1) ...
      Setting up iso-codes (4.6.0-1) ...
      Setting up libdw1:arm64 (0.183-1) ...
      Setting up libgstreamer1.0-0:arm64 (1.18.4-2.1) ...
      Setcap worked! gst-ptp-helper is not suid!
      Setting up libgstreamer-plugins-base1.0-0:arm64 (1.18.4-2+deb11u1) ...
      Setting up libcamera0:arm64 (0~git20230720+bde9b04f-1) ...
      Setting up libcamera-dev:arm64 (0~git20230720+bde9b04f-1) ...
      Processing triggers for libc-bin (2.31-13+deb11u6) ...

Conclusion

Since we can install libgmp-dev and libcamera-dev in the chroot, the sysroot setup is done successfully, and next step is to build a toolchain for my M2 Macbook Pro.

    Comments

    Popular posts from this blog

    RPI4 Cross Compile for libcamera-app on Mac Pro (with docker) (4): Build libcamera-apps

      RPI4 Cross Compile for libcamera-app on Mac Pro (with docker) (4): Build libcamera-apps Why am I doing this After reading the  camera app instructions , I thought of starting the development by modifying the libcamera-apps. Therefore, the first step is to build the original repo; after that, I can add my stuff to the official standard version. It looks easy. The  code-building instructions  are well-documented on the official website, but there is a catch in my mind. I bought an expensive, neat, and tidy Macbook Pro after quitting my job as a mind-comforting geek gadget to compensate for losing my working life, so I don't want to build the code on a small RPI board. Instead, I want to build the code and develop things on my new laptop, which is why I got into this over tons of unexpected things just popping up in my sight… Preface Create a docker container where I can cross-compile the libcamera-apps. Setup chroot Setup toolchain Build libcamera-apps  <- The docker container s

    RPI camera → website → Chromecast → TV: (2) Streaming the video to TV

     RPI camera → website → Chromecast → TV: (2) Streaming the video to TV Why am I doing this? As an unemployed engineer, I need to find interesting things to fill my leisure time. I found there is a thing I can do to make my life more convenient to see the toys under my couch without in the crowing position of bending my knee and waist to find the toys which are "eaten by the couch," my kids said. Maybe I can use a camera on RPI to see the area under the couch and project the streaming video onto the TV by Chromecast. That is my initial thought. Devices An RPI4 A V2 camera My computer that I can run a server on. A Chromecast and TV Goal Streaming the video to TV From the previous post , I can stream camera data from RPI to my computer; this time, I need to project the camera data to my TV. There are many ways to send the video to TV. My initial thoughts are that if I can write a website to show videos, I can project the webpage using the browser's built-in button, and all t

    RPI camera → website → Chromecast → TV: (1) Capture video by RPI

     RPI camera → website → Chromecast → TV: (1) Capture video by RPI Why am I doing this? As an unemployed engineer, I need to find interesting things to fill my leisure time. I found there is a thing I can do to make my life more convenient to see the toys under my couch without in the crowing position of bending my knee and waist to find the toys which are “eaten by the couch,” my kids said. Maybe I can use a camera on RPI to see the area under the couch and project the streaming video onto the TV by Chromecast. That is my initial thought. Devices An RPI4 A V2 camera My computer that I can run a server on. A Chromecast and TV Goal Capture video by RPI libcamera-vid libcamera-vid is a built-in app for the RPI system. I found that the network streaming functionality can be enabled with libcamera-vid terminal command line, written in the official document . Thus, I can send the streamed video using the app by UDP, TCP, or RTSP. Benchmark setting The RPI camera captures the computer