diff --git a/.github/workflows/oot-dev-manual.yml b/.github/workflows/oot-dev-manual.yml new file mode 100644 index 0000000..678e5ff --- /dev/null +++ b/.github/workflows/oot-dev-manual.yml @@ -0,0 +1,42 @@ +name: OOT Dev Image - Manual Docker Hub Push +on: + workflow_dispatch: + inputs: + ubuntu_version: + description: 'Ubuntu Version' + required: true + default: 'jammy' + gr_version: + description: 'GR Version' + required: true + default: 3.10.5.1 + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push + id: docker_build + uses: docker/build-push-action@v2 + env: + IMG: ${{ secrets.DOCKERHUB_USERNAME }}/oot-dev + TAG: ${{ github.event.inputs.gr_version }}-ubuntu-${{ github.event.inputs.ubuntu_version }} + with: + push: true + file: docker/oot-dev.dockerfile + platforms: linux/amd64,linux/arm64 + build-args: | + dist=ubuntu:${{ github.event.inputs.ubuntu_version }} + gr_version=${{ github.event.inputs.gr_version }} + tags: ${{ env.IMG }}:${{ env.TAG }} + cache-from: type=registry,ref=${{ env.IMG }}:${{ env.TAG }} + cache-to: type=inline \ No newline at end of file diff --git a/.github/workflows/oot-dev-on-tag.yml b/.github/workflows/oot-dev-on-tag.yml new file mode 100644 index 0000000..359c71b --- /dev/null +++ b/.github/workflows/oot-dev-on-tag.yml @@ -0,0 +1,47 @@ +name: OOT Dev Image - Auto Docker Hub Push + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - ubuntu-version: jammy + gr-version: 3.10.5.1 + - ubuntu-version: focal + gr-version: 3.10.5.1 + - ubuntu-version: bionic + gr-version: 3.8.2 + - ubuntu-version: bionic + gr-version: 3.7.11 + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push + id: docker_build + uses: docker/build-push-action@v2 + env: + IMG: ${{ secrets.DOCKERHUB_USERNAME }}/oot-dev + TAG: ${{ matrix.gr-version }}-ubuntu-${{ matrix.ubuntu-version }} + with: + push: true + file: docker/oot-dev.dockerfile + platforms: linux/amd64,linux/arm64 + build-args: | + dist=ubuntu:${{ matrix.ubuntu-version }} + gr_version=${{ matrix.gr-version }} + tags: ${{ env.IMG }}:${{ env.TAG }} + cache-from: type=registry,ref=${{ env.IMG }}:${{ env.TAG }} + cache-to: type=inline \ No newline at end of file diff --git a/README.md b/README.md index 480c8cd..e551416 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,176 @@ This repository contains a range of GNU Radio-related Docker images. +- [GNU Radio Docker Images](#gnu-radio-docker-images) + - [CI Builders](#ci-builders) + - [OOT Development Environment](#oot-development-environment) + - [Base Image for OOT Module](#base-image-for-oot-module) + - [Multiple GNU Radio Versions in Parallel](#multiple-gnu-radio-versions-in-parallel) + - [OOT Development Inside Container](#oot-development-inside-container) + - [Github Workflows](#github-workflows) + - [VSCode Devcontainer](#vscode-devcontainer) + + ## CI Builders The CI builders are the base images used on CI jobs, such as the workflows used in the [gnuradio/gnuradio](https://github.com/gnuradio/gnuradio/tree/main/.github/workflows) project to run tests and build packages. +## OOT Development Environment + +The `oot-dev` image provides a container environment for building, testing, and running GNU Radio out-of-tree (OOT) modules. The following examples demonstrate a few use cases for this image: + +### Base Image for OOT Module + +The `oot-dev` image can serve as the base image when building a dedicated image for an OOT module. For example, consider the following Dockerfile: + +```Dockerfile +ARG tag=3.10.3-ubuntu-focal +FROM gnuradio/oot-dev:$tag +# List of dependencies for your GR OOT module. +ARG deps +# OOT repository URL and name: +ARG oot_url +ARG oot_name +# Install dependencies +RUN apt-get install -y $deps +# Install the OOT module +RUN git clone --recursive $oot_url && \ + cd $oot_name && mkdir build && cd build/ && \ + cmake .. && \ + cmake --build . && \ + cmake --install . && \ + ldconfig && \ + cd ../../ && rm -r $oot_name +``` + +Suppose the above Dockerfile is saved on a file named `oot.dockerfile`. In this case, for example, to build an image for the [gr-dvbs2rx project](https://github.com/igorauad/gr-dvbs2rx/), run: + +```bash +docker build -f oot.dockerfile -t gr-dvbs2rx \ + --build-arg tag=3.10.5.1-ubuntu-jammy \ + --build-arg deps="libusb-1.0-0-dev libosmosdr-dev libsndfile1-dev" \ + --build-arg oot_url=https://github.com/igorauad/gr-dvbs2rx/ \ + --build-arg oot_name=gr-dvbs2rx \ + . +``` + +For a more advanced use case, refer to the actual [Dockerfile](https://github.com/igorauad/gr-dvbs2rx/blob/master/Dockerfile) used on the gr-dvbs2rx project. + +### Multiple GNU Radio Versions in Parallel + +The `oot-dev` image can be a convenient solution for running multiple GNU Radio versions in parallel on reproducible environments. For example, you can launch multiple containers with different GNU Radio +versions, as follows: + +```bash +docker run --name gr3.8 gnuradio/oot-dev:3.8.2-ubuntu-bionic +``` + +```bash +docker run --name gr3.9 gnuradio/oot-dev:3.9.4-ubuntu-focal +``` + +```bash +docker run --name gr3.10 gnuradio/oot-dev:3.10.5.1-ubuntu-jammy +``` + +If you would like to run GUI applications inside these containers, such as `gnuradio-companion`, consider defining aliases like so: + +Linux +```bash +alias docker-gui='docker run --env="DISPLAY" -v $HOME/.Xauthority:/root/.Xauthority --network=host' +``` + +OSX +```bash +alias docker-gui='docker run --env="DISPLAY=host.docker.internal:0"' +``` + +Then, run `docker-gui` instead of `docker run`. Also, in the case of OSX, you also need to authorize the container to access the host's X server: + +```bash +xhost + localhost +``` + +### OOT Development Inside Container + +The `oot-dev` image can be convenient for OOT development in general. For example, you can keep the OOT sources on the host while developing, building, and installing binaries inside the container. To do so, you can extend the commands explained in the previous section by adding a [bind mount option](https://docs.docker.com/engine/reference/run/#volume-shared-filesystems). Assuming you have the OOT sources in your host at `$HOME/src/my-oot/`, you can run the container as follows: + +```bash +docker run --rm -it \ + -v $HOME/src/my-oot/:/src/my-oot/ \ + gnuradio/oot-dev:3.10.5.1-ubuntu-jammy +``` + +Option `-v $HOME/src/my-oot/:/src/my-oot/` creates a bind-mount at `/src/my-oot/` inside the container, which you can use to access the OOT files. Any changes made in this directory are automatically reflected back to the host. For example, inside the container, build the OOT as follows: + +```bash +cd /src/my-oot/ +mkdir -p build/ +cmake .. +make +``` + +### Github Workflows + +The `oot-dev` image is also useful for setting up Github workflows on your OOT module's repository, such as the following workflow: + +```yml +name: Test +on: [push, pull_request] +env: + BUILD_TYPE: Release +jobs: + build: + runs-on: ubuntu-latest + container: + image: gnuradio/oot-dev:3.10.5.1-ubuntu-jammy + steps: + - uses: actions/checkout@v2 + - name: Configure CMake + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + - name: Test + run: cd ${{github.workspace}}/build && ctest -C ${{env.BUILD_TYPE}} -VV +``` + +For reference, refer to the workflow used on [gr-dvbs2rx](https://github.com/igorauad/gr-dvbs2rx/blob/master/.github/workflows/test.yml). + +### VSCode Devcontainer + +Finally, the `oot-dev` image also facilitates OOT development inside [devcontainers on VSCode](https://code.visualstudio.com/docs/remote/containers). All you need to do is install the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension, create a `.devcontainer/devcontainer.json` file in your project, and reopen the workspace inside the container. The `devcontainer.json` file should specify the image as follows: + +```json +{ + "image": "gnuradio/oot-dev:tag" +} +``` + +where `tag` should be replaced by one of the [available tags](https://hub.docker.com/r/gnuradio/oot-dev/tags). + +Furthermore, if you would like to run GUI applications (e.g., `gnuradio-companion`) directly from the VSCode terminal, you can append the following to your `devcontainer.json` file: +Linux +```json +{ + ... + "runArgs": [ + "-v $HOME/.Xauthority:/root/.Xauthority", + "--network=host" + ], + "containerEnv": { + "DISPLAY": "$DISPLAY" + } +} +``` +OSX +```json +{ + ... + "containerEnv": { + "DISPLAY": "host.docker.internal:0" + } +} +``` diff --git a/docker/oot-dev.dockerfile b/docker/oot-dev.dockerfile new file mode 100644 index 0000000..2a23e21 --- /dev/null +++ b/docker/oot-dev.dockerfile @@ -0,0 +1,33 @@ +ARG dist=ubuntu:focal +FROM $dist +ARG gr_version=3.10.1 +RUN apt update && apt install -y software-properties-common +RUN add-apt-repository ppa:gnuradio/gnuradio-releases && \ + apt update && \ + DEBIAN_FRONTEND="noninteractive" apt install -y \ + clang-format \ + cmake \ + doxygen \ + gdb \ + gir1.2-gtk-3.0 \ + git \ + gnuradio=$gr_version* \ + gnuradio-dev=$gr_version* \ + graphviz \ + libspdlog-dev \ + pkg-config \ + python3-pip \ + swig +RUN pip3 install pygccxml +# Configure the paths required to run GR over python2 and python3 +RUN if command -v python2 ; then \ + PYSITEDIR=$(python2 -m site --user-site) && \ + PYLIBDIR=$(python2 -c "from distutils import sysconfig; \ + print(sysconfig.get_python_lib(plat_specific=False, prefix='/usr/local'))") && \ + mkdir -p "$PYSITEDIR" && \ + echo "$PYLIBDIR" > "$PYSITEDIR/gnuradio.pth" ; fi +RUN PYSITEDIR=$(python3 -m site --user-site) && \ + PYLIBDIR=$(python3 -c "from distutils import sysconfig; \ + print(sysconfig.get_python_lib(plat_specific=False, prefix='/usr/local'))") && \ + mkdir -p "$PYSITEDIR" && \ + echo "$PYLIBDIR" > "$PYSITEDIR/gnuradio.pth"