diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..69677ce --- /dev/null +++ b/.editorconfig @@ -0,0 +1,63 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/general/.editorconfig +# See: https://editorconfig.org/ +# The formatting style defined in this file is the official standardized style to be used in all Arduino Tooling +# projects and should not be modified. +# Note: indent style for each file type is defined even when it matches the universal config in order to make it clear +# that this type has an official style. + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{adoc,asc,asciidoc}] +indent_size = 2 +indent_style = space + +[*.{bash,sh}] +indent_size = 2 +indent_style = space + +[*.{c,cc,cp,cpp,cxx,h,hh,hpp,hxx,ii,inl,ino,ixx,pde,tpl,tpp,txx}] +indent_size = 2 +indent_style = space + +[*.{go,mod}] +indent_style = tab + +[*.java] +indent_size = 2 +indent_style = space + +[*.{js,jsx,json,jsonc,json5,ts,tsx}] +indent_size = 2 +indent_style = space + +[*.{md,mdx,mkdn,mdown,markdown}] +indent_size = unset +indent_style = space + +[*.proto] +indent_size = 2 +indent_style = space + +[*.py] +indent_size = 4 +indent_style = space + +[*.svg] +indent_size = 2 +indent_style = space + +[*.{yaml,yml}] +indent_size = 2 +indent_style = space + +[{.gitconfig,.gitmodules}] +indent_style = tab + +[deps/*/*] +ignore = true diff --git a/.github/workflows/check-shell-task.yml b/.github/workflows/check-shell-task.yml new file mode 100644 index 0000000..5a105a0 --- /dev/null +++ b/.github/workflows/check-shell-task.yml @@ -0,0 +1,177 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-shell-task.md +name: Check Shell Scripts + +# See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows +on: + create: + push: + paths: + - ".github/workflows/check-shell-task.ya?ml" + - "Taskfile.ya?ml" + - "**/.editorconfig" + - "**.bash" + - "**.sh" + pull_request: + paths: + - ".github/workflows/check-shell-task.ya?ml" + - "Taskfile.ya?ml" + - "**/.editorconfig" + - "**.bash" + - "**.sh" + schedule: + # Run every Tuesday at 8 AM UTC to catch breakage caused by tool changes. + - cron: "0 8 * * TUE" + workflow_dispatch: + repository_dispatch: + +jobs: + run-determination: + runs-on: ubuntu-latest + outputs: + result: ${{ steps.determination.outputs.result }} + steps: + - name: Determine if the rest of the workflow should run + id: determination + run: | + RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x" + # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead. + if [[ + "${{ github.event_name }}" != "create" || + "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX + ]]; then + # Run the other jobs. + RESULT="true" + else + # There is no need to run the other jobs. + RESULT="false" + fi + + echo "result=$RESULT" >> $GITHUB_OUTPUT + + lint: + name: ${{ matrix.configuration.name }} + needs: run-determination + if: needs.run-determination.outputs.result == 'true' + runs-on: ubuntu-latest + + env: + # See: https://github.com/koalaman/shellcheck/releases/latest + SHELLCHECK_RELEASE_ASSET_SUFFIX: .linux.x86_64.tar.xz + + strategy: + fail-fast: false + + matrix: + configuration: + - name: Generate problem matcher output + # ShellCheck's "gcc" output format is required for annotated diffs, but inferior for humans reading the log. + format: gcc + # The other matrix job is used to set the result, so this job is configured to always pass. + continue-on-error: true + - name: ShellCheck + # ShellCheck's "tty" output format is most suitable for humans reading the log. + format: tty + continue-on-error: false + + steps: + - name: Set environment variables + run: | + # See: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable + echo "INSTALL_PATH=${{ runner.temp }}/shellcheck" >> "$GITHUB_ENV" + + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Download latest ShellCheck release binary package + id: download + uses: MrOctopus/download-asset-action@1.0 + with: + repository: koalaman/shellcheck + excludes: prerelease, draft + asset: ${{ env.SHELLCHECK_RELEASE_ASSET_SUFFIX }} + target: ${{ env.INSTALL_PATH }} + + - name: Install ShellCheck + run: | + cd "${{ env.INSTALL_PATH }}" + tar --extract --file="${{ steps.download.outputs.name }}" + EXTRACTION_FOLDER="$(basename "${{ steps.download.outputs.name }}" "${{ env.SHELLCHECK_RELEASE_ASSET_SUFFIX }}")" + # Add installation to PATH: + # See: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path + echo "${{ env.INSTALL_PATH }}/$EXTRACTION_FOLDER" >> "$GITHUB_PATH" + + - name: Run ShellCheck + uses: liskin/gh-problem-matcher-wrap@v2 + continue-on-error: ${{ matrix.configuration.continue-on-error }} + with: + linters: gcc + run: task --silent shell:check SHELLCHECK_FORMAT=${{ matrix.configuration.format }} + + formatting: + needs: run-determination + if: needs.run-determination.outputs.result == 'true' + runs-on: ubuntu-latest + + steps: + - name: Set environment variables + run: | + # See: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable + echo "SHFMT_INSTALL_PATH=${{ runner.temp }}/shfmt" >> "$GITHUB_ENV" + + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Download shfmt + id: download + uses: MrOctopus/download-asset-action@1.0 + with: + repository: mvdan/sh + excludes: prerelease, draft + asset: _linux_amd64 + target: ${{ env.SHFMT_INSTALL_PATH }} + + - name: Install shfmt + run: | + # Executable permissions of release assets are lost + chmod +x "${{ env.SHFMT_INSTALL_PATH }}/${{ steps.download.outputs.name }}" + # Standardize binary name + mv "${{ env.SHFMT_INSTALL_PATH }}/${{ steps.download.outputs.name }}" "${{ env.SHFMT_INSTALL_PATH }}/shfmt" + # Add installation to PATH: + # See: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path + echo "${{ env.SHFMT_INSTALL_PATH }}" >> "$GITHUB_PATH" + + - name: Format shell scripts + run: task --silent shell:format + + - name: Check formatting + run: git diff --color --exit-code + + executable: + needs: run-determination + if: needs.run-determination.outputs.result == 'true' + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Check for non-executable scripts + run: task --silent shell:check-mode diff --git a/README.md b/README.md index 55b1325..a8d5954 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Check Markdown status](https://github.com/arduino/crossbuild/actions/workflows/check-markdown-task.yml/badge.svg)](https://github.com/arduino/crossbuild/actions/workflows/check-markdown-task.yml) [![Check License status](https://github.com/arduino/crossbuild/actions/workflows/check-license.yml/badge.svg)](https://github.com/arduino/crossbuild/actions/workflows/check-license.yml) [![Check Taskfiles status](https://github.com/arduino/crossbuild/actions/workflows/check-taskfiles.yml/badge.svg)](https://github.com/arduino/crossbuild/actions/workflows/check-taskfiles.yml) +[![Check Shell Scripts status](https://github.com/arduino/crossbuild/actions/workflows/check-shell-task.yml/badge.svg)](https://github.com/arduino/crossbuild/actions/workflows/check-shell-task.yml) This docker container has been created to allow us to easily crosscompile our c++ tools. The idea comes from [multiarch/crossbuild](https://github.com/multiarch/crossbuild), but that container unfortunately is outdated and the apt sources are no longer available. diff --git a/Taskfile.yml b/Taskfile.yml index 7be02bd..3bfeb97 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -84,3 +84,80 @@ tasks: desc: Install dependencies managed by npm cmds: - npm install + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-shell-task/Taskfile.yml + shell:check: + desc: Check for problems with shell scripts + cmds: + - | + if ! which shellcheck &>/dev/null; then + echo "shellcheck not installed or not in PATH. Please install: https://github.com/koalaman/shellcheck#installing" + exit 1 + fi + - | + # There is something odd about shellcheck that causes the task to always exit on the first fail, despite any + # measures that would prevent this with any other command. So it's necessary to call shellcheck only once with + # the list of script paths as an argument. This could lead to exceeding the maximum command length on Windows if + # the repository contained a large number of scripts, but it's unlikely to happen in reality. + shellcheck \ + --format={{default "tty" .SHELLCHECK_FORMAT}} \ + $( + # The odd method for escaping . in the regex is required for windows compatibility because mvdan.cc/sh gives + # \ characters special treatment on Windows in an attempt to support them as path separators. + find . \ + -type d -name '.git' -prune -or \ + -type d -name '.licenses' -prune -or \ + -type d -name '__pycache__' -prune -or \ + -type d -name 'node_modules' -prune -or \ + -type d -path './deps/*' -prune -or \ + \( \ + -regextype posix-extended \ + -regex '.*[.](bash|sh)' -and \ + -type f \ + \) \ + -print + ) + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-shell-task/Taskfile.yml + shell:check-mode: + desc: Check for non-executable shell scripts + cmds: + - | + EXIT_STATUS=0 + while read -r nonExecutableScriptPath; do + # The while loop always runs once, even if no file was found + if [[ "$nonExecutableScriptPath" == "" ]]; then + continue + fi + + echo "::error file=${nonExecutableScriptPath}::non-executable script file: $nonExecutableScriptPath"; + EXIT_STATUS=1 + done <<<"$( + # The odd approach to escaping `.` in the regex is required for windows compatibility because mvdan.cc/sh + # gives `\` characters special treatment on Windows in an attempt to support them as path separators. + find . \ + -type d -name '.git' -prune -or \ + -type d -name '.licenses' -prune -or \ + -type d -name '__pycache__' -prune -or \ + -type d -name 'node_modules' -prune -or \ + -type d -path './deps/*' -prune -or \ + \( \ + -regextype posix-extended \ + -regex '.*[.](bash|sh)' -and \ + -type f -and \ + -not -executable \ + -print \ + \) + )" + exit $EXIT_STATUS + + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-shell-task/Taskfile.yml + shell:format: + desc: Format shell script files + cmds: + - | + if ! which shfmt &>/dev/null; then + echo "shfmt not installed or not in PATH. Please install: https://github.com/mvdan/sh#shfmt" + exit 1 + fi + - shfmt -w . diff --git a/deps/build_libs.sh b/deps/build_libs.sh index a1054de..c21b26f 100755 --- a/deps/build_libs.sh +++ b/deps/build_libs.sh @@ -1,23 +1,27 @@ #!/bin/bash -ex +true # Dummy command required to prevent first ShellCheck directive from having global scope. + +# shellcheck disable=SC2153 # Fix false positive of ShellCheck rule SC2153. export PREFIX=/opt/lib/${CROSS_COMPILE} -if [ x$CROSS_COMPILER == x ]; then -CROSS_COMPILER=${CROSS_COMPILE}-gcc -CROSS_COMPILER_CXX=${CROSS_COMPILE}-g++ +if [ "$CROSS_COMPILER" == "" ]; then + CROSS_COMPILER=${CROSS_COMPILE}-gcc + CROSS_COMPILER_CXX=${CROSS_COMPILE}-g++ # AR=${CROSS_COMPILE}-ar else -export CC=$CROSS_COMPILER -export CXX=$CROSS_COMPILER++ -CROSS_COMPILER=$CC -CROSS_COMPILER_CXX=$CXX + export CC=$CROSS_COMPILER + export CXX=$CROSS_COMPILER++ + CROSS_COMPILER=$CC + CROSS_COMPILER_CXX=$CXX fi cd /opt/lib/libusb-1.0.26 -export LIBUSB_DIR=`pwd` -./configure --prefix=${PREFIX} --with-pic --disable-udev --enable-static --disable-shared --host=${CROSS_COMPILE} +LIBUSB_DIR=$(pwd) +export LIBUSB_DIR +./configure --prefix="${PREFIX}" --with-pic --disable-udev --enable-static --disable-shared --host="${CROSS_COMPILE}" make distclean -./configure --prefix=${PREFIX} --with-pic --disable-udev --enable-static --disable-shared --host=${CROSS_COMPILE} -make -j$(nproc) +./configure --prefix="${PREFIX}" --with-pic --disable-udev --enable-static --disable-shared --host="${CROSS_COMPILE}" +make -j"$(nproc)" make install export PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig @@ -27,11 +31,12 @@ if [[ $CROSS_COMPILE == "x86_64-apple-darwin13" ]]; then export LIBUSB_1_0_LIBS="-L${PREFIX}/lib -lusb-1.0" fi cd /opt/lib/libusb-compat-0.1.7 -export LIBUSB0_DIR=`pwd` -PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig" ./configure --prefix=${PREFIX} --enable-static --disable-shared --host=${CROSS_COMPILE} +LIBUSB0_DIR=$(pwd) +export LIBUSB0_DIR +PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig" ./configure --prefix="${PREFIX}" --enable-static --disable-shared --host="${CROSS_COMPILE}" make distclean -PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig" ./configure --prefix=${PREFIX} --enable-static --disable-shared --host=${CROSS_COMPILE} -make -j$(nproc) +PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig" ./configure --prefix="${PREFIX}" --enable-static --disable-shared --host="${CROSS_COMPILE}" +make -j"$(nproc)" make install cd /opt/lib/libftdi1-1.4 @@ -39,7 +44,7 @@ rm -rf build && mkdir build && cd build CMAKE_EXTRA_FLAG="-DSHAREDLIBS=OFF -DBUILD_TESTS=OFF -DPYTHON_BINDINGS=OFF -DEXAMPLES=OFF -DFTDI_EEPROM=OFF" -if [[ $CROSS_COMPILE == "i686-w64-mingw32" ]] ; then +if [[ $CROSS_COMPILE == "i686-w64-mingw32" ]]; then CMAKE_EXTRA_FLAG="$CMAKE_EXTRA_FLAG -DCMAKE_TOOLCHAIN_FILE=./cmake/Toolchain-i686-w64-mingw32.cmake" fi @@ -47,58 +52,61 @@ if [[ $CROSS_COMPILE == "x86_64-apple-darwin13" ]]; then CMAKE_EXTRA_FLAG="$CMAKE_EXTRA_FLAG -DCMAKE_AR=$AR -DCMAKE_RANLIB=$RANLIB" fi -cmake -DCMAKE_C_COMPILER=$CROSS_COMPILER -DCMAKE_CXX_COMPILER=$CROSS_COMPILER_CXX -DCMAKE_INSTALL_PREFIX="$PREFIX" $CMAKE_EXTRA_FLAG -DLIBUSB_INCLUDE_DIR="$PREFIX/include/libusb-1.0" -DLIBFTDI_LIBRARY_DIRS="$PREFIX/lib" -DLIBUSB_LIBRARIES="usb-1.0" ../ -make -j$(nproc) +cmake -DCMAKE_C_COMPILER="$CROSS_COMPILER" -DCMAKE_CXX_COMPILER="$CROSS_COMPILER_CXX" -DCMAKE_INSTALL_PREFIX="$PREFIX" "$CMAKE_EXTRA_FLAG" -DLIBUSB_INCLUDE_DIR="$PREFIX/include/libusb-1.0" -DLIBFTDI_LIBRARY_DIRS="$PREFIX/lib" -DLIBUSB_LIBRARIES="usb-1.0" ../ +make -j"$(nproc)" make install cd /opt/lib/libelf-0.8.13 -export LIBELF_DIR=`pwd` -./configure --disable-shared --host=$CROSS_COMPILE --prefix=${PREFIX} +LIBELF_DIR=$(pwd) +export LIBELF_DIR +./configure --disable-shared --host="$CROSS_COMPILE" --prefix="${PREFIX}" make distclean -./configure --disable-shared --host=$CROSS_COMPILE --prefix=${PREFIX} -make -j$(nproc) +./configure --disable-shared --host="$CROSS_COMPILE" --prefix="${PREFIX}" +make -j"$(nproc)" make install echo "*****************" -file ${PREFIX}/lib/* +file "${PREFIX}"/lib/* echo "*****************" export CPPFLAGS="-P" cd /opt/lib/ncurses-6.3 -export NCURSES_DIR=`pwd` +NCURSES_DIR=$(pwd) +export NCURSES_DIR -./configure $EXTRAFLAGS --target=$CROSS_COMPILE --without-pthread --enable-database --enable-sp-funcs --enable-term-driver --without-shared --without-debug --without-ada --enable-termcap --without-manpages --without-progs --without-tests --host=$CROSS_COMPILE --prefix=${PREFIX} +./configure "$EXTRAFLAGS" --target="$CROSS_COMPILE" --without-pthread --enable-database --enable-sp-funcs --enable-term-driver --without-shared --without-debug --without-ada --enable-termcap --without-manpages --without-progs --without-tests --host="$CROSS_COMPILE" --prefix="${PREFIX}" make distclean -./configure $EXTRAFLAGS --target=$CROSS_COMPILE --without-pthread --enable-database --enable-sp-funcs --enable-term-driver --without-shared --without-debug --without-ada --enable-termcap --without-manpages --without-progs --without-tests --host=$CROSS_COMPILE --prefix=${PREFIX} -make -j$(nproc) +./configure "$EXTRAFLAGS" --target="$CROSS_COMPILE" --without-pthread --enable-database --enable-sp-funcs --enable-term-driver --without-shared --without-debug --without-ada --enable-termcap --without-manpages --without-progs --without-tests --host="$CROSS_COMPILE" --prefix="${PREFIX}" +make -j"$(nproc)" make install.libs cd /opt/lib/readline-8.0 -export READLINE_DIR=`pwd` -./configure --prefix=$PREFIX --disable-shared --host=$CROSS_COMPILE +READLINE_DIR=$(pwd) +export READLINE_DIR +./configure --prefix="$PREFIX" --disable-shared --host="$CROSS_COMPILE" make distclean -./configure --prefix=$PREFIX --disable-shared --host=$CROSS_COMPILE -make -j$(nproc) +./configure --prefix="$PREFIX" --disable-shared --host="$CROSS_COMPILE" +make -j"$(nproc)" make install-static -if [[ $CROSS_COMPILE != "i686-w64-mingw32" && $CROSS_COMPILE != "x86_64-apple-darwin13" ]] ; then -cd /opt/lib/eudev-3.2.10 -./autogen.sh -./configure --enable-static --disable-gudev --disable-introspection --disable-shared --disable-blkid --disable-kmod --disable-manpages --prefix=$PREFIX --host=${CROSS_COMPILE} -make distclean -./autogen.sh -./configure --enable-static --disable-gudev --disable-introspection --disable-shared --disable-blkid --disable-kmod --disable-manpages --prefix=$PREFIX --host=${CROSS_COMPILE} -make -j$(nproc) -make install +if [[ $CROSS_COMPILE != "i686-w64-mingw32" && $CROSS_COMPILE != "x86_64-apple-darwin13" ]]; then + cd /opt/lib/eudev-3.2.10 + ./autogen.sh + ./configure --enable-static --disable-gudev --disable-introspection --disable-shared --disable-blkid --disable-kmod --disable-manpages --prefix="$PREFIX" --host="${CROSS_COMPILE}" + make distclean + ./autogen.sh + ./configure --enable-static --disable-gudev --disable-introspection --disable-shared --disable-blkid --disable-kmod --disable-manpages --prefix="$PREFIX" --host="${CROSS_COMPILE}" + make -j"$(nproc)" + make install fi cd /opt/lib/hidapi-0.12.0 export PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig ./bootstrap -./configure --prefix=$PREFIX --enable-static --disable-shared --host=$CROSS_COMPILE +./configure --prefix="$PREFIX" --enable-static --disable-shared --host="$CROSS_COMPILE" make distclean ./bootstrap -./configure --prefix=$PREFIX --enable-static --disable-shared --host=$CROSS_COMPILE -make -j$(nproc) -make install \ No newline at end of file +./configure --prefix="$PREFIX" --enable-static --disable-shared --host="$CROSS_COMPILE" +make -j"$(nproc)" +make install