diff --git a/.dockcross-arm64 b/.dockcross-arm64 new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore index 78e9e2f..dd5bfda 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,8 @@ Makefile # Executables simple_object_storage -sos +simple_object_storage-x86_64 +simple_object_storage-arm64 # IDE specific files .vscode/ diff --git a/Dockerfile b/Dockerfile index c386e9a..05950f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,40 +1,17 @@ -FROM alpine:latest AS builder - -# Install build dependencies -RUN apk add --no-cache \ - build-base \ - cmake \ - git \ - musl-dev \ - sqlite-dev \ - tar \ - gzip \ - zlib-dev - -# Copy source code -COPY . /src -WORKDIR /src - -# Build -RUN rm -rf build && mkdir build && cd build && \ - cmake .. -DCMAKE_EXE_LINKER_FLAGS="-static" && \ - make -j$(nproc) - # Create final image -FROM scratch +FROM alpine:latest + +ARG TARGETOS +ARG TARGETARCH # Copy binary from builder -COPY --from=builder /src/build/simple_object_storage /sos -# Create data directory (though mounting is preferred) -# RUN mkdir -p /data -# VOLUME /data +RUN mkdir -p /sos -# Set working directory (optional for scratch) -# WORKDIR /data +COPY exe/simple_object_storage-${TARGETOS}-${TARGETARCH} /sos/sos # Expose port EXPOSE 80 # Run server (assuming config is mounted at /data/config.json) -ENTRYPOINT ["/sos"] \ No newline at end of file +CMD ["/sos/sos"] \ No newline at end of file diff --git a/build.sh b/build.sh index c8e399b..b1c003b 100755 --- a/build.sh +++ b/build.sh @@ -1,19 +1,95 @@ #!/bin/bash +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +CACHE_DIR="${SCRIPT_DIR}/cache" +EXE_DIR="${SCRIPT_DIR}/exe" +BUILD_DIR="${SCRIPT_DIR}/build" + +function title() { + echo "----------------------------------------" + # Center the text + local text="$1" + local line_length=40 + local text_length=${#text} + local padding=$(( (line_length - text_length) / 2 )) + printf "%*s%s%*s\n" $padding "" "$text" $padding "" + echo "----------------------------------------" +} + +function die() { + echo " " + title "$1" + echo " " + exit 1 +} + +function clean() { + echo "Cleaning build directories" + rm -rf build + rm -f cmake_install.cmake + rm -f CMakeCache.txt + rm -rf CMakeFiles +} + +function clean_cache() { + echo "Cleaning cache directories" + rm -rf ${CACHE_DIR} +} + +function build() { + ARCH=$1 + + clean + mkdir -p ${BUILD_DIR} + + DOCKCROSS_SCRIPT="${CACHE_DIR}/dockcross-${ARCH}" + + if [ ! -f "${DOCKCROSS_SCRIPT}" ]; then + echo "Downloading dockcross-${ARCH}" + docker run --rm "dockcross/${ARCH}-full" > "${DOCKCROSS_SCRIPT}" + chmod +x "${DOCKCROSS_SCRIPT}" + fi + + echo "Building $ARCH executable" + cd "${SCRIPT_DIR}" + "${DOCKCROSS_SCRIPT}" bash -c "cd build && cmake .. && make -j$(nproc)" + + if [ ! -f build/simple_object_storage ]; then + die "Failed to build $ARCH executable" + fi + + echo "Copying $ARCH executable to $EXE_DIR/simple_object_storage-$ARCH" + cp build/simple_object_storage $EXE_DIR/simple_object_storage-$ARCH +} + # Exit on error set -e -# Create build directory if it doesn't exist -mkdir -p build +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +cd $SCRIPT_DIR -# Enter build directory -cd build +clean_cache -# Run CMake -cmake .. +mkdir -p ${CACHE_DIR} +mkdir -p ${EXE_DIR} -# Build the project -make -j$(nproc) +title "Building linux-arm64 executable" +build linux-arm64 || die "Failed to build linux-arm64 executable" -echo "Build completed successfully!" -echo "The executable is located at: $(pwd)/simple_object_storage_template_registry" \ No newline at end of file +title "Building linux-x86_64 executable" +build linux-x86_64 || die "Failed to build linux-x86_64 executable" +# use Docker architecture style +cp ${EXE_DIR}/simple_object_storage-linux-x86_64 ${EXE_DIR}/simple_object_storage-linux-amd64 + +echo "Compile completed successfully!" +echo "amd64 executable: ./simple_object_storage-linux-amd64" +echo "arm64 executable: ./simple_object_storage-linux-arm64" + +echo "Setting up Docker BuildX" +docker buildx create --name mybuilder --use || true + +echo "Building multi-platform Docker image" +docker buildx build --load -t simple-object-storage:latest --platform linux/amd64,linux/arm64 . + +clean +clean_cache \ No newline at end of file diff --git a/cache/dockcross-linux-arm64 b/cache/dockcross-linux-arm64 new file mode 100755 index 0000000..ffeb27d --- /dev/null +++ b/cache/dockcross-linux-arm64 @@ -0,0 +1,278 @@ +#!/usr/bin/env bash + +DEFAULT_DOCKCROSS_IMAGE=dockcross/linux-arm64-full:20250324-a3b42cd + +#------------------------------------------------------------------------------ +# Helpers +# +err() { + echo -e >&2 "ERROR: $*\n" +} + +die() { + err "$*" + exit 1 +} + +has() { + # eg. has command update + local kind=$1 + local name=$2 + + type -t $kind:$name | grep -q function +} + +# If OCI_EXE is not already set, search for a container executor (OCI stands for "Open Container Initiative") +if [ -z "$OCI_EXE" ]; then + if which podman >/dev/null 2>/dev/null; then + OCI_EXE=podman + elif which docker >/dev/null 2>/dev/null; then + OCI_EXE=docker + else + die "Cannot find a container executor. Search for docker and podman." + fi +fi + +#------------------------------------------------------------------------------ +# Command handlers +# +command:update-image() { + $OCI_EXE pull $FINAL_IMAGE +} + +help:update-image() { + echo "Pull the latest $FINAL_IMAGE ." +} + +command:update-script() { + if cmp -s <( $OCI_EXE run --rm $FINAL_IMAGE ) $0; then + echo "$0 is up to date" + else + echo -n "Updating $0 ... " + $OCI_EXE run --rm $FINAL_IMAGE > $0 && echo ok + fi +} + +help:update-script() { + echo "Update $0 from $FINAL_IMAGE ." +} + +command:update() { + command:update-image + command:update-script +} + +help:update() { + echo "Pull the latest $FINAL_IMAGE, and then update $0 from that." +} + +command:help() { + if [[ $# != 0 ]]; then + if ! has command $1; then + err \"$1\" is not an dockcross command + command:help + elif ! has help $1; then + err No help found for \"$1\" + else + help:$1 + fi + else + cat >&2 < +ENDHELP + exit 1 + fi +} + +#------------------------------------------------------------------------------ +# Option processing +# +special_update_command='' +while [[ $# != 0 ]]; do + case $1 in + + --) + shift + break + ;; + + --args|-a) + ARG_ARGS="$2" + shift 2 + ;; + + --config|-c) + ARG_CONFIG="$2" + shift 2 + ;; + + --image|-i) + ARG_IMAGE="$2" + shift 2 + ;; + update|update-image|update-script) + special_update_command=$1 + break + ;; + -*) + err Unknown option \"$1\" + command:help + exit + ;; + + *) + break + ;; + + esac +done + +# The precedence for options is: +# 1. command-line arguments +# 2. environment variables +# 3. defaults + +# Source the config file if it exists +DEFAULT_DOCKCROSS_CONFIG=~/.dockcross +FINAL_CONFIG=${ARG_CONFIG-${DOCKCROSS_CONFIG-$DEFAULT_DOCKCROSS_CONFIG}} + +[[ -f "$FINAL_CONFIG" ]] && source "$FINAL_CONFIG" + +# Set the docker image +FINAL_IMAGE=${ARG_IMAGE-${DOCKCROSS_IMAGE-$DEFAULT_DOCKCROSS_IMAGE}} + +# Handle special update command +if [ "$special_update_command" != "" ]; then + case $special_update_command in + + update) + command:update + exit $? + ;; + + update-image) + command:update-image + exit $? + ;; + + update-script) + command:update-script + exit $? + ;; + + esac +fi + +# Set the docker run extra args (if any) +FINAL_ARGS=${ARG_ARGS-${DOCKCROSS_ARGS}} + +# Bash on Ubuntu on Windows +UBUNTU_ON_WINDOWS=$([ -e /proc/version ] && grep -l Microsoft /proc/version || echo "") +# MSYS, Git Bash, etc. +MSYS=$([ -e /proc/version ] && grep -l MINGW /proc/version || echo "") +# CYGWIN +CYGWIN=$([ -e /proc/version ] && grep -l CYGWIN /proc/version || echo "") + +if [ -z "$UBUNTU_ON_WINDOWS" -a -z "$MSYS" -a "$OCI_EXE" != "podman" ]; then + USER_IDS=(-e BUILDER_UID="$( id -u )" -e BUILDER_GID="$( id -g )" -e BUILDER_USER="$( id -un )" -e BUILDER_GROUP="$( id -gn )") +fi + +# Change the PWD when working in Docker on Windows +if [ -n "$UBUNTU_ON_WINDOWS" ]; then + WSL_ROOT="/mnt/" + CFG_FILE=/etc/wsl.conf + if [ -f "$CFG_FILE" ]; then + CFG_CONTENT=$(cat $CFG_FILE | sed -r '/[^=]+=[^=]+/!d' | sed -r 's/\s+=\s/=/g') + eval "$CFG_CONTENT" + if [ -n "$root" ]; then + WSL_ROOT=$root + fi + fi + HOST_PWD=`pwd -P` + HOST_PWD=${HOST_PWD/$WSL_ROOT//} +elif [ -n "$MSYS" ]; then + HOST_PWD=$PWD + HOST_PWD=${HOST_PWD/\//} + HOST_PWD=${HOST_PWD/\//:\/} +elif [ -n "$CYGWIN" ]; then + for f in pwd readlink cygpath ; do + test -n "$(type "${f}" )" || { echo >&2 "Missing functionality (${f}) (in cygwin)." ; exit 1 ; } ; + done ; + HOST_PWD="$( cygpath -w "$( readlink -f "$( pwd ;)" ; )" ; )" ; +else + HOST_PWD=$PWD + [ -L $HOST_PWD ] && HOST_PWD=$(readlink $HOST_PWD) +fi + +# Mount Additional Volumes +if [ -z "$SSH_DIR" ]; then + SSH_DIR="$HOME/.ssh" +fi + +HOST_VOLUMES= +if [ -e "$SSH_DIR" -a -z "$MSYS" ]; then + if test -n "${CYGWIN}" ; then + HOST_VOLUMES+="-v $(cygpath -w ${SSH_DIR} ; ):/home/$(id -un)/.ssh" ; + else + HOST_VOLUMES+="-v $SSH_DIR:/home/$(id -un)/.ssh" ; + fi ; +fi + +#------------------------------------------------------------------------------ +# Now, finally, run the command in a container +# +TTY_ARGS= +tty -s && [ -z "$MSYS" ] && TTY_ARGS=-ti +CONTAINER_NAME=dockcross_$RANDOM +$OCI_EXE run $TTY_ARGS --name $CONTAINER_NAME \ + -v "$HOST_PWD":/work \ + $HOST_VOLUMES \ + "${USER_IDS[@]}" \ + $FINAL_ARGS \ + $FINAL_IMAGE "$@" +run_exit_code=$? + +# Attempt to delete container +rm_output=$($OCI_EXE rm -f $CONTAINER_NAME 2>&1) +rm_exit_code=$? +if [[ $rm_exit_code != 0 ]]; then + if [[ "$CIRCLECI" == "true" ]] && [[ $rm_output == *"Driver btrfs failed to remove"* ]]; then + : # Ignore error because of https://circleci.com/docs/docker-btrfs-error/ + else + echo "$rm_output" + exit $rm_exit_code + fi +fi + +exit $run_exit_code + +################################################################################ +# +# This image is not intended to be run manually. +# +# To create a dockcross helper script for the +# dockcross/linux-arm64-full:20250324-a3b42cd image, run: +# +# docker run --rm dockcross/linux-arm64-full:20250324-a3b42cd > dockcross-linux-arm64-full-20250324-a3b42cd +# chmod +x dockcross-linux-arm64-full-20250324-a3b42cd +# +# You may then wish to move the dockcross script to your PATH. +# +################################################################################ diff --git a/dockcross-x86_64 b/cache/dockcross-linux-x86_64 similarity index 100% rename from dockcross-x86_64 rename to cache/dockcross-linux-x86_64 diff --git a/exe/simple_object_storage-linux-amd64 b/exe/simple_object_storage-linux-amd64 new file mode 100755 index 0000000..76a8d50 Binary files /dev/null and b/exe/simple_object_storage-linux-amd64 differ diff --git a/exe/simple_object_storage-linux-arm64 b/exe/simple_object_storage-linux-arm64 new file mode 100755 index 0000000..67ba93d Binary files /dev/null and b/exe/simple_object_storage-linux-arm64 differ diff --git a/exe/simple_object_storage-linux-x86_64 b/exe/simple_object_storage-linux-x86_64 new file mode 100755 index 0000000..76a8d50 Binary files /dev/null and b/exe/simple_object_storage-linux-x86_64 differ