diff --git a/.ci/README.md b/.ci/README.md new file mode 100644 index 0000000..9932697 --- /dev/null +++ b/.ci/README.md @@ -0,0 +1,5 @@ +# libcubescript CI scripts + +These CI scripts are meant to provide a helper environment for continuous +integration. They are written to be used only in the CI environment, not +general purpose environments. diff --git a/.ci/build-cs b/.ci/build-cs new file mode 100755 index 0000000..00aa20b --- /dev/null +++ b/.ci/build-cs @@ -0,0 +1,161 @@ +#!/bin/sh + +expected_triplet=$TARGET + +if [ -z "$expected_triplet" ]; then + echo "ERROR: target triplet not provided!" + exit 1 +fi + +current_triplet=`$CC -dumpmachine` + +if [ "$CC" = "clang" ]; then + export CXX="clang++" +else + export CXX="g++" +fi + +if [ "$TARGET" != "darwin" -a "$CC" != "clang" -a "$expected_triplet" != "$current_triplet" ]; then + cross=yes + export CC="${expected_triplet}-${CC}" + export CXX="${expected_triplet}-${CXX}" + export STRIP="${expected_triplet}-strip" + export AR="${expected_triplet}-ar" + export AS="${expected_triplet}-as" +else + export STRIP="strip" + export AR="ar" +fi + +meson_system="linux" + +case "${expected_triplet}" in + darwin) + # special case here + meson_system="darwin" + ;; + x86_64*) + meson_cpu_family="x86_64" + meson_cpu="x86_64" + meson_endian="little" + case "${expected_triplet}" in + *w64*) + meson_system="windows" + ;; + *) + qemu_cpu="x86_64" + ;; + esac + ;; + i686*) + meson_cpu_family="x86" + meson_cpu="i686" + meson_endian="little" + qemu_cpu="i386" + ;; + powerpc64le*) + meson_cpu_family="ppc64" + meson_cpu="ppc64le" + meson_endian="little" + qemu_cpu="ppc64le" + ;; + powerpc64*) + meson_cpu_family="ppc64" + meson_cpu="ppc64" + meson_endian="big" + qemu_cpu="ppc64" + ;; + powerpcle*) + echo "ERROR: ppcle not supported in qemu" + exit 1 + ;; + powerpc*) + meson_cpu_family="ppc" + meson_cpu="ppc" + meson_endian="big" + qemu_cpu="ppc" + ;; + aarch64-*) + meson_cpu_family="aarch64" + meson_cpu="aarch64" + meson_endian="little" + qemu_cpu="aarch64" + ;; + arm-*) + meson_cpu_family="arm" + meson_cpu="armv6l" + meson_endian="little" + qemu_cpu="arm" + ;; + riscv64-*) + meson_cpu_family="riscv64" + meson_cpu="riscv64" + meson_endian="little" + qemu_cpu="riscv64" + ;; + s390x*) + meson_cpu_family="s390x" + meson_cpu="s390x" + meson_endian="big" + qemu_cpu="s390x" + ;; + mips-*) + meson_cpu_family="mips" + meson_cpu="mips" + meson_endian="big" + qemu_cpu="mips" + ;; + m68k*) + meson_cpu_family="m68k" + meson_cpu="m68k" + meson_endian="big" + qemu_cpu="m68k" + ;; + *) + echo "ERROR: Cross CPU unspecified" + exit 1 + ;; +esac + +export PATH="$(pwd)/host_tools:$PATH" + +if [ -n "$qemu_cpu" -a -n "$cross" ]; then + echo ">> Preparing qemu..." + # work around glibc being dumb + # the cache format is not endian agnostic, so unless a dummy file exists + # here, qemu will try to use host's and it will crash guest glibc on BE + sudo mkdir -p /usr/${expected_triplet}/etc + sudo touch /usr/${expected_triplet}/etc/ld.so.cache +fi + +echo ">> Building and testing cubescript..." + +mkdir -p build +cd build + +args="" +if [ -n "${cross}" ]; then + cat << EOF > crossfile +[binaries] +c = '${CC}' +cpp = '${CXX}' +strip = '${STRIP}' + +[host_machine] +system = '${meson_system}' +cpu_family = '${meson_cpu_family}' +cpu = '${meson_cpu}' +endian = '${meson_endian}' +EOF + args="${args} --cross-file=crossfile" +fi +if [ -n "$BUILDTYPE" ]; then + args="${args} --buildtype=$BUILDTYPE" +fi + +meson .. ${args} || exit 1 +ninja all || exit 1 +ninja test || exit 1 +cd .. + +exit 0 diff --git a/.ci/build-cs-windows b/.ci/build-cs-windows new file mode 100755 index 0000000..1db7d49 --- /dev/null +++ b/.ci/build-cs-windows @@ -0,0 +1,23 @@ +#!/bin/bash + +unset CC CXX CC_FOR_BUILD CXX_FOR_BUILD + +export PATH="$(pwd)/host_tools:$PATH" + +echo ">> Building and testing cubescript..." + +args="" +if [ -n "$BUILDTYPE" ]; then + args="${args} --buildtype=$BUILDTYPE" +fi + +mkdir -p build +cd build- + +cmd.exe //C 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat' amd64 '&&' \ +meson .. ${args} '&&' \ +ninja all '&&' ninja test || exit 1 + +cd .. + +exit 0 diff --git a/.ci/install-env b/.ci/install-env new file mode 100755 index 0000000..df3547a --- /dev/null +++ b/.ci/install-env @@ -0,0 +1,88 @@ +#!/bin/sh + +expected_triplet=$TARGET + +if [ -z "$expected_triplet" ]; then + echo "ERROR: target triplet not provided!" + exit 1 +fi + +ensure_tool() { + command -v "$1" > /dev/null + if [ $? -ne 0 ]; then + echo "ERROR: Missing tool: $1" + exit 1 + fi +} + +if [ "$(uname -s)" = "Linux" ]; then + is_linux=yes +fi + +echo ">> Checking tools..." + +ensure_tool gcc +ensure_tool g++ +ensure_tool clang +ensure_tool clang++ + +mkdir -p host_tools + +echo ">> Updating package database..." + +[ -n "$is_linux" ] && sudo apt-get update + +echo ">> Installing meson..." + +if [ -n "$is_linux" ]; then + sudo apt-get install ninja-build +else + ninja_version=1.10.2 + cd host_tools + wget "https://github.com/ninja-build/ninja/releases/download/v${ninja_version}/ninja-mac.zip" || exit 1 + tar xf ninja-mac.zip || exit 1 + rm ninja-mac.zip + cd .. + export PATH="$(pwd)/host_tools:$PATH" +fi + +if [ -n "$(command -v pip3)" ]; then + sudo pip3 install meson || exit 1 +elif [ -n "$(command -v pip)" ]; then + sudo pip install meson || exit 1 +else + echo "ERROR: pip not found" + exit 1 +fi + +ensure_tool meson +ensure_tool ninja + +if [ "$(uname -s)" != "Linux" ]; then + exit 0 +fi + +current_triplet=`gcc -dumpmachine` + +if [ -z "$current_triplet" ]; then + echo "ERROR: Native compiler not present!" + exit 1 +fi + +if [ "$expected_triplet" = "$current_triplet" ]; then + exit 0 +fi + +echo ">> Installing toolchain..." + +if [ "$expected_triplet" = "x86_64-w64-mingw32" ]; then + gcc_suffix="mingw-w64" + extra_packages="wine" +else + gcc_suffix="${expected_triplet}" + extra_packages="qemu-user" +fi + +sudo apt-get install gcc-${gcc_suffix} g++-${gcc_suffix} ${extra_packages} || exit 1 + +exit $? diff --git a/.ci/install-env-windows b/.ci/install-env-windows new file mode 100755 index 0000000..9a397e6 --- /dev/null +++ b/.ci/install-env-windows @@ -0,0 +1,15 @@ +#!/bin/bash + +ninja_version=1.10.2 + +echo ">> Installing meson..." + +mkdir -p host_tools + +curl -L -o ninja.zip https://github.com/ninja-build/ninja/releases/download/v${ninja_version}/ninja-win.zip || exit 1 +7z x ninja.zip || exit 1 +mv ninja.exe host_tools + +pip3 install meson + +exit 0 diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..fbf952c --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,91 @@ +name: CI + +on: push + +jobs: + linux: + name: Linux + runs-on: ubuntu-20.04 + + env: + TARGET: '${{ matrix.config.target }}' + LUA_VERSIONS: '5.4.2 5.3.6 5.2.4 5.1.5' + CC: '${{ matrix.config.cc }}' + BUILDTYPE: '${{ matrix.config.buildtype }}' + + strategy: + matrix: + config: + # x86_64: test gcc, clang, + release mode to catch assert bugs + - { target: x86_64-linux-gnu, cc: gcc, buildtype: debugoptimized } + - { target: x86_64-linux-gnu, cc: gcc, buildtype: release } + - { target: x86_64-linux-gnu, cc: clang, buildtype: debugoptimized } + # 32-bit x86 + - { target: i686-linux-gnu, cc: gcc, buildtype: debugoptimized } + # all powerpc + - { target: powerpc64le-linux-gnu, cc: gcc, buildtype: debugoptimized } + - { target: powerpc64-linux-gnu, cc: gcc, buildtype: debugoptimized } + - { target: powerpc-linux-gnu, cc: gcc, buildtype: debugoptimized } + # aarch64 and arm + - { target: aarch64-linux-gnu, cc: gcc, buildtype: debugoptimized } + - { target: arm-linux-gnueabi, cc: gcc, buildtype: debugoptimized } + # riscv64 and s390x + - { target: riscv64-linux-gnu, cc: gcc, buildtype: debugoptimized } + - { target: s390x-linux-gnu, cc: gcc, buildtype: debugoptimized } + # mips, m68k + - { target: mips-linux-gnu, cc: gcc, buildtype: debugoptimized } + - { target: m68k-linux-gnu, cc: gcc, buildtype: debug } + # x86_64 windows cross, release mode + - { target: x86_64-w64-mingw32, cc: gcc, buildtype: release } + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + persist-credentials: false + + - name: Prepare environment + run: sh ./.ci/install-env + + - name: Build and test cubescript + run: sh ./.ci/build-cs + + windows: + name: Windows + runs-on: windows-2019 + + env: + LUA_VERSIONS: '5.4.2 5.3.6 5.2.4 5.1.5' + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + persist-credentials: false + + - name: Prepare environment + run: bash ./.ci/install-env-windows + + - name: Build and test cubescript + run: bash ./.ci/build-cs-windows + + mac: + name: MacOS + runs-on: macos-10.15 + + env: + TARGET: 'darwin' + LUA_VERSIONS: '5.4.2 5.3.6 5.2.4 5.1.5' + CC: 'clang' + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + persist-credentials: false + + - name: Prepare environment + run: sh ./.ci/install-env + + - name: Build and test cubescript + run: sh ./.ci/build-cs diff --git a/README.md b/README.md index a075d39..7210272 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # libcubescript +[![Build Status](https://github.com/octaforge/libcubescript/actions/workflows/build.yaml/badge.svg)](https://github.com/octaforge/libcubescript/actions) + ![CubeScript REPL](https://ftp.octaforge.org/q66/random/libcs_repl.gif) ## Overview