name: ci

on: [push, pull_request]

jobs:
  build-linux:
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        container: [ "ubuntu:latest", "ubuntu:22.04", "debian:12", "debian:11", "archlinux:base" ]

    container:
      image: ${{ matrix.container }}
      options: --privileged

    steps:
      - uses: actions/checkout@v4

      - name: setup build environment
        run: |
          case "${{ matrix.container }}" in
          ubuntu:latest)
            apt update
            apt upgrade -y
            # ubuntu:26.04 drops libwnn-dev
            apt install -y build-essential autoconf flex libutempter-dev libgtk-3-dev libvterm-dev libvte-2.91-dev libsdl2-dev libfribidi-dev libuim-dev libfcitx5core-dev libfcitx5gclient-dev libscim-dev libibus-1.0-dev libm17n-dev libcanna1g-dev libssh2-1-dev curl unzip protobuf-compiler libprotobuf-dev libncurses-dev libssl-dev default-jdk libswt-gtk-4-java libvte-2.91-gtk4-dev
            ;;
          ubuntu:22.04|debian*)
            apt update
            apt upgrade -y
            # ubuntu:22.04 and debian:11 do not support libvte-2.91-gtk4-dev.
            apt install -y build-essential autoconf flex libutempter-dev libgtk-3-dev libvterm-dev libvte-2.91-dev libsdl2-dev libfribidi-dev libuim-dev libfcitx5core-dev libfcitx5gclient-dev libscim-dev libibus-1.0-dev libm17n-dev libwnn-dev libcanna1g-dev libssh2-1-dev curl unzip protobuf-compiler libprotobuf-dev libncurses-dev libssl-dev default-jdk libswt-gtk-4-java
            ;;
          archlinux*)
            pacman -Syyu --noconfirm base-devel intltool libutempter wayland gtk3 gtk4 libvterm vte3 vte4 sdl2 fribidi fcitx5 fcitx5-gtk scim ibus m17n-lib libssh2 curl unzip protobuf
            ;;
          esac

      - name: configure
        run: |
          (cd uitoolkit/wayland && sh ./rescanproto.sh)
          curl -L -O https://github.com/arakiken/mosh/archive/refs/heads/sixel-winsock.zip
          unzip sixel-winsock.zip
          (cd mosh-sixel-winsock; autoconf; ./configure)
          CONFIGURE_ARGS="--with-gui=xlib,fb,console,wayland,sdl2 --with-mosh=$PWD/mosh-sixel-winsock --enable-debug --enable-optimize-redrawing --enable-vt52"
          case "${{ matrix.container }}" in
          archlinux*)
            CONFIGURE_ARGS="$CONFIGURE_ARGS --with-gtk=4.0"
            ;;
          esac
          CFLAGS="-Wall -Werror=incompatible-pointer-types -g -O2" ./configure ${CONFIGURE_ARGS}

      - name: build
        run: |
          make
          make install
          (cd libvterm && make && make install)
          (cd gtk && make && make install)
          case "${{ matrix.container }}" in
          archlinux*)
            (cd gtk && make gtk3 && make install-gtk3)
            ;;
          ubuntu:latest)
            (cd gtk && make gtk4 && make install-gtk4)
            ;;
          esac
          java_ver=`javac --version|sed 's/javac \([0-9]*\).*/\1/'`
          if test "$java_ver" != ""; then (cd java; cat Makefile | sed s/java-26-openjdk/java-${java_ver}-openjdk-amd64/ > Makefile.2; mv Makefile.2 Makefile; make); fi
          (cd main; ./mlterm --test --logmsg=false)

  build-linux-min:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: setup build environment
        run: |
          sudo apt update
          sudo apt upgrade -y
          sudo apt install -y build-essential flex libsdl2-dev

      - name: configure
        run: |
          (cd uitoolkit/wayland && sh ./rescanproto.sh)
          CONFIGURE_ARGS="--with-gui=xlib,fb,console,wayland,sdl2 --without-map-table --without-prop-table --disable-image --disable-dl-ctl --disable-fribidi --disable-dl-type --disable-otl --disable-ssh2 --with-utmp=none --disable-dnd --disable-kbd --disable-uim --disable-m17nlib --disable-ibus --disable-fcitx --disable-scim --disable-canna --disable-wnn --disable-skk --disable-iiimf --disable-ind --with-type-engines=xcore --disable-anti-alias --disable-fontconfig --disable-daemon --disable-split --disable-zmodem --disable-compact-truecolor"
          CFLAGS="-Wall -Werror=incompatible-pointer-types -g -O2" ./configure ${CONFIGURE_ARGS}

      - name: build
        run: |
          make
          sudo make install

  build-android:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: nttld/setup-ndk@v1
        id: setup-ndk
        with:
          ndk-version: r26d

      - name: build
        run: |
          CLANG_ARMV7A=`ls $ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi*-clang|tail -n 1`
          JNI_PATH=$HOME/mlterm-android/app/src/main/jni
          curl -L -O https://github.com/fribidi/fribidi/releases/download/0.19.7/fribidi-0.19.7.tar.bz2
          tar xvf fribidi-0.19.7.tar.bz2
          (cd fribidi-0.19.7; CC="$CLANG_ARMV7A -fPIC" ./configure --host=armv7a-linux-androideabi; mkdir -p $JNI_PATH/fribidi; cp `find . -name *.[chi]` $JNI_PATH/fribidi)
          curl -L -O https://download.savannah.gnu.org/releases/freetype/freetype-2.13.3.tar.gz
          tar xvf freetype-2.13.3.tar.gz
          (cd freetype-2.13.3; sh ./autogen.sh; CC="$CLANG_ARMV7A -fPIC" ./configure --host=armv7a-linux-androideabi --disable-shared --with-png=no --with-harfbuzz=no --with-bzip2=no --with-brotli=no --prefix=$JNI_PATH/freetype/armeabi-v7a; make; make install)
          curl -L -O https://download.savannah.nongnu.org/releases/m17n/libotf-0.9.16.tar.gz
          tar xvf libotf-0.9.16.tar.gz
          echo 'PKG_CONFIG_PATH=$HOME/mlterm-android/app/src/main/jni/freetype/armeabi-v7a/lib/pkgconfig:$PKG_CONFIG_PATH pkg-config freetype2 $*' > libotf-0.9.16/freetype-config
          (cd libotf-0.9.16; chmod 755 freetype-config; ac_cv_func_malloc_0_nonnull=yes PATH=$PWD:$PATH CC="$CLANG_ARMV7A -fPIC" ./configure --host=armv7a-linux-androideabi; mkdir -p $JNI_PATH/libotf; cp `find . -name *.[ch]` $JNI_PATH/libotf)
          curl -L -O https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-4.0.0.tar.gz
          tar xvf libressl-4.0.0.tar.gz
          (cd libressl-4.0.0; CC="$CLANG_ARMV7A -fPIC" ./configure --host=armv7a-linux-androideabi --disable-shared --prefix=$HOME/libressl; make; make install)
          curl -L -O https://libssh2.org/download/libssh2-1.11.1.tar.gz
          tar xvf libssh2-1.11.1.tar.gz
          (cd libssh2-1.11.1; CC="$CLANG_ARMV7A -fPIC" ./configure --host=armv7a-linux-androideabi --disable-shared --prefix=$JNI_PATH/libssh2/armeabi-v7a --with-libssl-prefix=$HOME/libressl; make; make install)
          cp $HOME/libressl/lib/libcrypto.a $JNI_PATH/libssh2/armeabi-v7a/lib
          curl -L -O https://github.com/protocolbuffers/protobuf/releases/download/v3.20.1/protobuf-cpp-3.20.1.tar.gz
          tar xvf protobuf-cpp-3.20.1.tar.gz
          (cd protobuf-3.20.1; CC="$CLANG_ARMV7A -fPIC" CXX="${CLANG_ARMV7A}++ -fPIC" ./configure --host=armv7a-linux-androideabi --disable-shared --prefix=$JNI_PATH/protobuf/armeabi-v7a; make; make install; make clean)
          (cd protobuf-3.20.1; ./configure --disable-shared --prefix=$HOME/protobuf; make; make install)
          curl -L -O https://github.com/arakiken/mosh/archive/refs/heads/sixel-winsock.zip
          unzip sixel-winsock.zip
          # Without -L$HOME/libressl/lib in CC, ./configure stops in "checking for AES_encrypt in -lcrypto... no".
          (cd mosh-sixel-winsock; autoconf; PATH=$HOME/protobuf/bin:$PATH PKG_CONFIG_PATH=$HOME/libressl/lib/pkgconfig:$JNI_PATH/protobuf/armeabi-v7a/lib/pkgconfig:$PKG_CONFIG_PATH CC="$CLANG_ARMV7A -fPIC -L$HOME/libressl/lib" CXX="${CLANG_ARMV7A}++ -fPIC -L$HOME/libressl/lib" ./configure --host=armv7a-linux-androideabi; for f in src/protobufs/*.proto; do $HOME/protobuf/bin/protoc --cpp_out=src/protobufs -Isrc/protobufs $f; done)
          (cd android; ./prepare-gradle.sh $HOME/mlterm-android $PWD/../mosh-sixel-winsock $HOME/libressl 8.8.0)
          (cd $HOME/mlterm-android; ./build-gradle.sh)
          mkdir dist; cp `find $HOME/mlterm-android -name *.apk` dist

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: mlterm-android
          path: dist/*.apk

  build-macos:
    strategy:
      matrix:
        os: [ macos-latest, macos-14 ]

    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v4

      - name: setup build environment
        run: |
          brew install gtk+3 libssh2

      - name: configure
        run: |
          CONFIGURE_ARGS="--prefix=$HOME/mlterm --with-gui=quartz"
          CFLAGS="-Wall -Werror=incompatible-pointer-types -g -O2" ./configure ${CONFIGURE_ARGS}

      - name: build
        run: |
          rm tool/mlconfig/po/Makefile
          make; make install
          cp -R cocoa/mlterm.app ~/
          cocoa/install.sh ~/mlterm
          mkdir dist
          mv ~/mlterm.app dist/

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: mlterm-${{ matrix.os }}
          path: dist/**

  build-ios:
    runs-on: macos-latest

    steps:
      - uses: actions/checkout@v4

      - name: configure
        run: |
          SDK=`xcodebuild -showsdks|grep iphonesimulator|tail -n 1|sed 's/^.*\(iphonesimulator.*\)/\1/'`
          SDKROOT=`xcrun --sdk $SDK --show-sdk-path`
          SDKCC="`xcrun --sdk $SDK -f cc` -isysroot $SDKROOT -arch x86_64"
          curl -L -O https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-4.0.0.tar.gz
          tar xvf libressl-4.0.0.tar.gz
          (cd libressl-4.0.0; curl -L https://raw.githubusercontent.com/palmerc/portable/5626ce43e30e936e870c123b4ac80e469de4d9b9/include/compat/endian.h > include/compat/endian.h; CC="$SDKCC" ./configure --host=x86_64-apple-darwin --disable-shared --prefix=$HOME/libressl; make; make install)
          curl -L -O https://libssh2.org/download/libssh2-1.11.1.tar.gz
          tar xvf libssh2-1.11.1.tar.gz
          (cd libssh2-1.11.1; CC="$SDKCC" ./configure --host=x86_64-apple-darwin --disable-shared --prefix=$HOME/libssh2 --with-libssl-prefix=$HOME/libressl; make; make install)
          CONFIGURE_ARGS="--prefix=$HOME/mlterm --disable-shared --with-gui=quartz --host=x86_64-apple-darwin --disable-fribidi --disable-otl --without-tools --enable-debug --with-ios-sdk=$SDK --with-ios-arch=x86_64"
          PKG_CONFIG_PATH=$HOME/libressl/lib/pkgconfig:$HOME/libssh2/lib/pkgconfig CFLAGS="-Wall -Werror=incompatible-pointer-types -g -O2 -fno-objc-arc -fobjc-weak" ./configure ${CONFIGURE_ARGS}

      - name: build
        run: |
          make; make install
          cp -R cocoa/mlterm-ios.app ~/
          cocoa/install-ios.sh ~/mlterm
          mkdir dist
          mv ~/mlterm-ios.app dist/

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: mlterm-ios
          path: dist/**

  build-netbsd:
    name: "build-netbsd (NetBSD/amd64 10.1 with pkgsrc)"
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Install packages and run configure and make (on the NetBSD VM)
        uses: vmactions/netbsd-vm@v1
        with:
          release: "10.1"
          copyback: false
          prepare: |
            ftp -o - https://cdn.NetBSD.org/pub/NetBSD/NetBSD-`uname -r`/amd64/binary/sets/xbase.tar.xz | tar -C / -zxpf - ./usr/X11R7/bin ./usr/X11R7/include ./usr/X11R7/lib ./usr/X11R7/share
            ftp -o - https://cdn.NetBSD.org/pub/NetBSD/NetBSD-`uname -r`/amd64/binary/sets/xcomp.tar.xz | tar -C / -zxpf - ./usr/X11R7/bin ./usr/X11R7/include ./usr/X11R7/lib ./usr/X11R7/share
            # Explicitly update glib2 first. It has been pre-installed by
            # vmactions/netbsd-builder for fuse-sshfs
            pkg_add -u glib2
            pkg_add -u pkgconf gettext-tools libtool-base
            pkg_add -u cairo Canna-lib fribidi gdk-pixbuf2 gtk3+ fcitx ibus m17n-lib harfbuzz scim uim ja-FreeWnn-lib libXft SDL2 libssh2 vte3
          run: |
            CFLAGS="-Wall -Werror=incompatible-pointer-types -g -O2" CPPFLAGS="-I/usr/pkg/include" ./configure --x-includes=/usr/X11R7/include --x-libraries=/usr/X11R7/lib --with-imagelib=gdk-pixbuf --with-gui=xlib,wscons,sdl2 --with-type-engins=xcore,xft,cairo --enable-anti-alias
            make
            make install
            (cd gtk && make && make install)

  build-freebsd:
    name: "build-freebsd (FreeBSD/amd64 15.1 with ports)"
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Install packages and run configure and make (on the FreeBSD VM)
        uses: vmactions/freebsd-vm@v1
        with:
          release: "15.1"
          copyback: false
          prepare: |
            pkg install -y pkgconf perl5 libtool desktop-file-utils glib cairo gdk-pixbuf2 gtk3 vte3 libssh2 fontconfig freetype2 fribidi uim m17n-lib scim ibus ja-FreeWnn-lib ja-canna-lib sdl2
          run: |
            CFLAGS="-Wall -Werror=incompatible-pointer-types -g -O2" CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib -Wl,--undefined-version" ./configure --with-imagelib=gdk-pixbuf --with-gui=xlib,fb,sdl2 --with-type-engins=xcore,xft,cairo --enable-anti-alias
            make
            make install
            (cd gtk && make && make install)

  build-mingw-with-mosh:
    runs-on: windows-latest

    defaults:
      run:
        shell: msys2 {0}
    steps:
      - uses: actions/checkout@v3

      - uses: msys2/setup-msys2@v2
        with:
          msystem: UCRT64
          update: true
          install: git make mingw-w64-ucrt-x86_64-toolchain mingw-w64-ucrt-x86_64-libssh2 mingw-w64-ucrt-x86_64-gtk3 unzip mingw-w64-ucrt-x86_64-autotools mingw-w64-ucrt-x86_64-protobuf

      - name: build
        run: |
          curl -L -O https://github.com/arakiken/mosh/archive/refs/heads/sixel-winsock.zip
          unzip sixel-winsock.zip
          sed 's/^Libs:.\(.*\)/Libs:\1 -lws2_32/' /ucrt64/lib/pkgconfig/libssh2.pc > libssh2.pc; mv libssh2.pc /ucrt64/lib/pkgconfig
          (cd mosh-sixel-winsock; autoconf; ./configure)
          CFLAGS="-Wall -g -O2" ./configure --with-gui=win32 --with-mosh=$PWD/mosh-sixel-winsock
          make
          DESTDIR=/tmp make install
          mkdir dist
          cp -R /tmp/ucrt64/etc/mlterm dist/
          cp /tmp/ucrt64/bin/*.exe /tmp/ucrt64/bin/*.dll /tmp/ucrt64/lib/*/*.dll dist/
          # for debug by gdb.
          mkdir dist/nomt; cp dist/*.exe dist/nomt/
          mt=`ls /c/Program\ Files\ \(x86\)\/Windows\ Kits\/*\/bin\/*\/x64\/mt.exe | head -n 1`
          echo $mt
          if test "$mt" != ""; then for f in dist/*.exe; do "$mt" -manifest win32/mlterm.manifest -outputresource:$f; done; fi
          (cd dist; ldd *.exe libptymosh.dll libptyssh.dll | sed -n 's/.*=> \([^ ]*\) .*/\1/p' | grep --ignore-case -v /WINDOWS/ | grep -v /dist/ | xargs | sed 's/\(.*\)/cp \1 ./' | sh)

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: mlterm-mingw-w64-with-mosh
          path: dist/**

  build-mingw:
    runs-on: windows-latest

    defaults:
      run:
        shell: msys2 {0}
    steps:
      - uses: actions/checkout@v3

      - uses: msys2/setup-msys2@v2
        with:
          msystem: UCRT64
          update: true
          install: git make mingw-w64-ucrt-x86_64-toolchain mingw-w64-ucrt-x86_64-libssh2 mingw-w64-ucrt-x86_64-gtk3 mingw-w64-ucrt-x86_64-SDL2

      - name: build
        run: |
          curl -L -O https://mlterm.sourceforge.net/vte-headers.tar.gz
          tar xzvf vte-headers.tar.gz -C D:/a/_temp/msys64/ucrt64
          CFLAGS="-Wall -g -O2" ./configure --with-gui=win32,sdl2 --enable-debug
          # cp these files fails with 'cannot create symbolic link' because
          # ../win32, ../xlib and ../wayland have not been copied yet.
          cp uitoolkit/xlib/ui_selection_encoding.c uitoolkit/win32/ui.c uitoolkit/win32/winrs.rs gui/sdl2/uitoolkit/sdl2/
          make
          DESTDIR=/tmp make install
          (cd gtk; sed 's/-luuid//g' Makefile > Makefile.2; mv Makefile.2 Makefile; make; DESTDIR=/tmp make install)
          mkdir dist
          cp -R /tmp/ucrt64/etc/mlterm dist/
          cp /tmp/ucrt64/bin/*.exe /tmp/ucrt64/bin/*.dll /tmp/ucrt64/lib/*/*.dll dist/
          # for debug by gdb.
          mkdir dist/nomt; cp dist/*.exe dist/nomt/
          mt=`ls /c/Program\ Files\ \(x86\)\/Windows\ Kits\/*\/bin\/*\/x64\/mt.exe | head -n 1`
          echo $mt
          if test "$mt" != ""; then for f in dist/*.exe; do "$mt" -manifest win32/mlterm.manifest -outputresource:$f; done; fi
          (cd dist; ldd *.exe | sed -n 's/.*=> \([^ ]*\) .*/\1/p' | grep --ignore-case -v /WINDOWS/ | grep -v /dist/ | xargs | sed 's/\(.*\)/cp \1 ./' | sh)
          (cd dist; ./mlterm.exe --test --logmsg=false)

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: mlterm-mingw-w64
          path: dist/**

  build-msys2:
    runs-on: windows-latest

    defaults:
      run:
        shell: msys2 {0}
    steps:
      - uses: actions/checkout@v3

      - uses: msys2/setup-msys2@v2
        with:
          msystem: MSYS
          update: true
          install: git base-devel gcc

      - name: build
        run: |
          CFLAGS="-Wall -g -O2" ./configure --with-gui=win32
          make
          DESTDIR=/tmp make install
          mkdir dist
          cp -R /tmp/usr dist/
          # for debug by gdb.
          mkdir dist/usr/bin/nomt; cp dist/usr/bin/*.exe dist/usr/bin/nomt/
          mt=`ls /c/Program\ Files\ \(x86\)\/Windows\ Kits\/*\/bin\/*\/x64\/mt.exe | head -n 1`
          echo $mt
          # No exe files in dist/usr/libexec/mlterm for now.
          if test "$mt" != ""; then for f in dist/usr/bin/*.exe; do "$mt" -manifest win32/mlterm.manifest -outputresource:$f; done; fi

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: mlterm-msys2
          path: dist/**
