diff --git a/README.md b/README.md index 899c9f3..8057511 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,15 @@ If you want to add or remove a repository maintained by these scripts, follow th and has files. +CI / Nightly-Builders +===================== + +The `builders` directory contains Dockerfiles and scripts to create Debian packages +as well as a cross-compiled Windows installer for Geany and Geany-Plugins. +These scripts are used for the nightly builds, for details see +[builders/README.md](builders/README.md). + + IRC Bot Plugins =============== @@ -68,6 +77,6 @@ features like a bunch of !commands. For details, read the source code. License -=============== +======= Unless stated otherwise all code in this repository is licensed of under the terms of the GNU General Public License version 2 (see COPYING in this repository). diff --git a/builders/.dockerignore b/builders/.dockerignore new file mode 100644 index 0000000..d4cd1e8 --- /dev/null +++ b/builders/.dockerignore @@ -0,0 +1,5 @@ +/.git +/certificates +/output +/scripts +/start_build.sh diff --git a/builders/Dockerfile.debian b/builders/Dockerfile.debian new file mode 100644 index 0000000..5febc18 --- /dev/null +++ b/builders/Dockerfile.debian @@ -0,0 +1,32 @@ +# +# Copyright 2022 The Geany contributors +# License: GPLv2 +# +# Docker image for Geany and Geany-Plugins for building Debian packages. +# + +ARG BASE_IMAGE_NAME=debian:bullseye +FROM $BASE_IMAGE_NAME + +LABEL org.opencontainers.image.title="Geany-Debian-CI" +LABEL org.opencontainers.image.description="Build image for Geany CI to support automatic building of Debian packages." +LABEL org.opencontainers.image.url="https://github.com/geany/infrastructure" +LABEL org.opencontainers.image.source="https://github.com/geany/infrastructure" +LABEL org.opencontainers.image.authors="The Geany contributors" +LABEL org.opencontainers.image.licenses="GPL-2.0" + +ENV DEBIAN_FRONTEND=noninteractive + +RUN set -ex && \ + apt-get update && \ + apt-get dist-upgrade --assume-yes && \ + apt-get install --assume-yes --no-install-recommends \ + ca-certificates wget gnupg build-essential git \ + devscripts dpkg-dev equivs fakeroot git-buildpackage \ + intltool libdistro-info-perl reprepro \ + # pre-install a few basic dependencies we probably need to reduce build time + libgtk-3-dev python3 python3-docutils python3-lxml \ + # pre-install some geany-plugins dependencies + cppcheck valac libgpgme-dev libctpl-dev liblua5.1-0-dev libmarkdown2-dev \ + # tools not necessary for build but useful for debugging + nano less diff --git a/builders/Dockerfile.mingw64 b/builders/Dockerfile.mingw64 new file mode 100644 index 0000000..6c15e64 --- /dev/null +++ b/builders/Dockerfile.mingw64 @@ -0,0 +1,121 @@ +# +# Copyright 2022 The Geany contributors +# License: GPLv2 +# +# Docker image for Geany and Geany-Plugins cross-build to Windows +# The image contains a self-compiled Pacman to install mingw-w64 +# packages and all other dependencies necessary to build the code +# and create a ready-use installer. +# For more details, see build_mingw64_geany.sh where this image is used. +# +# Intermediate container for building pacman +FROM debian:bullseye as build-pacman + +ENV PACMAN_VERSION=6.0.1 +ENV PACMAN_SHA256="0db61456e56aa49e260e891c0b025be210319e62b15521f29d3e93b00d3bf731" +ENV MSYS2_KEYRING_PKG="msys2-keyring-1~20220623-1-any.pkg.tar.zst" +ENV MSYS2_KEYRING_PKG_SHA256="3508c7fca2f8b9722139666459eb8716f2413fd6daaf997abf0df41d7f285dc9" +ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/pacman/lib/x86_64-linux-gnu + +RUN set -ex && \ + apt-get update && \ + apt-get install --no-install-recommends --assume-yes \ + build-essential meson wget xz-utils zstd gnupg2 file zstd ca-certificates \ + pkg-config m4 libarchive-dev libssl-dev libcurl4-gnutls-dev libgpgme-dev \ + python3-setuptools + +# compile Pacman +RUN set -ex && \ + wget --no-verbose https://sources.archlinux.org/other/pacman/pacman-${PACMAN_VERSION}.tar.xz && \ + echo "${PACMAN_SHA256} *pacman-${PACMAN_VERSION}.tar.xz" | sha256sum --check --strict - && \ + tar xf pacman-${PACMAN_VERSION}.tar.xz && \ + cd /pacman-${PACMAN_VERSION} && \ + meson \ + --prefix /usr/local/pacman \ + --sysconfdir=/windows/etc \ + --localstatedir=/windows/var \ + --buildtype release \ + --strip \ + -Dscriptlet-shell='/bin/bash' \ + -Ddoc='disabled' \ + -Ddoxygen='disabled' \ + -Ddoc='disabled' \ + -Di18n=false \ + build && \ + ninja -C build && \ + ninja -C build install && \ + ln -s /usr/local/pacman/bin/* /usr/local/bin/ + +COPY mingw64/etc/ /windows/etc/ + +# setup pacman-key +RUN set -ex && \ + # download MSYS2 keyring + mkdir -p /usr/local/pacman/share/pacman/keyrings/ && \ + wget --no-verbose "https://repo.msys2.org/msys/x86_64/${MSYS2_KEYRING_PKG}" && \ + echo "${MSYS2_KEYRING_PKG_SHA256} *${MSYS2_KEYRING_PKG}" | sha256sum --check --strict - && \ + tar -x -C /usr/local/pacman/share/pacman/keyrings/ -f "${MSYS2_KEYRING_PKG}" --strip-components 4 usr && \ + # initialize keyring + pacman-key --init && \ + pacman-key --populate msys2 + + +# Main image +FROM debian:bullseye + +LABEL org.opencontainers.image.title="Geany-Mingw-w64-CI" +LABEL org.opencontainers.image.description="Build image for Geany CI to support automatic building of Windows installers." +LABEL org.opencontainers.image.url="https://github.com/geany/infrastructure" +LABEL org.opencontainers.image.source="https://github.com/geany/infrastructure" +LABEL org.opencontainers.image.authors="The Geany contributors" +LABEL org.opencontainers.image.licenses="GPL-2.0" + +# install native tools and libraries +RUN set -ex && \ + dpkg --add-architecture i386 && \ + apt-get update && \ + apt-get install --no-install-recommends --assume-yes \ + # libraries \ + libcurl3-gnutls libgpgme11 libarchive13 libssl1.1 \ + # common useful utilities \ + wget curl less nano git gnupg2 file ca-certificates dos2unix \ + zip unzip xz-utils zstd \ + # build tools \ + build-essential automake autoconf autopoint gettext libtool check cppcheck \ + # genay-plugins autogen.sh requirements + intltool libglib2.0-dev \ + # mingw-w64 \ + gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 mingw-w64-x86-64-dev mingw-w64-tools \ + # install wine to test installer and created binaries + wine wine32 wine64 \ + # install NSIS and exiftool to inspect binary metadata + nsis libimage-exiftool-perl osslsigncode \ + # Geany build dependencies \ + python3-lxml python3-docutils + + +# copy pacman and scripts +COPY --from=build-pacman /windows /windows +COPY --from=build-pacman /usr/local/pacman /usr/local/pacman +COPY mingw64/bin/ /usr/local/bin/ +RUN ln -s /usr/local/pacman/bin/* /usr/local/bin/ && \ + mkdir /build + +WORKDIR /build +ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/pacman/lib/x86_64-linux-gnu + +# start wine to initially create config directory +RUN /usr/local/bin/mingw-w64-i686-wine hostname.exe && \ + /usr/local/bin/mingw-w64-x86_64-wine hostname.exe && \ + # install GTK3 and all its dependencies + pacman --noconfirm -Sy mingw-w64-x86_64-gtk3 && \ + # cleanup + apt-get clean && \ + rm -rf /var/lib/apt/lists/* && \ + yes | pacman -Scc && \ + rm -r /usr/share/doc \ + /usr/share/locale \ + /usr/share/man \ + /windows/mingw64/share/icons \ + /windows/mingw64/share/locale \ + /windows/mingw64/share/doc diff --git a/builders/README.md b/builders/README.md new file mode 100644 index 0000000..5487773 --- /dev/null +++ b/builders/README.md @@ -0,0 +1,135 @@ +CI / Nightly-Builders +===================== + +## About + +Scripts and Dockerfiles for Geany and Geany-Plugins nightly builds. +`start_nightly_build.sh` will create (if missing) Docker images for +Debian stable and unstable as well as a Docker image for Mingw-w64 +cross-compilaton to Windows. +For the created Debian packages repositories for the distributions +(stable and unstable) will be created. + +## Scripts and files + + ├── Dockerfile.debian -> Dockerfile for Debian build image + ├── Dockerfile.mingw64 -> Dockerfile for Mingw-64 build image + ├── README.md + ├── certificates -> Certificate for signing Windows binaries and installer + │   ├── cert.pem -> Certificate public key (the filename is important) + │   └── key.pem -> Certificate secret key (the filename is important) + │ + ├── mingw64 -> Helpers and configuration for Pacman and Windows builds + │   ├── bin (these files will be built into the Windows Docker image) + │   │   ├── mingw-w64-i686-wine + │   │   └── mingw-w64-x86_64-wine + │   └── etc + │   ├── pacman.conf + │   └── pacman.d + │   └── mirrorlist.mingw64 + ├── output -> Directory where all build results are stored + │ + ├── scripts -> Build scripts to be executed within Docker containers + │   ├── build_debian_geany.sh -> Build Geany Debian packages + │   ├── build_debian_geany_plugins.sh -> Build Geany-Plugins Debian packages + │   ├── build_mingw64_geany.sh -> Build Geany Windows installer + │   ├── build_mingw64_geany_plugins.sh -> Build Geany-Plugins Windows installer + │   └── update_debian_repositories.sh -> Build repositories for Debian packages + │ + └── start_build.sh -> Run Debian and Windows build containers and start builds + +## Geany sources + +All of the scripts can either use an existing source distribution +of Geany (and Geany-Plugins) if it is mounted into the build Docker +container (as `/geany-source` resp. `/geany-plugins-source`). +If no existing source distribution is found, the scripts will clone +Geany resp. Geany-Plugins from GIT master. + +## start_build.sh + +Main entry point to (re-)build the necessary Docker images and trigger +the builds of Geany and Geany-Plugins for the various targets. + + usage: start_build.sh [-d|--distro DISTRO] [-m|--mingw64] + [-r|--rebuild-images] + -d, --distro DISTRO Build for target Debian DISTRO (e.g. "bullseye", + can be specified multiple times + -f, --force-rebuild Force rebuilding of immages even if not necessary + -g, --geany Build Geany + --geany-source Path to a Geany source directory (optional, cloned from GIT if missing) + --geany-plugins-source Path to a Geany-Plugins source directory (optional, cloned from GIT if missing) + -h Show this help screen + -l, --log-to-stdout Log build output additionally to stdout + -m, --mingw64 Build for target Mingw-w64 + -p, --geany-plugins Build Geany-Plugins + -r, --rebuild-images Rebuild Docker images before start building + (images are rebuilt automatically every 30 days) + -s, --sudo Use "sudo" for Docker commands + + +Example to build Geany and Geany-Plugins for Debian Bullseye, Debian Sid and Windows: + + bash start_build.sh --geany --geany-plugins --mingw64 --distro sid --distro bullseye + +## Debian package build + +The Debian based builds use as much as possible the official Debian package sources +from https://salsa.debian.org/geany-team/geany.git (and resp. for Geany-Plugins). + +Within the Debian based Docker images, packages are built from a GIT clone of Geany (unless +a source tree is provided into the container via a volume). + +### Docker image + +The Debian based Docker image is pretty straight-forward and just extends the official +"debian:$distro" images. The base image can be passed as build argument on image building and +so images for different Debian distributions (stable, sid, ...) can be built for later use. + +The Dockerfile just installs a couple of development tools and libraries which are required for +building Geany and Geany-Plugins. This is mainly to prepopulate the image with commonly used +tools and libraries. + +### Repository creation + +TBW - WIP + +#### GnuPG key + +TBW - WIP + +## Windows (Mingw64) build + +Geany and Geany-Plugins are built for Windows by cross-compiling them in a Docker container +containing all necessary tools. + +If the build was started via Github Actions from a pull request, the pull request number +will be appended to the resulting installer filename. For all other builds, the used GIT +commit short hash is used. + +The created installer for Geany will contain the +[Geany-Themes](https://github.com/geany/geany-themes) collection as well as the GTK +runtime with all necessary dependencies. + +The created installer for Geany-Plugins will contain all necessary dependencies +for the plugins to work. + +For more details, see the scripts `build_mingw64_geany.sh` and `build_mingw64_geany_plugins.sh` + +In theory, it is also possible to create release installers with this method. + +### Docker image + +The Docker image for the Windows build is based on a Debian image but has the full toolchain +for cross-compiling to mingw64 included. Additionally, the image contains a self-compiled +Pacman package manager to install packages from the MSYS2 repositories. + +### Code sign certificate + +If the directory `certificates` contains the two files `cert.pem` and `key.pem `, +then they will be used to digitally sign all created binary files (all built +`.exe` and `.dll` files). + +If the directory is empty, code signing will be skipped. + +The certificate should be in the PEM format and the key should not require a passphrase. diff --git a/builders/certificates/.gitkeep b/builders/certificates/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/builders/mingw64/bin/mingw-w64-i686-wine b/builders/mingw64/bin/mingw-w64-i686-wine new file mode 100755 index 0000000..722e5b8 --- /dev/null +++ b/builders/mingw64/bin/mingw-w64-i686-wine @@ -0,0 +1,4 @@ +#!/bin/sh -e + +WINEPATH="${WINEPATH};/windows/mingw32/bin" wine $@ + diff --git a/builders/mingw64/bin/mingw-w64-x86_64-wine b/builders/mingw64/bin/mingw-w64-x86_64-wine new file mode 100755 index 0000000..193291e --- /dev/null +++ b/builders/mingw64/bin/mingw-w64-x86_64-wine @@ -0,0 +1,3 @@ +#!/bin/sh -e + +WINEPATH="${WINEPATH};/windows/mingw64/bin" wine64 $@ diff --git a/builders/mingw64/etc/pacman.conf b/builders/mingw64/etc/pacman.conf new file mode 100644 index 0000000..8a911e4 --- /dev/null +++ b/builders/mingw64/etc/pacman.conf @@ -0,0 +1,40 @@ + +[options] +RootDir = /windows +DBPath = /windows/var/lib/pacman/ +CacheDir = /windows/var/cache/pacman/pkg/ +LogFile = /windows/var/log/pacman.log +GPGDir = /windows/etc/pacman.d/gnupg/ +HoldPkg = pacman +#XferCommand = /usr/bin/curl -C - -f %u > %o +#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u +#CleanMethod = KeepInstalled +#UseDelta = 0.7 +Architecture = x86_64 + +# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup +#IgnorePkg = +#IgnoreGroup = + +#NoUpgrade = +#NoExtract = + +# Misc options +#UseSyslog +#Color +#TotalDownload +CheckSpace +#VerbosePkgLists + +# By default, pacman accepts packages signed by keys that its local keyring +# trusts (see pacman-key and its man page), as well as unsigned packages. +#SigLevel = Never +SigLevel = Required DatabaseOptional +LocalFileSigLevel = Optional +#RemoteFileSigLevel = Required + +[mingw64] +Include = /windows/etc/pacman.d/mirrorlist.mingw64 + +[msys] +Include = /windows/etc/pacman.d/mirrorlist.msys diff --git a/builders/mingw64/etc/pacman.d/mirrorlist.mingw64 b/builders/mingw64/etc/pacman.d/mirrorlist.mingw64 new file mode 100644 index 0000000..dc16ae5 --- /dev/null +++ b/builders/mingw64/etc/pacman.d/mirrorlist.mingw64 @@ -0,0 +1,6 @@ +## +## 64-bit Mingw-w64 repository mirrorlist +## + +Server = http://repo.msys2.org/mingw/x86_64 +Server = http://www2.futureware.at/~nickoe/msys2-mirror/mingw/x86_64 diff --git a/builders/mingw64/etc/pacman.d/mirrorlist.msys b/builders/mingw64/etc/pacman.d/mirrorlist.msys new file mode 100644 index 0000000..0c27b68 --- /dev/null +++ b/builders/mingw64/etc/pacman.d/mirrorlist.msys @@ -0,0 +1,6 @@ +## +## MSYS repository mirrorlist +## + +Server = http://repo.msys2.org/msys/$arch/ +Server = http://www2.futureware.at/~nickoe/msys2-mirror/msys/$arch/ diff --git a/builders/output/.gitkeep b/builders/output/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/builders/scripts/build_debian_geany.sh b/builders/scripts/build_debian_geany.sh new file mode 100644 index 0000000..9fc56ef --- /dev/null +++ b/builders/scripts/build_debian_geany.sh @@ -0,0 +1,182 @@ +#!/bin/bash +# +# Copyright 2022 The Geany contributors +# License: GPLv2 +# +# Helper script to build Debian packages for Geany. +# +# This script has to be executed within the Docker container. +# The Docker container should have a bind-mount for ${OUTPUT_DIRECTORY} +# where the resulting packages is stored. +# +# This script is meant to be run in a Docker container. +# + + +GEANY_VERSION= # will be set below from configure.ac +GEANY_GIT_REVISION= # will be set below from configure.ac +PACKAGE_VERSION= # will be set below +OUTPUT_DIRECTORY="/output" +GEANY_GIT_REPOSITORY="https://github.com/geany/geany.git" +GEANY_DEBIAN_REPOSITORY="https://salsa.debian.org/geany-team/geany.git" + +# rather static values, unlikely to be changed +GEANY_SOURCE_DIR="/geany-source" +GEANY_BUILD_DIR="/tmp/geany-build" +GEANY_DEBIAN_DIR="/tmp/geany-debian" + +# for "dch" (debian changelog) +export DEBEMAIL="devel@lists.geany.org" +export DEBFULLNAME="The Geany contributors" + +# stop on errors +set -e + + +log() { + echo "=========== $(date '+%Y-%m-%d %H:%M:%S %Z') $* ===========" +} + + +git_clone_geany_if_necessary() { + log "Clone Geany repository (if necessary)" + mkdir -p "$(dirname ${GEANY_BUILD_DIR})" + if [ -d ${GEANY_SOURCE_DIR} ]; then + log "Copying Geany source" + cp --archive ${GEANY_SOURCE_DIR}/ ${GEANY_BUILD_DIR}/ + else + log "Cloning Geany repository from ${GEANY_GIT_REPOSITORY}" + git clone --depth 1 ${GEANY_GIT_REPOSITORY} ${GEANY_BUILD_DIR} + fi +} + + +parse_geany_version() { + log "Parse Geany version" + GEANY_VERSION=$(sed -n -E -e 's/^AC_INIT\(\[Geany\], \[(.+)\],/\1/p' ${GEANY_BUILD_DIR}/configure.ac) + GEANY_GIT_REVISION=$(cd ${GEANY_BUILD_DIR} && git rev-parse --short --revs-only HEAD 2>/dev/null || true) + PACKAGE_VERSION="${GEANY_VERSION}-1~$(date '+%Y%m%d')git${GEANY_GIT_REVISION}" +} + + +run_autogen_sh() { + log "Run ./autogen.sh" + cd ${GEANY_BUILD_DIR} + # run ./autogen.sh as the Debian package won't run ./autogen.sh for us + NOCONFIGURE=1 ./autogen.sh +} + +create_tarball_for_debuild() { + log "Create source tarball" + cd ${GEANY_BUILD_DIR} + # create a source tarball, keep .git included on purpose for Geany GIT build detection + tar --transform "s,^,geany-plugins-${GEANY_VERSION}/,S" \ + --create \ + --gzip \ + --file "../geany_${GEANY_VERSION}.orig.tar.gz" \ + . +} + + +git_clone_debian_geany() { + log "Clone Geany Debian repository" + git clone --depth 1 ${GEANY_DEBIAN_REPOSITORY} ${GEANY_DEBIAN_DIR} + # move debian package files to Geany GIT checkout + mv ${GEANY_DEBIAN_DIR}/debian ${GEANY_BUILD_DIR} +} + + +install_build_dependencies() { + log "Install build dependencies" + cd ${GEANY_BUILD_DIR} + apt-get --assume-yes update + apt-get --assume-yes dist-upgrade + mk-build-deps \ + --install \ + --remove \ + --tool "apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --assume-yes" + # mk-build-deps leave the following files which then break 'debuild' later on + rm -f geany-build-deps_*-?_amd64.buildinfo geany-build-deps_*-?_amd64.changes +} + + +add_changelog_entry() { + log "Add ChangeLog entry for Debian package" + cd ${GEANY_BUILD_DIR} + dch \ + --urgency low \ + --distribution unstable \ + --newversion "${PACKAGE_VERSION}" \ + "Autobuilt by CI or nightly build." +} + + +build_package() { + log "Build Debian package" + cd ${GEANY_BUILD_DIR} + + debuild -uc -us +} + + +copy_results() { + log "Copy build artefacts" + + BUILD_DIR_DIRNAME=$(dirname ${GEANY_BUILD_DIR}) + + rm -rf ${OUTPUT_DIRECTORY}/geany/* + + cp --verbose ${BUILD_DIR_DIRNAME}/geany_* ${OUTPUT_DIRECTORY}/geany + cp --verbose ${BUILD_DIR_DIRNAME}/geany-common_* ${OUTPUT_DIRECTORY}/geany + cp --verbose ${BUILD_DIR_DIRNAME}/geany-dbgsym_* ${OUTPUT_DIRECTORY}/geany +} + + +log_and_store_build_environment() { + log "Using environment" + + GTK_VERSION=$(pkg-config --modversion gtk+-3.0) + GLIB_VERSION=$(pkg-config --modversion glib-2.0) + COMPILER_VERSION=$(gcc -dumpfullversion) + + echo "Debian Distribution : $(grep PRETTY_NAME /etc/os-release | cut -d '=' -f 2)" + echo "Geany version : ${GEANY_VERSION}" + echo "Geany GIT revision : ${GEANY_GIT_REVISION}" + echo "GLib version : ${GLIB_VERSION}" + echo "GTK version : ${GTK_VERSION}" + echo "GCC version : ${COMPILER_VERSION}" + + cat < ${OUTPUT_DIRECTORY}/geany/versions.json + { + "glib_version": "${GLIB_VERSION}", + "gtk_version": "${GTK_VERSION}", + "gcc_version": "${COMPILER_VERSION}", + } +EOT + + # dump and copy test suite log otherwise it would be lost + cat ${GEANY_BUILD_DIR}/tests/ctags/test-suite.log + cp ${GEANY_BUILD_DIR}/tests/ctags/test-suite.log ${OUTPUT_DIRECTORY}/geany +} + + +main() { + git_clone_geany_if_necessary + parse_geany_version + run_autogen_sh + create_tarball_for_debuild + + git_clone_debian_geany + install_build_dependencies + add_changelog_entry + + build_package + copy_results + + log_and_store_build_environment + + log "Done." +} + + +main diff --git a/builders/scripts/build_debian_geany_plugins.sh b/builders/scripts/build_debian_geany_plugins.sh new file mode 100644 index 0000000..be14328 --- /dev/null +++ b/builders/scripts/build_debian_geany_plugins.sh @@ -0,0 +1,183 @@ +#!/bin/bash +# +# Copyright 2022 The Geany contributors +# License: GPLv2 +# +# Helper script to build Debian packages for Geany-Plugins. +# +# This script has to be executed within the Docker container. +# The Docker container should have a bind-mount for ${OUTPUT_DIRECTORY} +# where the resulting packages is stored. +# +# This script is meant to be run in a Docker container. +# + + +GEANY_PLUGINS_VERSION= # will be set below from configure.ac +GEANY_PLUGINS_GIT_REVISION= # will be set below from configure.ac +PACKAGE_VERSION= # will be set below +OUTPUT_DIRECTORY="/output" +GEANY_PLUGINS_GIT_REPOSITORY="https://github.com/geany/geany-plugins.git" +GEANY_PLUGINS_DEBIAN_REPOSITORY="https://salsa.debian.org/geany-team/geany-plugins.git" + +# rather static values, unlikely to be changed +GEANY_PLUGINS_SOURCE_DIR="/geany-plugins-source" +GEANY_PLUGINS_BUILD_DIR="/tmp/geany-plugins-build" +GEANY_PLUGINS_DEBIAN_DIR="/tmp/geany-plugins-debian" + +# for "dch" (debian changelog) +export DEBEMAIL="devel@lists.geany.org" +export DEBFULLNAME="The Geany contributors" + +# stop on errors +set -e + + +log() { + echo "=========== $(date '+%Y-%m-%d %H:%M:%S %Z') $* ===========" +} + + +git_clone_geany_if_necessary() { + log "Clone Geany-Plugins repository (if necessary)" + mkdir -p "$(dirname ${GEANY_PLUGINS_BUILD_DIR})" + if [ -d ${GEANY_PLUGINS_SOURCE_DIR} ]; then + log "Copying Geany-Plugins source" + cp --archive ${GEANY_PLUGINS_SOURCE_DIR}/ ${GEANY_PLUGINS_BUILD_DIR}/ + else + log "Cloning Geany-Plugins repository from ${GEANY_PLUGINS_GIT_REPOSITORY}" + git clone --depth 1 ${GEANY_PLUGINS_GIT_REPOSITORY} ${GEANY_PLUGINS_BUILD_DIR} + fi +} + + +parse_geany_plugins_version() { + log "Parse Geany-Plugins version" + GEANY_PLUGINS_VERSION=$(sed -n -E -e 's/^AC_INIT\(\[geany-plugins\], \[(.+)\]\)/\1/p' ${GEANY_PLUGINS_BUILD_DIR}/configure.ac) + GEANY_PLUGINS_GIT_REVISION=$(cd ${GEANY_PLUGINS_BUILD_DIR} && git rev-parse --short --revs-only HEAD 2>/dev/null || true) + PACKAGE_VERSION="${GEANY_PLUGINS_VERSION}-1~$(date '+%Y%m%d')git${GEANY_PLUGINS_GIT_REVISION}" +} + + +run_autogen_sh() { + log "Run ./autogen.sh" + cd ${GEANY_PLUGINS_BUILD_DIR} + # run ./autogen.sh as the Debian package won't run ./autogen.sh for us + NOCONFIGURE=1 ./autogen.sh +} + + +create_tarball_for_debuild() { + log "Create source tarball" + cd ${GEANY_PLUGINS_BUILD_DIR} + tar --transform "s,^,geany-plugins-${GEANY_PLUGINS_VERSION}/,S" \ + --create \ + --gzip \ + --file "../geany-plugins_${GEANY_PLUGINS_VERSION}.orig.tar.gz" \ + . +} + + +git_clone_debian_geany() { + log "Clone Geany-Plugins Debian repository" + git clone --depth 1 ${GEANY_PLUGINS_DEBIAN_REPOSITORY} ${GEANY_PLUGINS_DEBIAN_DIR} + # move debian package files to Geany GIT checkout + mv ${GEANY_PLUGINS_DEBIAN_DIR}/debian ${GEANY_PLUGINS_BUILD_DIR} +} + + +install_build_dependencies() { + log "Install build dependencies" + cd ${GEANY_PLUGINS_BUILD_DIR} + # install Geany from previous build + dpkg -i \ + ${OUTPUT_DIRECTORY}/geany/geany-common_*git*_all.deb \ + ${OUTPUT_DIRECTORY}/geany/geany_*git*_amd64.deb + + apt-get --assume-yes update + apt-get --assume-yes dist-upgrade + mk-build-deps \ + --install \ + --remove \ + --tool "apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --assume-yes" + # mk-build-deps leave the following files which then break 'debuild' later on + rm -f geany-plugins-build-deps_*-?_amd64.buildinfo geany-plugins-build-deps_*-?_amd64.changes +} + + +add_changelog_entry() { + log "Add ChangeLog entry for Debian package" + cd ${GEANY_PLUGINS_BUILD_DIR} + dch \ + --urgency low \ + --distribution unstable \ + --newversion "${PACKAGE_VERSION}" \ + "Autobuilt by CI or nightly build." +} + + +build_package() { + log "Build Debian package" + cd ${GEANY_PLUGINS_BUILD_DIR} + + debuild -uc -us +} + + +copy_results() { + log "Copy build artefacts" + + BUILD_DIR_DIRNAME=$(dirname ${GEANY_PLUGINS_BUILD_DIR}) + + rm -rf ${OUTPUT_DIRECTORY}/geany-plugins/* + + cp --verbose ${BUILD_DIR_DIRNAME}/geany-plugins_* ${OUTPUT_DIRECTORY}/geany-plugins + cp --verbose ${BUILD_DIR_DIRNAME}/geany-plugins-*_* ${OUTPUT_DIRECTORY}/geany-plugins + cp --verbose ${BUILD_DIR_DIRNAME}/geany-plugin-*_* ${OUTPUT_DIRECTORY}/geany-plugins +} + + +log_and_store_build_environment() { + log "Using environment" + + GTK_VERSION=$(pkg-config --modversion gtk+-3.0) + GLIB_VERSION=$(pkg-config --modversion glib-2.0) + COMPILER_VERSION=$(gcc -dumpfullversion) + + echo "Debian Distribution : $(grep PRETTY_NAME /etc/os-release | cut -d '=' -f 2)" + echo "Geany-Plugins version : ${GEANY_PLUGINS_VERSION}" + echo "Geany-Plugins GIT revision : ${GEANY_PLUGINS_GIT_REVISION}" + echo "GLib version : ${GLIB_VERSION}" + echo "GTK version : ${GTK_VERSION}" + echo "GCC version : ${COMPILER_VERSION}" + + cat < ${OUTPUT_DIRECTORY}/geany-plugins/versions.json + { + "glib_version": "${GLIB_VERSION}", + "gtk_version": "${GTK_VERSION}", + "gcc_version": "${COMPILER_VERSION}", + } +EOT +} + + +main() { + git_clone_geany_if_necessary + parse_geany_plugins_version + run_autogen_sh + create_tarball_for_debuild + + git_clone_debian_geany + install_build_dependencies + add_changelog_entry + + build_package + copy_results + + log_and_store_build_environment + + log "Done." +} + + +main diff --git a/builders/scripts/build_mingw64_geany.sh b/builders/scripts/build_mingw64_geany.sh new file mode 100644 index 0000000..5787129 --- /dev/null +++ b/builders/scripts/build_mingw64_geany.sh @@ -0,0 +1,327 @@ +#!/bin/bash +# +# Copyright 2022 The Geany contributors +# License: GPLv2 +# +# Helper script to build Geany for Windows in a Docker container. +# The following steps are performed: +# - clone Geany repository if necessary (i.e. if it is not bind-mounted into the container) +# - cross-compile Geany for Windows 64bit and GTK3 +# - sign all binaries and installer (if /certificates exist and contains cert.pem and key.pem) +# - download Geany-Themes for bundling +# - create GTK3 bundle with all dependencies (including grep and sort) +# - create the NSIS installer in ${OUTPUT_DIRECTORY} +# - test the created NSIS installer and compiled Geany +# - test uninstaller and check there is nothing left after uninstalling +# +# This script has to be executed within the Docker container. +# The Docker container should have a bind-mount for ${OUTPUT_DIRECTORY} +# where the resulting installer binary is stored. +# +# To test the installer and Geany binary "wine" is used. +# Please note that we need to use wine32 and wine64 as the +# created installer and uninstaller binaries are 32bit whereas the created +# Geany binary is 64bit. +# + +GEANY_VERSION= # will be set below from configure.ac +GEANY_GIT_REVISION= # will be set below from configure.ac +OUTPUT_DIRECTORY="/output" +GEANY_GIT_REPOSITORY="https://github.com/geany/geany.git" +GEANY_THEMES_REPOSITORY="https://github.com/geany/geany-themes.git" + +# rather static values, unlikely to be changed +GTK_BUNDLE_DIR="/build/gtk-bundle" +GEANY_SOURCE_DIR="/geany-source" +GEANY_BUILD_DIR="/build/geany-build" +GEANY_RELEASE_DIR="/build/geany-release" +GEANY_INSTALLER_FILENAME= # will be set below +GEANY_INSTALLATION_DIR_WIN="C:\\geany_install" +GEANY_INSTALLATION_DIR=$(winepath --unix ${GEANY_INSTALLATION_DIR_WIN}) +GEANY_THEMES_DIR="/build/geany-themes" +GEANY_RELEASE_BINARY_PATTERNS=( + "${GEANY_RELEASE_DIR}/bin/geany.exe" + "${GEANY_RELEASE_DIR}/bin/*.dll" + "${GEANY_RELEASE_DIR}/lib/geany/*.dll" +) +GEANY_RELEASE_TEXTFILE_PATTERNS=( + "${GEANY_RELEASE_DIR}/*.txt" + "${GEANY_RELEASE_DIR}/share/doc/geany/*" +) + +# CI CFLAGS +CFLAGS="\ + -Wall \ + -Wextra \ + -O2 \ + -Wunused \ + -Wno-unused-parameter \ + -Wunreachable-code \ + -Wformat=2 \ + -Wundef \ + -Wpointer-arith \ + -Wwrite-strings \ + -Waggregate-return \ + -Wmissing-prototypes \ + -Wmissing-declarations \ + -Wmissing-noreturn \ + -Wmissing-format-attribute \ + -Wredundant-decls \ + -Wnested-externs \ + -Wno-deprecated-declarations" + +# cross-compilation environment +ARCH="x86_64" +MINGW_ARCH="mingw64" +HOST="x86_64-w64-mingw32" +export CC="/usr/bin/${HOST}-gcc" +export CPP="/usr/bin/${HOST}-cpp" +export CXX="/usr/bin/${HOST}-g++" +export AR="/usr/bin/${HOST}-ar" +export STRIP="/usr/bin/${HOST}-strip" +export WINDRES="/usr/bin/${HOST}-windres" +export CFLAGS="-I/windows/${MINGW_ARCH}/include/ ${CFLAGS}" +export LDFLAGS="-static-libgcc ${LDFLAGS}" +export PKG_CONFIG_SYSROOT_DIR="/windows" +export PKG_CONFIG_PATH="/windows/${MINGW_ARCH}/lib/pkgconfig/" +export PKG_CONFIG="/usr/bin/pkg-config" +export NOCONFIGURE=1 + +# stop on errors +set -e + + +log() { + echo "=========== $(date '+%Y-%m-%d %H:%M:%S %Z') $* ===========" +} + + +git_clone_geany_if_necessary() { + if [ -d ${GEANY_SOURCE_DIR} ]; then + log "Copying Geany source" + cp --archive ${GEANY_SOURCE_DIR}/ ${GEANY_BUILD_DIR}/ + else + log "Cloning Geany repository from ${GEANY_GIT_REPOSITORY}" + git clone --depth 1 ${GEANY_GIT_REPOSITORY} ${GEANY_BUILD_DIR} + fi +} + + +parse_geany_version() { + GEANY_VERSION=$(sed -n -E -e 's/^AC_INIT.\[Geany\], \[(.+)\],/\1/p' ${GEANY_BUILD_DIR}/configure.ac) + GEANY_GIT_REVISION=$(cd ${GEANY_BUILD_DIR} && git rev-parse --short --revs-only HEAD 2>/dev/null || true) + TIMESTAMP=$(date +%Y%m%d%H%M%S) + # add pull request number if this is a CI and a PR build + if [ "${GITHUB_PULL_REQUEST}" ]; then + GEANY_VERSION="${GEANY_VERSION}_ci_${TIMESTAMP}_${GEANY_GIT_REVISION}_pr${GITHUB_PULL_REQUEST}" + elif [ "${CI}" -a "${GEANY_GIT_REVISION}" ]; then + GEANY_VERSION="${GEANY_VERSION}_ci_${TIMESTAMP}_${GEANY_GIT_REVISION}" + elif [ "${GEANY_GIT_REVISION}" ]; then + GEANY_VERSION="${GEANY_VERSION}_git_${TIMESTAMP}_${GEANY_GIT_REVISION}" + fi + GEANY_INSTALLER_FILENAME="geany-${GEANY_VERSION}_setup.exe" +} + + +log_environment() { + log "Using environment" + CONFIGURE_OPTIONS="--disable-silent-rules --host=${HOST} --prefix=${GEANY_RELEASE_DIR} --with-libiconv-prefix=/windows/mingw64" + echo "Geany version : ${GEANY_VERSION}" + echo "Geany GIT revision : ${GEANY_GIT_REVISION}" + echo "PATH : ${PATH}" + echo "HOST : ${HOST}" + echo "CC : ${CC}" + echo "CFLAGS : ${CFLAGS}" + echo "Configure : ${CONFIGURE_OPTIONS}" +} + + +patch_version_information() { + log "Patching version information" + + if [ -z "${GEANY_GIT_REVISION}" ] && [ -z "${CI}" ]; then + return + fi + + # parse version string and decrement the patch and/or minor levels to keep nightly build + # versions below the next release version + regex='^([0-9]*)[.]([0-9]*)([.]([0-9]*))?' + if [[ ${GEANY_VERSION} =~ $regex ]]; then + MAJOR="${BASH_REMATCH[1]}" + MINOR="${BASH_REMATCH[2]}" + PATCH="${BASH_REMATCH[4]}" + if [ -z "${PATCH}" ] || [ "${PATCH}" = "0" ]; then + MINOR="$((MINOR-1))" + PATCH="90" + else + PATCH="$((PATCH-1))" + fi + else + echo "Could not extract or parse version tag" >&2 + exit 1 + fi + # replace version information in configure.ac and for Windows binaries + sed -i -E "s/^AC_INIT.\[Geany\], \[(.+)\],/AC_INIT(\[Geany\], \[${GEANY_VERSION}\],/" ${GEANY_BUILD_DIR}/configure.ac + sed -i -E "s/^#define VER_FILEVERSION_STR[[:space:]]+\".*\"+/#define VER_FILEVERSION_STR \"${GEANY_VERSION}\"/" ${GEANY_BUILD_DIR}/geany_private.rc + sed -i -E "s/^#define VER_FILEVERSION[[:space:]]+[0-9,]+/#define VER_FILEVERSION ${MAJOR},${MINOR},${PATCH},90/" ${GEANY_BUILD_DIR}/geany_private.rc + sed -i -E "s/^[[:space:]]+version=\"[0-9.]+\"/version=\"${MAJOR}.${MINOR}.${PATCH}.90\"/" ${GEANY_BUILD_DIR}/geany.exe.manifest + sed -i -E "s/^!define PRODUCT_VERSION \"@VERSION@\"/!define PRODUCT_VERSION \"${GEANY_VERSION}\"/" ${GEANY_BUILD_DIR}/geany.nsi.in + sed -i -E "s/^!define PRODUCT_VERSION_ID \"@VERSION@.0.0\"/!define PRODUCT_VERSION_ID \"${MAJOR}.${MINOR}.${PATCH}.90\"/" ${GEANY_BUILD_DIR}/geany.nsi.in +} + + +build_geany() { + cd ${GEANY_BUILD_DIR} + log "Running autogen.sh" + ./autogen.sh + log "Running configure" + ./configure ${CONFIGURE_OPTIONS} + log "Running make" + make + log "Running install-strip" + make install-strip + + cd / +} + + +sign_file() { + echo "Sign file $1" + if [ -f /certificates/cert.pem ] && [ -f /certificates/key.pem ]; then + osslsigncode sign \ + -certs /certificates/cert.pem \ + -key /certificates/key.pem \ + -n "Geany Binary" \ + -i "https://www.geany.org/" \ + -ts http://zeitstempel.dfn.de/ \ + -h sha512 \ + -in ${1} \ + -out ${1}-signed + mv ${1}-signed ${1} + else + echo "Skip signing due to missing certificate" + fi +} + + +sign_geany_binaries() { + log "Signing Geany binary files" + for binary_file_pattern in ${GEANY_RELEASE_BINARY_PATTERNS[@]}; do + for binary_file in $(ls ${binary_file_pattern}); do + sign_file ${binary_file} + done + done +} + + +convert_text_files_to_crlf() { + log "Converting line endings to CRLF in text files" + for text_file_pattern in ${GEANY_RELEASE_TEXTFILE_PATTERNS[@]}; do + for text_file in $(ls ${text_file_pattern}); do + mime_type=$(file --brief --mime-type ${text_file}) + case $mime_type in text/*) + unix2dos ${text_file} + esac + done + done +} + + +create_gtk_bundle() { + log "Creating GTK bundle" + mkdir ${GTK_BUNDLE_DIR} + cd ${GTK_BUNDLE_DIR} + bash ${GEANY_BUILD_DIR}/scripts/gtk-bundle-from-msys2.sh -x -3 + cd / +} + + +fetch_geany_themes() { + log "Cloning Geany-Themes repository from ${GEANY_THEMES_REPOSITORY}" + git clone --depth 1 ${GEANY_THEMES_REPOSITORY} ${GEANY_THEMES_DIR} +} + + +create_installer() { + log "Creating NSIS installer" + makensis \ + -V3 \ + -WX \ + -DGEANY_INSTALLER_NAME="${GEANY_INSTALLER_FILENAME}" \ + -DGEANY_RELEASE_DIR=${GEANY_RELEASE_DIR} \ + -DGEANY_THEMES_DIR=${GEANY_THEMES_DIR} \ + -DGTK_BUNDLE_DIR=${GTK_BUNDLE_DIR} \ + ${GEANY_BUILD_DIR}/geany.nsi +} + + +sign_installer() { + log "Signing NSIS installer" + sign_file ${GEANY_BUILD_DIR}/${GEANY_INSTALLER_FILENAME} +} + + +test_installer() { + log "Test NSIS installer" + exiftool -FileName -FileType -FileVersion -FileVersionNumber ${GEANY_BUILD_DIR}/${GEANY_INSTALLER_FILENAME} + # install Geany: perform a silent install and check for installed files + mingw-w64-i686-wine ${GEANY_BUILD_DIR}/${GEANY_INSTALLER_FILENAME} /S /D=${GEANY_INSTALLATION_DIR_WIN} + # check if we have something installed + test -f ${GEANY_INSTALLATION_DIR}/uninst.exe || exit 1 + test -f ${GEANY_INSTALLATION_DIR}/bin/geany.exe || exit 1 + test -f ${GEANY_INSTALLATION_DIR}/lib/geany/export.dll || exit 1 + test ! -f ${GEANY_INSTALLATION_DIR}/lib/geany/demoplugin.dll || exit 1 +} + + +log_geany_version() { + log "Log installed Geany version" + mingw-w64-x86_64-wine ${GEANY_INSTALLATION_DIR}/bin/geany.exe --version 2>/dev/null + exiftool -FileName -FileType -FileVersion -FileVersionNumber ${GEANY_INSTALLATION_DIR}/bin/geany.exe +} + + +test_uninstaller() { + log "Test NSIS uninstaller" + # uninstall Geany and test if everything is clean + mingw-w64-i686-wine ${GEANY_INSTALLATION_DIR}/uninst.exe /S + sleep 10 # it seems the uninstaller returns earlier than the files are actually removed, so wait a moment + test ! -e ${GEANY_INSTALLATION_DIR} +} + + +copy_installer_and_bundle() { + log "Copying NSIS installer and GTK bundle" + cp ${GEANY_BUILD_DIR}/${GEANY_INSTALLER_FILENAME} ${OUTPUT_DIRECTORY} + cd ${GTK_BUNDLE_DIR} + zip --quiet --recurse-paths ${OUTPUT_DIRECTORY}/gtk_bundle_$(date '+%Y%m%dT%H%M%S').zip * + cd / +} + + +main() { + git_clone_geany_if_necessary + + parse_geany_version + log_environment + patch_version_information + build_geany + sign_geany_binaries + convert_text_files_to_crlf + + create_gtk_bundle + fetch_geany_themes + create_installer + sign_installer + + test_installer + log_geany_version + test_uninstaller + + copy_installer_and_bundle + + log "Done." +} + + +main diff --git a/builders/scripts/build_mingw64_geany_plugins.sh b/builders/scripts/build_mingw64_geany_plugins.sh new file mode 100644 index 0000000..7f5e807 --- /dev/null +++ b/builders/scripts/build_mingw64_geany_plugins.sh @@ -0,0 +1,357 @@ +#!/bin/bash +# +# Copyright 2022 The Geany contributors +# License: GPLv2 +# +# Helper script to build Geany-Plugins for Windows in a Docker container. +# The following steps are performed: +# - clone Geany-Plugins repository if necessary (i.e. if it is not bind-mounted into the container) +# - cross-compile Geany-Plugins for Windows 64bit and GTK3 +# - sign all binaries and installer (if /certificates exist and contains cert.pem and key.pem) +# - create bundle with all dependencies +# - create the NSIS installer in ${OUTPUT_DIRECTORY} +# - test the created NSIS installer +# - test uninstaller and check there is nothing unexpected left after uninstalling +# +# This script has to be executed within the Docker container. +# The Docker container should have a bind-mount for ${OUTPUT_DIRECTORY} +# where the resulting installer binary is stored. +# +# To test the installer "wine" is used. +# Please note that we need to use wine32 as the created installer and uninstaller +# binaries are 32bit. +# + +GEANY_PLUGINS_VERSION= # will be set below from configure.ac +GEANY_PLUGINS_GIT_REVISION= # will be set below +OUTPUT_DIRECTORY="/output" +GEANY_PLUGINS_GIT_REPOSITORY="https://github.com/geany/geany-plugins.git" + +# rather static values, unlikely to be changed +DEPENDENCY_BUNDLE_DIR="/build/dependencies-bundle" +GEANY_PLUGINS_SOURCE_DIR="/geany-plugins-source" +GEANY_PLUGINS_BUILD_DIR="/build/geany-plugins-build" +GEANY_PLUGINS_RELEASE_DIR="/build/geany-plugins-release" +GEANY_PLUGINS_INSTALLER_FILENAME= # will be set below +GEANY_PLUGINS_INSTALLATION_DIR_WIN="C:\\geany_plugins_install" +GEANY_PLUGINS_INSTALLATION_DIR=$(winepath --unix ${GEANY_PLUGINS_INSTALLATION_DIR_WIN}) +GEANY_PLUGINS_RELEASE_BINARY_PATTERNS=( + "${GEANY_PLUGINS_RELEASE_DIR}/lib/geany/*.dll" + "${GEANY_PLUGINS_RELEASE_DIR}/lib/geany-plugins/geanylua/libgeanylua.dll" + "${GEANY_PLUGINS_RELEASE_DIR}/bin/libgeanypluginutils*.dll" +) + +GEANY_PLUGINS_RELEASE_TEXTFILE_PATTERNS=( + "${GEANY_PLUGINS_RELEASE_DIR}/share/doc/geany-plugins/*" + "${GEANY_PLUGINS_RELEASE_DIR}/share/doc/geany-plugins/*/*" +) +GEANY_INSTALLATION_DIR="/root/.wine/drive_c/geany_install" + +GEANY_INSTALL_DIR_WIN=$(winepath --windows ${GEANY_INSTALLATION_DIR}) +GEANY_INSTALLER_EXECUTABLE=$(ls ${OUTPUT_DIRECTORY}/geany-*_setup.exe) + +# TODO move to include and use it also in Geany build script +# CI CFLAGS +CFLAGS="\ + -Wall \ + -Wextra \ + -O2 \ + -Wunused \ + -Wno-unused-parameter \ + -Wunreachable-code \ + -Wformat=2 \ + -Wundef \ + -Wpointer-arith \ + -Wwrite-strings \ + -Waggregate-return \ + -Wmissing-prototypes \ + -Wmissing-declarations \ + -Wmissing-noreturn \ + -Wmissing-format-attribute \ + -Wredundant-decls \ + -Wnested-externs \ + -Wno-deprecated-declarations" + +# cross-compilation environment +ARCH="x86_64" +MINGW_ARCH="mingw64" +HOST="x86_64-w64-mingw32" +export CC="/usr/bin/${HOST}-gcc" +export CPP="/usr/bin/${HOST}-cpp" +export CXX="/usr/bin/${HOST}-g++" +export AR="/usr/bin/${HOST}-ar" +export STRIP="/usr/bin/${HOST}-strip" +export WINDRES="/usr/bin/${HOST}-windres" +export CFLAGS="-I/windows/${MINGW_ARCH}/include/ ${CFLAGS}" +export LDFLAGS="-static-libgcc ${LDFLAGS}" +export PKG_CONFIG_SYSROOT_DIR="/windows" +export PKG_CONFIG_PATH="/windows/${MINGW_ARCH}/lib/pkgconfig/" +export PKG_CONFIG="/usr/bin/pkg-config" +export PATH="${PATH}:/windows/mingw64/bin" +export NOCONFIGURE=1 + +# stop on errors +set -e + + +log() { + echo "=========== $(date '+%Y-%m-%d %H:%M:%S %Z') $* ===========" +} + + +git_clone_geany_plugins_if_necessary() { + if [ -d ${GEANY_PLUGINS_SOURCE_DIR} ]; then + log "Copying Geany-Plugins source" + cp --archive ${GEANY_PLUGINS_SOURCE_DIR}/ ${GEANY_PLUGINS_BUILD_DIR}/ + else + log "Cloning Geany-Plugins repository from ${GEANY_PLUGINS_GIT_REPOSITORY}" + git clone --depth 1 ${GEANY_PLUGINS_GIT_REPOSITORY} ${GEANY_PLUGINS_BUILD_DIR} + fi +} + + +parse_geany_plugins_version() { + GEANY_PLUGINS_VERSION=$(sed -n -E -e 's/^AC_INIT.\[geany-plugins\], \[(.+)\]./\1/p' ${GEANY_PLUGINS_BUILD_DIR}/configure.ac) + GEANY_PLUGINS_GIT_REVISION=$(cd ${GEANY_PLUGINS_BUILD_DIR} && git rev-parse --short --revs-only HEAD 2>/dev/null || true) + TIMESTAMP=$(date +%Y%m%d%H%M%S) + # add pull request number if this is a CI and a PR build + if [ "${GITHUB_PULL_REQUEST}" ]; then + GEANY_PLUGINS_VERSION="${GEANY_PLUGINS_VERSION}_ci_${TIMESTAMP}_${GEANY_PLUGINS_GIT_REVISION}_pr${GITHUB_PULL_REQUEST}" + elif [ "${CI}" -a "${GEANY_PLUGINS_GIT_REVISION}" ]; then + GEANY_PLUGINS_VERSION="${GEANY_PLUGINS_VERSION}_ci_${TIMESTAMP}_${GEANY_PLUGINS_GIT_REVISION}" + elif [ "${GEANY_PLUGINS_GIT_REVISION}" ]; then + GEANY_PLUGINS_VERSION="${GEANY_PLUGINS_VERSION}_git_${TIMESTAMP}_${GEANY_PLUGINS_GIT_REVISION}" + fi + GEANY_PLUGINS_INSTALLER_FILENAME="geany-plugins-${GEANY_PLUGINS_VERSION}_setup.exe" +} + + +log_environment() { + log "Using environment" + CONFIGURE_OPTIONS="--disable-silent-rules --host=${HOST} --prefix=${GEANY_PLUGINS_RELEASE_DIR} --with-geany-libdir=${GEANY_PLUGINS_RELEASE_DIR}/lib" + echo "Geany-Plugins version : ${GEANY_PLUGINS_VERSION}" + echo "Geany-Plugins GIT revision : ${GEANY_PLUGINS_GIT_REVISION}" + echo "Geany installer : ${GEANY_INSTALLER_EXECUTABLE}" + echo "PATH : ${PATH}" + echo "HOST : ${HOST}" + echo "CC : ${CC}" + echo "CFLAGS : ${CFLAGS}" + echo "Configure : ${CONFIGURE_OPTIONS}" +} + + +patch_version_information() { + log "Patching version information" + + if [ -z "${GEANY_PLUGINS_GIT_REVISION}" ]; then + return + fi + + # parse version string and decrement the patch and/or minor levels to keep nightly build + # versions below the next release version + regex='^([0-9]*)[.]([0-9]*)([.]([0-9]*))?' + if [[ ${GEANY_PLUGINS_VERSION} =~ $regex ]]; then + MAJOR="${BASH_REMATCH[1]}" + MINOR="${BASH_REMATCH[2]}" + PATCH="${BASH_REMATCH[4]}" + if [ -z "${PATCH}" ] || [ "${PATCH}" = "0" ]; then + MINOR="$((MINOR-1))" + PATCH="90" + else + PATCH="$((PATCH-1))" + fi + else + echo "Could not extract or parse version tag" >&2 + exit 1 + fi + # replace version information in configure.ac and for Windows binaries + sed -i -E "s/^AC_INIT.\[geany-plugins\], \[(.+)\],/AC_INIT(\[geany-plugins\], \[${GEANY_PLUGINS_VERSION}\],/" ${GEANY_PLUGINS_BUILD_DIR}/configure.ac + sed -i -E "s/^!define PRODUCT_VERSION \"(.+)\"/!define PRODUCT_VERSION \"${GEANY_PLUGINS_VERSION}\"/" ${GEANY_PLUGINS_BUILD_DIR}/build/geany-plugins.nsi + sed -i -E "s/^!define PRODUCT_VERSION_ID \"(.+)\"/!define PRODUCT_VERSION_ID \"${MAJOR}.${MINOR}.${PATCH}.90\"/" ${GEANY_PLUGINS_BUILD_DIR}/build/geany-plugins.nsi + sed -i -E "s/^!define REQUIRED_GEANY_VERSION \"(.+)\"/!define REQUIRED_GEANY_VERSION \"${MAJOR}.${MINOR}\"/" ${GEANY_PLUGINS_BUILD_DIR}/build/geany-plugins.nsi +} + + +install_dependencies() { + log "Installing build dependencies" + pacman --noconfirm -Syu + pacman --noconfirm -S \ + mingw-w64-${ARCH}-check \ + mingw-w64-${ARCH}-cppcheck \ + mingw-w64-${ARCH}-ctpl-git \ + mingw-w64-${ARCH}-enchant \ + mingw-w64-${ARCH}-gpgme \ + mingw-w64-${ARCH}-gtkspell3 \ + mingw-w64-${ARCH}-libgit2 \ + mingw-w64-${ARCH}-libsoup \ + mingw-w64-${ARCH}-lua51 +} + + +install_geany() { + log "Installing Geany (using wine)" + if [ -z "${GEANY_INSTALLER_EXECUTABLE}" -o ! -f "${GEANY_INSTALLER_EXECUTABLE}" ]; then + echo "No Geany installer found" + exit 1 + fi + mingw-w64-i686-wine ${GEANY_INSTALLER_EXECUTABLE} /S /D=${GEANY_INSTALL_DIR_WIN} + + # TODO the following steps are way too hacky: installing Geany from the installer is basically + # what we want for CI tests but the installed "geany.pc" file isn't really suitable + # for cross-compiling + + # add the Geany installation directory to the PKG_CONFIG_PATH + export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${GEANY_INSTALLATION_DIR}/lib/pkgconfig/" + # patch Geany pkg-config prefix: pkg-config always prepend "/windows" to the "prefix" variable, so we + # need to add ../ to get out of the hardcoded "/windows" path element + sed -i "s%^\(prefix=\).*$%\1/..${GEANY_INSTALLATION_DIR}%" ${GEANY_INSTALLATION_DIR}/lib/pkgconfig/geany.pc + sed -i "s%^\(exec_prefix=\).*$%\1/..${GEANY_INSTALLATION_DIR}%" ${GEANY_INSTALLATION_DIR}/lib/pkgconfig/geany.pc + # we need "${exec_prefix}/bin" additionally for libgeany-0.dll which is installed into bin/ and replace -lgeany by -lgeany-0 + sed -i "s%^Libs: -L\${libdir} -lgeany$%Libs: -L\${libdir} -L\${exec_prefix}/bin -lgeany-0%" ${GEANY_INSTALLATION_DIR}/lib/pkgconfig/geany.pc +} + + +build_geany_plugins() { + cd ${GEANY_PLUGINS_BUILD_DIR} + log "Running autogen.sh" + ./autogen.sh + log "Running configure" + ./configure ${CONFIGURE_OPTIONS} + log "Running make" + make + log "Running install-strip" + make install-strip + + cd / +} + + +sign_file() { + echo "Sign file $1" + if [ -f /certificates/cert.pem ] && [ -f /certificates/key.pem ]; then + osslsigncode sign \ + -certs /certificates/cert.pem \ + -key /certificates/key.pem \ + -n "Geany-Plugins Binary" \ + -i "https://www.geany.org/" \ + -ts http://zeitstempel.dfn.de/ \ + -h sha512 \ + -in ${1} \ + -out ${1}-signed + mv ${1}-signed ${1} + else + echo "Skip signing due to missing certificate" + fi +} + + +sign_geany_plugins_binaries() { + log "Signing Geany-Plugins binary files" + for binary_file_pattern in ${GEANY_PLUGINS_RELEASE_BINARY_PATTERNS[@]}; do + for binary_file in $(ls ${binary_file_pattern}); do + sign_file ${binary_file} + done + done +} + + +convert_text_files_to_crlf() { + log "Converting line endings to CRLF in text files" + for text_file_pattern in ${GEANY_PLUGINS_RELEASE_TEXTFILE_PATTERNS[@]}; do + for text_file in $(ls ${text_file_pattern}); do + mime_type=$(file --brief --mime-type ${text_file}) + case $mime_type in text/*) + unix2dos ${text_file} + esac + done + done +} + + +create_dependencies_bundle() { + log "Creating Geany-Plugins dependencies bundle" + mkdir ${DEPENDENCY_BUNDLE_DIR} + cd ${DEPENDENCY_BUNDLE_DIR} + bash ${GEANY_PLUGINS_BUILD_DIR}/build/gtk-bundle-from-msys2.sh -x -3 + cd / +} + + +create_installer() { + log "Creating NSIS installer" + makensis \ + -V3 \ + -WX \ + -DGEANY_PLUGINS_INSTALLER_NAME="${GEANY_PLUGINS_INSTALLER_FILENAME}" \ + -DGEANY_PLUGINS_RELEASE_DIR=${GEANY_PLUGINS_RELEASE_DIR} \ + -DDEPENDENCY_BUNDLE_DIR=${DEPENDENCY_BUNDLE_DIR} \ + ${GEANY_PLUGINS_BUILD_DIR}/build/geany-plugins.nsi +} + + +sign_installer() { + log "Signing NSIS installer" + sign_file ${GEANY_PLUGINS_BUILD_DIR}/build/${GEANY_PLUGINS_INSTALLER_FILENAME} +} + + +test_installer() { + log "Test NSIS installer" + # perform a silent install and check for installed files + exiftool -FileName -FileType -FileVersion -FileVersionNumber ${GEANY_PLUGINS_BUILD_DIR}/build/${GEANY_PLUGINS_INSTALLER_FILENAME} + # install Geany-Plugins + mingw-w64-i686-wine ${GEANY_PLUGINS_BUILD_DIR}/build/${GEANY_PLUGINS_INSTALLER_FILENAME} /S /D=${GEANY_PLUGINS_INSTALLATION_DIR_WIN} + # check if we have something installed + ls -l ${GEANY_PLUGINS_INSTALLATION_DIR}/uninst-plugins.exe || exit 1 + ls -l ${GEANY_PLUGINS_INSTALLATION_DIR}/lib/geany/addons.dll || exit 1 +} + + +test_uninstaller() { + log "Test NSIS uninstaller" + # uninstall Geany-Plugins and test if everything is clean + mingw-w64-i686-wine ${GEANY_PLUGINS_INSTALLATION_DIR}/uninst-plugins.exe /S + sleep 15 # it seems the uninstaller returns earlier than the files are actually removed, so wait a moment + rest=$(find ${GEANY_PLUGINS_INSTALLATION_DIR} \( -path '*share/locale' -o -path '*share/licenses' \) -prune -false -o -true -printf '%P ') + if [ "${rest}" != " share share/locale share/licenses " ]; then + # do not treat this as error, it might happen if upstream dependencies have been updated, + # the list of files to be removed needs to be updated only before releases + echo "WARNING: Uninstaller failed to uninstall the following files files: ${rest}" + fi +} + + +copy_installer_and_bundle() { + log "Copying NSIS installer and dependencies bundle" + cp ${GEANY_PLUGINS_BUILD_DIR}/build/${GEANY_PLUGINS_INSTALLER_FILENAME} ${OUTPUT_DIRECTORY} + cd ${DEPENDENCY_BUNDLE_DIR} + zip --quiet --recurse-paths ${OUTPUT_DIRECTORY}/geany_plugins_dependencies_bundle_$(date '+%Y%m%dT%H%M%S').zip * + cd / +} + + +main() { + git_clone_geany_plugins_if_necessary + + parse_geany_plugins_version + log_environment + patch_version_information + install_dependencies + install_geany + build_geany_plugins + sign_geany_plugins_binaries + convert_text_files_to_crlf + + create_dependencies_bundle + create_installer + sign_installer + copy_installer_and_bundle + + test_installer + test_uninstaller + + log "Done." +} + + +main diff --git a/builders/scripts/update_debian_repositories.sh b/builders/scripts/update_debian_repositories.sh new file mode 100644 index 0000000..f438dd2 --- /dev/null +++ b/builders/scripts/update_debian_repositories.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# +# Copyright 2022 The Geany contributors +# License: GPLv2 +# +# Create a Debian repository for the Debian distribution +# requested in the environment variable ${DISTRO}. +# The repository will be signed with the GnuPG key as found +# in /gnupg (which must be provided from the caller). +# +# This script is meant to be run in a Docker container. +# + + +# codename -> suite mapping +declare -A SUITES=([buster]=stable [sid]=unstable) + +# stop on errors +set -e + +# cleanup +rm -rf /repository/conf +rm -rf /repository/db +rm -rf /repository/dists +rm -rf /repository/pool + +# create repository config +mkdir /repository/conf +cat << CONF > /repository/conf/distributions +Codename: ${DISTRO} +Suite: ${SUITES[${DISTRO}]} +Components: main +Architectures: amd64 source +SignWith: ${GNUPG_KEYID} +CONF + +# create repository +reprepro --silent --gnupghome /gnupg -b /repository createsymlinks +package_paths=`find /output -name '*.deb'` +for package in ${package_paths} +do + reprepro --silent --gnupghome /gnupg -b /repository includedeb ${DISTRO} ${package} +done +# add source packages +dsc_paths=`find /output -name '*.dsc'` +for dsc in ${dsc_paths} +do + reprepro --silent --gnupghome /gnupg -b /repository includedsc ${DISTRO} ${dsc} +done diff --git a/builders/start_build.sh b/builders/start_build.sh new file mode 100644 index 0000000..a01670d --- /dev/null +++ b/builders/start_build.sh @@ -0,0 +1,294 @@ +#!/bin/bash +# +# Copyright 2022 The Geany contributors +# License: GPLv2 +# +# Run Debian and Windows build containers and start builds within. +# The Docker image for the containers are rebuilt automatically +# every 30 days to keep them up to date. +# +# This script has to be run outside of the containers. +# +# usage: start_build.sh [-d|--distro DISTRO] [-m|--mingw64] +# [-r|--rebuild-images] +# -d, --distro DISTRO Build for target Debian DISTRO (e.g. "bullseye", +# can be specified multiple times +# -f, --force-rebuild Force rebuilding of immages even if not necessary +# -g, --geany Build Geany +# --geany-source Path to a Geany source directory (optional, cloned from GIT if missing) +# --geany-plugins-source Path to a Geany-Plugins source directory (optional, cloned from GIT if missing) +# -h Show this help screen +# -l, --log-to-stdout Log build output additionally to stdout +# -m, --mingw64 Build for target Mingw-w64 +# -p, --geany-plugins Build Geany-Plugins +# -r, --rebuild-images Rebuild Docker images before start building +# (images are rebuilt automatically every 30 days) +# -s, --sudo Use "sudo" for Docker commands + + +DOCKER_IMAGE_MAX_AGE_DAYS=30 +# GNUPG config for the Debian repository, path and key must exist on the local machine +GNUPG_HOME=${GNUPG_HOME:-~/.gnupg} +GNUPG_KEYID=${GNUPG_KEYID:-0EE5B5AD} + +BASE_OUTPUT_DIRECTORY="${PWD}/output/" +DOCKER_CMD="docker" +GEANY_SOURCE= +GEANY_PLUGINS_SOURCE= + +# stop on errors +set -e +set -o pipefail + + +log() { + log_filename="$1" + shift + if [ "${log_filename}" = "-" ]; then + echo "========== $(date '+%Y-%m-%d %H:%M:%S %Z') $@ ==========" + else + if [ -n "${DO_LOG_TO_STDOUT}" ]; then + $@ 2>&1 | tee "${log_filename}" + else + $@ > "${log_filename}" 2>&1 + fi + fi +} + + +rebuild_image() { + image_name="$1" + dockerfile="$2" + build_args="$3" + # query image created date or use 0 if the image does not exist to trigger a build + image_date=$(${DOCKER_CMD} image inspect --format='{{.Created}}' "${image_name}" 2>/dev/null || echo -n 1970-01-01) + image_date=$(echo "${image_date}" | xargs) # trim leading and trailing whitespace + image_date_seconds=$(date --date="${image_date}" "+%s") + expire_date_seconds=$(date --date="${DOCKER_IMAGE_MAX_AGE_DAYS} days ago" "+%s") + if [ "${image_date_seconds}" -lt "${expire_date_seconds}" ] || [ -n "${DO_FORCE_IMAGE_REBUILD}" ]; then + log - "Building image ${image_name} (last build: ${image_date})" + log "${BASE_OUTPUT_DIRECTORY}/docker_image_build_${image_name}_$(date '+%Y_%m_%d_%H_%M_%S').log" \ + ${DOCKER_CMD} build \ + --no-cache \ + --file "${dockerfile}" \ + --label "org.opencontainers.image.created=$(date --iso-8601=seconds)" \ + --tag "${image_name}" \ + ${build_args} \ + . + fi +} + + +build_for_debian_distro() { + distro=${1} + IMAGE_NAME_DEBIAN="geany-debian-${distro}-ci" + OUTPUT_DIRECTORY=${BASE_OUTPUT_DIRECTORY}/${distro} + LOGFILE_GEANY=${OUTPUT_DIRECTORY}/build_debian_${distro}_geany_$(date '+%Y_%m_%d_%H_%M_%S').log + LOGFILE_GEANY_PLUGINS=${OUTPUT_DIRECTORY}/build_debian_${distro}_geany_plugins_$(date '+%Y_%m_%d_%H_%M_%S').log + + mkdir -p "${OUTPUT_DIRECTORY}/geany" "${OUTPUT_DIRECTORY}/geany-plugins" + + # (re)build Docker image + rebuild_image "${IMAGE_NAME_DEBIAN}" Dockerfile.debian "--build-arg BASE_IMAGE_NAME=debian:${distro}" + + # build Geany + if [ -n "${DO_GEANY}" ]; then + log - "Building Geany for ${distro}" + log "${LOGFILE_GEANY}" \ + ${DOCKER_CMD} run \ + --rm \ + --env=GITHUB_PULL_REQUEST="${GITHUB_PULL_REQUEST}" \ + --env=CI="${CI}" \ + --volume "${PWD}/scripts:/scripts/" \ + --volume "${OUTPUT_DIRECTORY}:/output/" \ + --tmpfs /tmp:rw,exec,size=1024m \ + "${IMAGE_NAME_DEBIAN}:latest" \ + bash /scripts/build_debian_geany.sh + fi + + # build Geany-Plugins + if [ -n "${DO_GEANY_PLUGINS}" ]; then + log - "Building Geany-Plugins for ${distro}" + log "${LOGFILE_GEANY_PLUGINS}" \ + ${DOCKER_CMD} run \ + --rm \ + --env=GITHUB_PULL_REQUEST="${GITHUB_PULL_REQUEST}" \ + --env=CI="${CI}" \ + --volume "${PWD}/scripts:/scripts/" \ + --volume "${OUTPUT_DIRECTORY}:/output/" \ + --tmpfs /tmp:rw,exec,size=1024m \ + "${IMAGE_NAME_DEBIAN}:latest" \ + bash /scripts/build_debian_geany_plugins.sh + fi + + # build/update Debian repository + log - "Update Debian repository for ${distro}" + log "${OUTPUT_DIRECTORY}/build_debian_repository_$(date '+%Y_%m_%d_%H_%M_%S').log" \ + ${DOCKER_CMD} run \ + --rm \ + --env GNUPG_KEYID="${GNUPG_KEYID}" \ + --env DISTRO="${distro}" \ + --volume "${PWD}/scripts:/scripts/" \ + --volume "${GNUPG_HOME}:/gnupg/" \ + --volume "${OUTPUT_DIRECTORY}:/output/" \ + --volume "${BASE_OUTPUT_DIRECTORY}/repositories/${distro}:/repository/" \ + "${IMAGE_NAME_DEBIAN}:latest" \ + bash /scripts/update_debian_repositories.sh +} + + +build_mingw64() { + IMAGE_NAME_WINDOWS="geany-mingw64-ci" + MINGW64_OUTPUT_DIRECTORY=${BASE_OUTPUT_DIRECTORY}/mingw64 + LOGFILE_MINGW64_GEANY=${MINGW64_OUTPUT_DIRECTORY}/build_mingw64_geany_$(date '+%Y_%m_%d_%H_%M_%S').log + LOGFILE_MINGW64_GEANY_PLUGINS=${MINGW64_OUTPUT_DIRECTORY}/build_mingw64_geany_plugins_$(date '+%Y_%m_%d_%H_%M_%S').log + mkdir -p "${MINGW64_OUTPUT_DIRECTORY}" + + # (re)build Docker image + rebuild_image ${IMAGE_NAME_WINDOWS} Dockerfile.mingw64 + + # Build Geany + if [ -n "${DO_GEANY}" ]; then + log - "Building Geany for Windows" + if [ -n "${GEANY_SOURCE}" ]; then + source_volume="--volume ${GEANY_SOURCE}:/geany-source/:ro" + else + source_volume= + fi + log "${LOGFILE_MINGW64_GEANY}" \ + ${DOCKER_CMD} run \ + --rm \ + --env=GITHUB_PULL_REQUEST="${GITHUB_PULL_REQUEST}" \ + --env=CI="${CI}" \ + ${source_volume} \ + --volume "${PWD}/scripts:/scripts/" \ + --volume "${PWD}/certificates/:/certificates/" \ + --volume "${MINGW64_OUTPUT_DIRECTORY}:/output/" \ + "${IMAGE_NAME_WINDOWS}:latest" \ + bash /scripts/build_mingw64_geany.sh + fi + + # Build Geany-Plugins + if [ -n "${DO_GEANY_PLUGINS}" ]; then + log - "Building Geany-Plugins for Windows" + if [ -n "${GEANY_PLUGINS_SOURCE}" ]; then + source_volume="--volume ${GEANY_PLUGINS_SOURCE}:/geany-plugins-source/:ro" + else + source_volume= + fi + log "${LOGFILE_MINGW64_GEANY_PLUGINS}" \ + ${DOCKER_CMD} run \ + --rm \ + --env=GITHUB_PULL_REQUEST="${GITHUB_PULL_REQUEST}" \ + --env=CI="${CI}" \ + ${source_volume} \ + --volume "${PWD}/scripts:/scripts/" \ + --volume "${PWD}/certificates/:/certificates/" \ + --volume "${MINGW64_OUTPUT_DIRECTORY}:/output/" \ + "${IMAGE_NAME_WINDOWS}:latest" \ + bash /scripts/build_mingw64_geany_plugins.sh + fi +} + + +usage() { + echo "usage: start_build.sh [-d|--distro DISTRO] [-m|--mingw64]" + echo " [-r|--rebuild-images]" + echo " -d, --distro DISTRO Build for target Debian DISTRO (e.g. \"bullseye\"," + echo " can be specified multiple times" + echo " -g, --geany Build Geany" + echo "--geany-source Path to a Geany source directory (optional, cloned from GIT if missing)" + echo "--geany-plugins-source Path to a Geany-Plugins source directory (optional, cloned from GIT if missing)" + echo " -h Show this help screen" + echo " -l, --log-to-stdout Log build output additionally to stdout" + echo " -m, --mingw64 Build for target Mingw-w64" + echo " -p, --geany-plugins Build Geany-Plugins" + echo " -r, --rebuild-images Rebuild Docker images before start building" + echo " (images are rebuilt automatically every ${DOCKER_IMAGE_MAX_AGE_DAYS} days)" + echo " -s, --sudo Use \"sudo\" for Docker commands" + exit 1 +} + + +parse_command_line_options() { + if [ $# -eq 0 ]; then + usage + fi + for opt in "$@"; do + case "$opt" in + -d|--distro) + DO_DISTRO="${DO_DISTRO} ${2}" + shift + shift + ;; + -f|--force-rebuild) + DO_FORCE_IMAGE_REBUILD=1 + shift + ;; + -g|--geany) + DO_GEANY=1 + shift + ;; + --geany-source) + GEANY_SOURCE="${2}" + shift + shift + ;; + --geany-plugins-source) + GEANY_PLUGINS_SOURCE="${2}" + shift + shift + ;; + -l|--log-to-stdout) + DO_LOG_TO_STDOUT=1 + shift + ;; + -m|--mingw64) + DO_MINGW64=1 + shift + ;; + -p|--geany-plugins) + DO_GEANY_PLUGINS=1 + shift + ;; + -r|--rebuild-images) + DO_IMAGE_REBUILD=1 + shift + ;; + -s|--sudo) + DOCKER_CMD="sudo docker" + shift + ;; + -h|--help) + usage + ;; + esac + done +} + + +DO_DISTRO= +DO_MINGW64= +DO_IMAGE_REBUILD= +DO_FORCE_IMAGE_REBUILD= +DO_GEANY= +DO_GEANY_PLUGINS= +DO_LOG_TO_STDOUT= +GEANY_SOURCE= +GEANY_PLUGINS_SOURCE= + + +main() { + if [ -n "${DO_DISTRO}" ]; then + for distro in ${DO_DISTRO}; do + build_for_debian_distro "${distro}" + done + fi + if [ -n "${DO_MINGW64}" ]; then + build_mingw64 + fi +} + + +parse_command_line_options $@ +main