Skip to content

Commit

Permalink
Add cannelloni/libsctp source code to archive
Browse files Browse the repository at this point in the history
  • Loading branch information
reimarstier committed Jun 27, 2024
1 parent 4eb733a commit e2d241f
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 89 deletions.
78 changes: 34 additions & 44 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,62 +1,52 @@
ARG DOCKCROSS_REGISTRY=docker.io/dockcross
ARG DOCKCROSS_IMAGE=linux-arm64
ARG DOCKCROSS_VERSION=latest

FROM dockcross/$DOCKCROSS_IMAGE:$DOCKCROSS_VERSION as cannelloni-builder
ARG VERSION=1.1.0
ARG HASH=0dcb9277b21f916f5646574b9b2229d3b8e97d5e99b935a4d0b7509a5f0ccdcd
FROM $DOCKCROSS_REGISTRY/$DOCKCROSS_IMAGE:$DOCKCROSS_VERSION as cannelloni-builder
# Version arguments that may be controlled via docker build argument
ARG CANNELLONI_VERSION=1.1.0
ARG CANNELLONI_HASH=0dcb9277b21f916f5646574b9b2229d3b8e97d5e99b935a4d0b7509a5f0ccdcd

# Output definitions
ENV TARGET_DIR=/tmp/cannelloni
ENV CANNELLONI_BUILD_LOG=$TARGET_DIR/build-metadata-log.txt
RUN mkdir $TARGET_DIR

# Document docker build log arguments
ARG DOCKCROSS_REGISTRY=docker.io/dockcross
ARG DOCKCROSS_IMAGE=linux-arm64
ARG DOCKCROSS_VERSION=latest
RUN echo -e "Built with $DOCKCROSS_REGISTRY/$DOCKCROSS_IMAGE:$DOCKCROSS_VERSION\n" | tee -a ${CANNELLONI_BUILD_LOG}

RUN mkdir /tmp/cannelloni

# Version definitions
ENV CANNELLONI_VERSION=$CANNELLONI_VERSION
ENV CANNELLONI_HASH=$CANNELLONI_HASH
ENV LIBSCTP_VERSION=1.0.19
WORKDIR /tmp/libsctp
# copy installed libraries to expected target location for cmake toolchain
COPY build_libsctp.sh /build_libsctp.sh
RUN /build_libsctp.sh
ENV LIBSCTP_HASH=9251b1368472fb55aaeafe4787131bdde4e96758f6170620bc75b638449cef01

WORKDIR /tmp/cannelloni
RUN wget https://github.com/mguentner/cannelloni/archive/refs/tags/v$VERSION.tar.gz -O cannelloni-$VERSION.tar.gz
RUN echo "$HASH cannelloni-$VERSION.tar.gz" | sha256sum --check --status
RUN tar --strip-components=1 -xvf cannelloni-$VERSION.tar.gz

# Document build metadata
RUN echo "Built with dockcross/$DOCKCROSS_IMAGE:$DOCKCROSS_VERSION\n" | tee -a /tmp/cannelloni/build-metadata.txt

RUN cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DSCTP_INCLUDE_DIR=/tmp/libsctp/src/include/netinet/ -DSCTP_LIBRARY=/tmp/libsctp/src/lib/.libs/ -DSCTP_SUPPORT=ON 2>&1 | tee -a /tmp/cannelloni/build-metadata.txt
RUN make 2>&1 | tee -a /tmp/cannelloni/build-metadata.txt
# Build libsctp
ENV CANNELLONI_BUILD_DIR=/tmp/cannelloni_build/
ENV LIBSCTP_BUILD_DIR=/tmp/libsctp_build/
WORKDIR $LIBSCTP_BUILD_DIR
COPY build_libsctp.sh /build_libsctp.sh
# https://github.com/docker/docs/blob/da4ccc81e6b1bbd585c9f5ac9a35b9c8684c5d57/content/build/building/best-practices.md#using-pipes
# If you want the command to fail due to an error at any stage in the pipe, prepend set -o pipefail && to ensure that an unexpected error prevents the build from inadvertently succeeding. For example:
RUN set -o pipefail && /build_libsctp.sh | tee -a ${CANNELLONI_BUILD_LOG}

COPY checklib.sh /checklib.sh
RUN /checklib.sh 2>&1 | tee -a /tmp/cannelloni/build-metadata.txt
# Build cannelloni
WORKDIR $CANNELLONI_BUILD_DIR
COPY build_cannelloni.sh /build_cannelloni.sh
RUN set -o pipefail && /build_cannelloni.sh | tee -a ${CANNELLONI_BUILD_LOG}

# Bundle result files: create tar file as output
WORKDIR /tmp/
RUN find $TARGET_DIR
RUN tar cf /tmp/cannelloni.tar.gz cannelloni/*

# rename libcannelloni in target directory
RUN cp --remove-destination /tmp/cannelloni/libcannelloni-common.so.0.0.1 /tmp/cannelloni/libcannelloni-common.so.0
RUN mv cannelloni/gpl-2.0.txt cannelloni/cannelloni-license-gpl-2.0.txt
# copy libsctp license to target directory
RUN curl https://raw.githubusercontent.com/sctp/lksctp-tools/master/COPYING.lib --output /tmp/cannelloni/libsctp-license.txt
# add note about source
RUN echo "You can find a copy of the cannelloni source code here: https://github.com/mguentner/cannelloni/archive/refs/tags/v$VERSION.tar.gz " > /tmp/cannelloni/SOURCES.md
RUN echo "You can find a copy of the libsctp source code here: https://github.com/sctp/lksctp-tools" >> /tmp/cannelloni/SOURCES.md

# create tar file as output
RUN tar cf /tmp/cannelloni.tar.gz \
cannelloni/SOURCES.md \
cannelloni/cannelloni cannelloni/libcannelloni-common.so.0 cannelloni/cannelloni-license-gpl-2.0.txt cannelloni/README.md \
cannelloni/build-metadata.txt \
cannelloni/libsctp-license.txt cannelloni/libsctp*.so*

# create directory as output
# RUN mkdir -p /cannelloni_${DOCKCROSS_IMAGE}_${VERSION}/
# RUN cp /tmp/cannelloni/libcannelloni-common.so.0 /tmp/cannelloni/cannelloni /tmp/cannelloni/README.md /tmp/cannelloni/gpl-2.0.txt /cannelloni_${DOCKCROSS_IMAGE}_${VERSION}/

# Separate build stage, all files in this stage are added to the final output
FROM scratch AS export-stage
ARG DOCKCROSS_IMAGE=linux-arm64
ARG VERSION=1.1.0

# copy tar file from builder
COPY --from=cannelloni-builder /tmp/cannelloni.tar.gz /cannelloni_${DOCKCROSS_IMAGE}_${VERSION}.tar.gz

# copy directory from builder
# COPY --from=cannelloni-builder /cannelloni_${DOCKCROSS_IMAGE}_${VERSION}/ /cannelloni_${DOCKCROSS_IMAGE}_${VERSION}/
37 changes: 24 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,44 @@ Uses [dockcross](https://github.com/dockcross/dockcross) to compile for the spec

## Build for multiple architectures

If building with podman, it requires at least version 4.1 (requires the output flag implemented [here](https://github.com/containers/buildah/pull/3823)).
Run `python build.py` to build for all architectures.

### Description of build workflow

The build workflow is run in docker containers (dockcross).
1. Build libsctp
* Build in temporary directory `LIBSCTP_BUILD_DIR=/tmp/libsctp_build/`
* Copy libraries and headers to cannelloni build directory `CANNELLONI_BUILD_DIR=/tmp/cannelloni_build/`
* Copy release artifacts to target directory `TARGET_DIR=/tmp/cannelloni`
* Add notes about source code origin to `${TARGET_DIR}/SOURCES.md`
2. Build cannelloni
* Build in temporary directory `CANNELLONI_BUILD_DIR=/tmp/cannelloni_build/`
* Copy release artifacts to `TARGET_DIR=/tmp/cannelloni`
* Add notes about source code origin to `${TARGET_DIR}/SOURCES.md`
3. Bundle files from `TARGET_DIR` into final release artifact.
4. Separate docker build stage is used to collect the final release artifact

## Install cannelloni

* Download appropriate architecture.
```shell
wget https://github.com/eclipse-opendut/cannelloni/releases/download/v1.1.0/cannelloni_linux-x64_1.1.0.tar.gz
tar xf cannelloni_linux-x64_1.1.0.tar.gz
```
* Install dependencies on Ubuntu/Debian
```shell
# libsctp1: user-space access to Linux kernel SCTP - shared library
apt-get install -y libsctp1
# can-utils: SocketCAN userspace utilities and tools
apt-get install -y can-utils
wget https://github.com/eclipse-opendut/cannelloni/releases/download/v1.1.0/cannelloni_linux-x64_1.1.0.tar.gz -O /tmp/cannelloni.tar.gz
cd /tmp
tar xf cannelloni.tar.gz
```
* The archive comes with a matching `libsctp` included.
* Extract archive on your target system and copy to system location:
```shell
cp cannelloni/libcannelloni-common.so.0 /lib/
cp cannelloni/cannelloni /usr/local/bin/
cannelloni # run cannelloni
```
* Or to custom library location:
* Or copy to custom location:
```shell
cp cannelloni/libcannelloni-common.so.0 /usr/local/lib/
cp cannelloni/cannelloni /usr/local/bin/
export LD_LIBRARY_PATH="/usr/local/lib/:$LD_LIBRARY_PATH"
sudo cp /tmp/cannelloni/ /opt/cannelloni
export LD_LIBRARY_PATH="/opt/cannelloni/:$LD_LIBRARY_PATH"
export PATH="/opt/cannelloni:$PATH"
cannelloni # run cannelloni
```

Expand Down
34 changes: 22 additions & 12 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,45 +14,52 @@ class BuildMetadata:

DEFAULT_VERSION = "1.1.0"
DEFAULT_HASH = "0dcb9277b21f916f5646574b9b2229d3b8e97d5e99b935a4d0b7509a5f0ccdcd"
DEFAULT_DOCKCROSS_REGISTRY = "docker.io/dockcross"
# Dockcross image names: https://github.com/dockcross/dockcross?tab=readme-ov-file#summary-cross-compilers
# Debian architectures: https://wiki.debian.org/SupportedArchitectures
BUILD_TARGETS = {
#"linux-x64": BuildMetadata(dockcross_image="linux-x64", dockcross_version="20240418-88c04a4"),
#"linux-armv6": BuildMetadata(dockcross_image="linux-armv6", dockcross_version="20240418-88c04a4"),
# "linux-x64": BuildMetadata(dockcross_image="linux-x64", dockcross_version="20240418-88c04a4"),
# "linux-armv6": BuildMetadata(dockcross_image="linux-armv6", dockcross_version="20240418-88c04a4"),
"linux-armv6-lts": BuildMetadata(dockcross_image="linux-armv6-lts", dockcross_version="20240418-88c04a4"),
#"linux-armv7": BuildMetadata(dockcross_image="linux-armv7", dockcross_version="20240418-88c04a4"),
# "linux-armv7": BuildMetadata(dockcross_image="linux-armv7", dockcross_version="20240418-88c04a4"),
"linux-armv7-lts": BuildMetadata(dockcross_image="linux-armv7-lts", dockcross_version="20240418-88c04a4"),
#"linux-arm64": BuildMetadata(dockcross_image="linux-arm64", dockcross_version="20240418-88c04a4"),
# "linux-arm64": BuildMetadata(dockcross_image="linux-arm64", dockcross_version="20240418-88c04a4"),
"linux-arm64-lts": BuildMetadata(dockcross_image="linux-arm64-lts", dockcross_version="20240418-88c04a4"),
"manylinux_2_28-x64": BuildMetadata(dockcross_image="manylinux_2_28-x64", dockcross_version="20240418-88c04a4"),
}


def build_cannelloni(build_metadata: BuildMetadata, build_version: str, build_hash: str):
def build_cannelloni(build_metadata: BuildMetadata, build_version: str, build_hash: str, no_build_cache: bool):
print(f"""
Build cannelloni for your architecture.
Dockcross image: dockcross/{build_metadata.dockcross_image}:{build_metadata.dockcross_version}
Dockcross image: {DEFAULT_DOCKCROSS_REGISTRY}/{build_metadata.dockcross_image}:{build_metadata.dockcross_version}
""")

cmd = f"""docker build
--build-arg VERSION={build_version}
--build-arg HASH={build_hash}
--build-arg CANNELLONI_VERSION={build_version}
--build-arg CANNELLONI_HASH={build_hash}
--build-arg DOCKCROSS_REGISTRY={DEFAULT_DOCKCROSS_REGISTRY}
--build-arg DOCKCROSS_IMAGE={build_metadata.dockcross_image}
--build-arg DOCKCROSS_VERSION={build_metadata.dockcross_version}
--output type=local,dest=out ."""

if no_build_cache:
print("Disabling docker build cache.")
cmd += " --no-cache"

my_env = os.environ.copy()
my_env["BUILDKIT_PROGRESS"] = "plain" # show progress output when building with docker
result = subprocess.run(cmd.split(), env=my_env)
if result.returncode != 0:
raise RuntimeError("Failed to build docker image for architecture={}".format(build_metadata.dockcross_image))


def show_version(build_metadata: BuildMetadata):
print(f"""
Dockcross image : dockcross/{build_metadata.dockcross_image}:{build_metadata.dockcross_version}""")
Dockcross image : {DEFAULT_DOCKCROSS_REGISTRY}/{build_metadata.dockcross_image}:{build_metadata.dockcross_version}""")

cmd = f"""docker run --entrypoint= --rm -v ./show_version.sh:/show_version.sh dockcross/{build_metadata.dockcross_image}:{build_metadata.dockcross_version} /show_version.sh""".split()
cmd = f"""docker run --entrypoint= --rm -v ./show_version.sh:/show_version.sh {DEFAULT_DOCKCROSS_REGISTRY}/{build_metadata.dockcross_image}:{build_metadata.dockcross_version} /show_version.sh""".split()
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode == 0:
print(result.stdout.decode().strip())
Expand All @@ -65,12 +72,15 @@ def show_version(build_metadata: BuildMetadata):
parser.add_argument('--architecture', help='Architecture to build.', choices=BUILD_TARGETS.keys(), required=False)
parser.add_argument('--version', help='Cannelloni release version to build.')
parser.add_argument('--hash', help='Cannelloni release hash to do integrity check.')
parser.add_argument('--show', help='Show toolchain versions of dockcross images.', required=False, action='store_true')
parser.add_argument('--show', help='Show toolchain versions of dockcross images.', required=False,
action='store_true')
parser.add_argument('--no-cache', help='Disable docker build cache.', required=False, action='store_true')
args = parser.parse_args()

given_architecture = args.architecture
build_version = args.version or DEFAULT_VERSION
build_hash = args.hash or DEFAULT_HASH
no_build_cache = args.no_cache

if given_architecture is None:
target_list = list(BUILD_TARGETS.keys())
Expand All @@ -83,4 +93,4 @@ def show_version(build_metadata: BuildMetadata):
if args.show:
show_version(metadata)
else:
build_cannelloni(metadata, build_version, build_hash)
build_cannelloni(metadata, build_version, build_hash, no_build_cache)
65 changes: 65 additions & 0 deletions build_cannelloni.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/bash
set -x
set -e

############################################
# CONFIG
############################################
# assumes to be run in a temporary directory
VERSION="${CANNELLONI_VERSION:-1.1.0}"
HASH="${CANNELLONI_HASH:-0dcb9277b21f916f5646574b9b2229d3b8e97d5e99b935a4d0b7509a5f0ccdcd}"
TARGET_DIR="${TARGET_DIR:-/tmp/cannelloni}"
DOWNLOAD_URL="https://github.com/mguentner/cannelloni/archive/refs/tags/v${VERSION}.tar.gz"

# Download source code
wget "$DOWNLOAD_URL" -O "cannelloni-$VERSION.tar.gz"
echo "$HASH cannelloni-$VERSION.tar.gz" | sha256sum --check --status

# Extract archive
tar --strip-components=1 -xvf "cannelloni-$VERSION.tar.gz"

# Check if libsctp is at the expected location
if [ ! -e "netinet/sctp.h" ]; then
echo "Could not find sctp header file! Aborting."
exit 1
fi
if [ ! -e "libsctp.so.1" ]; then
echo "Could not find sctp library file! Aborting."
exit 1
fi

############################################
# Build cannelloni
############################################
cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DSCTP_INCLUDE_DIR=./netinet/ -DSCTP_LIBRARY=./ -DSCTP_SUPPORT=ON 2>&1
make 2>&1

echo Finished building cannelloni

############################################
# COPY results to target directory
############################################
mkdir -p "${TARGET_DIR}/sources/"
cp --remove-destination libcannelloni-common.so.0.0.1 "${TARGET_DIR}"/libcannelloni-common.so.0
cp cannelloni "${TARGET_DIR}"/cannelloni
cp cannelloni-"$VERSION".tar.gz "${TARGET_DIR}"/sources/
mv gpl-2.0.txt "${TARGET_DIR}"/cannelloni-license-gpl-2.0.txt
echo "You can find a copy of the cannelloni source code attached to this archive." >> "${TARGET_DIR}/SOURCES.md"
echo "The cannelloni source code was downloaded from here: $DOWNLOAD_URL." >> "${TARGET_DIR}/SOURCES.md"

############################################
# CHECK result
############################################
# for other architectures than x86_64, copy libraries to this location for cmake toolchain
TARGET_XCC_DIR="$(ls -d /usr/xcc/*/*/sysroot/ 2>/dev/null || echo)"

if [ -n "$TARGET_XCC_DIR" ]; then
echo "Built with crosstool-ng"
"$TARGET_XCC_DIR"/usr/bin/ldd --version
echo -e "\nPrint shared object information on cannelloni library:"
readelf -h "${TARGET_DIR}"/cannelloni
else
echo "Not a cross build."
ldd --version
ldd "${TARGET_DIR}"/cannelloni
fi
43 changes: 39 additions & 4 deletions build_libsctp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,20 @@
set -x
set -e

############################################
# CONFIG
############################################
# assumes to be run in a temporary directory
# has outputs that are added to the build directory of cannelloni!

LIBSCTP_VERSION="${LIBSCTP_VERSION:-1.0.19}"
LIBSCTP_HASH="${LIBSCTP_HASH:-9251b1368472fb55aaeafe4787131bdde4e96758f6170620bc75b638449cef01}"
TARGET_DIR="${TARGET_DIR:-/tmp/target}"
CANNELLONI_BUILD_DIR="${CANNELLONI_BUILD_DIR:-/tmp/cannelloni_build}"
DOWNLOAD_URL="https://github.com/sctp/lksctp-tools/archive/refs/tags/v${LIBSCTP_VERSION}.tar.gz"

############################################
# Check if environment variable is present
if [ -z "$LIBSCTP_VERSION" ]; then
echo "No library version for libsctp specified! Set environment variable 'LIBSCTP_VERSION'!"
exit 1
Expand All @@ -16,12 +27,15 @@ TARGET_XCC_DIR="$(ls -d /usr/xcc/*/*/sysroot/)"
TARGET_TRIPLE="$(ls /usr/xcc/)"
set -e

wget https://github.com/sctp/lksctp-tools/archive/refs/tags/v"$LIBSCTP_VERSION".tar.gz -O libsctp-"$LIBSCTP_VERSION".tar.gz
wget "$DOWNLOAD_URL" -O libsctp-"$LIBSCTP_VERSION".tar.gz
echo "$LIBSCTP_HASH libsctp-$LIBSCTP_VERSION.tar.gz" | sha256sum --check --status

tar --strip-components=1 -xvf libsctp-"$LIBSCTP_VERSION".tar.gz
./bootstrap

############################################
# Build libsctp
############################################
# CFLAGS are set to "MinSizeRel"
export CFLAGS="-Os -DNDEBUG"
# CFLAGS are set to "Release"
Expand All @@ -37,14 +51,35 @@ make
find . -name "libsctp*"
find . -name "sctp.h"

# Copy library and its headers to a location where the compiler will find it
if [ -n "$TARGET_XCC_DIR" ]; then
cp ./src/include/netinet/sctp.h "$TARGET_XCC_DIR"/usr/include/netinet/
cp src/lib/.libs/libsctp.* "$TARGET_XCC_DIR"/usr/lib/
else
echo "Not a cross build. Nothing to do for current architecture: $ARCHITECTURE"
echo "Not a cross build. Architecture: $ARCHITECTURE"
cp ./src/include/netinet/sctp.h /usr/include/netinet/
cp src/lib/.libs/libsctp.* /usr/lib/
fi

cp -a ./src/include/netinet/ /tmp/cannelloni/
cp --no-dereference --preserve=links src/lib/.libs/libsctp.* /tmp/cannelloni/
############################################
# COPY results to cannelloni build directory
############################################
mkdir -p "${CANNELLONI_BUILD_DIR}"
# copy header files
cp -a ./src/include/netinet/ "${CANNELLONI_BUILD_DIR}"/
# copy object files
cp --no-dereference --preserve=links src/lib/.libs/libsctp.{a,so*} "${CANNELLONI_BUILD_DIR}"/

############################################
# COPY results to target directory
############################################
# copy source code
mkdir -p "${TARGET_DIR}/sources/"
cp libsctp-"$LIBSCTP_VERSION".tar.gz "${TARGET_DIR}/sources/"
# copy license
cp COPYING.lib "${TARGET_DIR}/libsctp-license.txt"
# copy library files
cp --no-dereference --preserve=links src/lib/.libs/libsctp.{a,so*} "${TARGET_DIR}"/

echo "You can find a copy of the libsctp source code attached to this archive." >> "${TARGET_DIR}/SOURCES.md"
echo "The libsctp source code was downloaded from here: $DOWNLOAD_URL" >> "${TARGET_DIR}/SOURCES.md"
Loading

0 comments on commit e2d241f

Please sign in to comment.