From 4e5ab5b1628df50f06d13fbe2d1bfeeead37d01e Mon Sep 17 00:00:00 2001 From: Guillaume Nodet <gnodet@gmail.com> Date: Tue, 12 Oct 2021 10:07:46 +0200 Subject: [PATCH] Support linux armv6 platform, fixes #201 (#221) --- Makefile | 6 +- Makefile.common | 2 +- docker/dockcross-linux-armv6 | 278 ++++++++++++++++++ .../internal/native/Linux/armv6/libjansi.so | Bin 0 -> 15068 bytes 4 files changed, 283 insertions(+), 3 deletions(-) create mode 100755 docker/dockcross-linux-armv6 create mode 100755 src/main/resources/org/fusesource/jansi/internal/native/Linux/armv6/libjansi.so diff --git a/Makefile b/Makefile index db0ec595..2ed46976 100644 --- a/Makefile +++ b/Makefile @@ -27,8 +27,7 @@ NATIVE_TARGET_DIR:=target/classes/org/fusesource/jansi/internal/native/$(OS_NAME NATIVE_DLL:=$(NATIVE_DIR)/$(LIBNAME) # For cross-compilation, install docker. See also https://github.com/dockcross/dockcross -# Disabled linux-armv6 build because of this issue; https://github.com/dockcross/dockcross/issues/190 -native-all: linux-x86 linux-x86_64 linux-arm linux-armv7 \ +native-all: linux-x86 linux-x86_64 linux-arm linux-armv6 linux-armv7 \ linux-arm64 linux-ppc64 win-x86 win-x86_64 mac-x86 mac-x86_64 freebsd-x86 freebsd-x86_64 native: $(NATIVE_DLL) @@ -48,6 +47,9 @@ linux-x86_64: linux-arm: docker run -it --rm -v $$PWD:/workdir -e CROSS_TRIPLE=arm-linux-gnueabi multiarch/crossbuild make clean-native native OS_NAME=Linux OS_ARCH=arm +linux-armv6: + ./docker/dockcross-linux-armv6 bash -c 'make clean-native native CROSS_PREFIX=armv6-unknown-linux-gnueabihf- OS_NAME=Linux OS_ARCH=armv6' + linux-armv7: docker run -it --rm -v $$PWD:/workdir -e CROSS_TRIPLE=arm-linux-gnueabihf multiarch/crossbuild make clean-native native OS_NAME=Linux OS_ARCH=armv7 diff --git a/Makefile.common b/Makefile.common index 55a5c210..cee5d933 100644 --- a/Makefile.common +++ b/Makefile.common @@ -40,7 +40,7 @@ Linux-arm_JANSI_FLAGS := Linux-armv6_CC := $(CROSS_PREFIX)gcc Linux-armv6_STRIP := $(CROSS_PREFIX)strip -Linux-armv6_CCFLAGS := -I$(JAVA_HOME)/include -Isrc/main/lib/inc_linux -Os -mfloat-abi=hard -mfpu=vfp -fPIC -fvisibility=hidden +Linux-armv6_CCFLAGS := -I$(JAVA_HOME)/include -Isrc/main/lib/inc_linux -Os -fPIC -fvisibility=hidden Linux-armv6_LINKFLAGS := -shared -static-libgcc Linux-armv6_LIBNAME := libjansi.so Linux-armv6_JANSI_FLAGS := diff --git a/docker/dockcross-linux-armv6 b/docker/dockcross-linux-armv6 new file mode 100755 index 00000000..a1eed923 --- /dev/null +++ b/docker/dockcross-linux-armv6 @@ -0,0 +1,278 @@ +#!/usr/bin/env bash + +DEFAULT_DOCKCROSS_IMAGE=dockcross/linux-armv6:latest + +#------------------------------------------------------------------------------ +# 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 docker >/dev/null 2>/dev/null; then + OCI_EXE=docker + elif which podman >/dev/null 2>/dev/null; then + OCI_EXE=podman + 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-image() { + 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 +Usage: dockcross [options] [--] command [args] + +By default, run the given *command* in an dockcross Docker container. + +The *options* can be one of: + + --args|-a Extra args to the *docker run* command + --image|-i Docker cross-compiler image to use + --config|-c Bash script to source before running this script + + +Additionally, there are special update commands: + + update-image + update-script + update + +For update command help use: $0 help <command> +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" ]; 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-armv6:latest image, run: +# +# docker run --rm dockcross/linux-armv6:latest > dockcross-linux-armv6-latest +# chmod +x dockcross-linux-armv6-latest +# +# You may then wish to move the dockcross script to your PATH. +# +################################################################################ diff --git a/src/main/resources/org/fusesource/jansi/internal/native/Linux/armv6/libjansi.so b/src/main/resources/org/fusesource/jansi/internal/native/Linux/armv6/libjansi.so new file mode 100755 index 0000000000000000000000000000000000000000..6113726ce44997fdb97f46c305adf0b26c91741b GIT binary patch literal 15068 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 literal 0 HcmV?d00001