3 # Copyright 2022 The Geany contributors
6 # Helper script to build Geany for Windows in a Docker container.
7 # The following steps are performed:
8 # - clone Geany repository if necessary (i.e. if it is not bind-mounted into the container)
9 # - cross-compile Geany for Windows 64bit and GTK3
10 # - sign all binaries and installer (if /certificates exist and contains cert.pem and key.pem)
11 # - download Geany-Themes for bundling
12 # - create GTK3 bundle with all dependencies (including grep and sort)
13 # - create the NSIS installer in ${OUTPUT_DIRECTORY}
14 # - test the created NSIS installer and compiled Geany
15 # - test uninstaller and check there is nothing left after uninstalling
17 # This script has to be executed within the Docker container.
18 # The Docker container should have a bind-mount for ${OUTPUT_DIRECTORY}
19 # where the resulting installer binary is stored.
21 # To test the installer and Geany binary "wine" is used.
22 # Please note that we need to use wine32 and wine64 as the
23 # created installer and uninstaller binaries are 32bit whereas the created
24 # Geany binary is 64bit.
27 GEANY_VERSION
= # will be set below from configure.ac
28 GEANY_GIT_REVISION
= # will be set below from configure.ac
29 OUTPUT_DIRECTORY
="/output"
30 GEANY_GIT_REPOSITORY
="https://github.com/geany/geany.git"
31 GEANY_THEMES_REPOSITORY
="https://github.com/geany/geany-themes.git"
33 # rather static values, unlikely to be changed
34 GTK_BUNDLE_DIR
="/build/gtk-bundle"
35 GEANY_SOURCE_DIR
="/geany-source"
36 GEANY_BUILD_DIR
="/build/geany-build"
37 GEANY_RELEASE_DIR
="/build/geany-release"
38 GEANY_INSTALLER_FILENAME
= # will be set below
39 GEANY_INSTALLATION_DIR_WIN
="C:\\geany_install"
40 GEANY_INSTALLATION_DIR
=$
(winepath
--unix ${GEANY_INSTALLATION_DIR_WIN})
41 GEANY_THEMES_DIR
="/build/geany-themes"
42 GEANY_RELEASE_BINARY_PATTERNS
=(
43 "${GEANY_RELEASE_DIR}/bin/geany.exe"
44 "${GEANY_RELEASE_DIR}/bin/*.dll"
45 "${GEANY_RELEASE_DIR}/lib/geany/*.dll"
54 -Wno-unused-parameter \
61 -Wmissing-prototypes \
62 -Wmissing-declarations \
64 -Wmissing-format-attribute \
67 -Wno-deprecated-declarations"
69 # cross-compilation environment
72 HOST
="x86_64-w64-mingw32"
73 export LDFLAGS
="-static-libgcc ${LDFLAGS}"
74 export PKG_CONFIG_SYSROOT_DIR
="/windows"
75 export PKG_CONFIG_PATH
="/windows/${MINGW_ARCH}/lib/pkgconfig/"
77 export JOBS
=${JOBS:-1}
78 export lt_cv_deplibs_check_method
='pass_all'
85 echo "=========== $(date '+%Y-%m-%d %H:%M:%S %Z') $* ==========="
89 git_clone_geany_if_necessary
() {
90 if [ -d ${GEANY_SOURCE_DIR} ]; then
91 log
"Copying Geany source"
92 cp --archive ${GEANY_SOURCE_DIR}/ ${GEANY_BUILD_DIR}/
93 chown
--recursive $
(id
-u):$
(id
-g) ${GEANY_BUILD_DIR}/
95 log
"Cloning Geany repository from ${GEANY_GIT_REPOSITORY}"
96 git clone
--depth 1 ${GEANY_GIT_REPOSITORY} ${GEANY_BUILD_DIR}
101 parse_geany_version
() {
102 GEANY_VERSION
=$
(sed -n -E -e 's/^AC_INIT.\[Geany\], \[(.+)\],/\1/p' ${GEANY_BUILD_DIR}/configure.ac
)
103 GEANY_GIT_REVISION
=$
(cd ${GEANY_BUILD_DIR} && git rev-parse
--short --revs-only HEAD
2>/dev
/null || true
)
104 TIMESTAMP
=$
(date +%Y
%m
%d
%H
%M
%S
)
105 # add pull request number if this is a CI and a PR build
106 if [ "${GITHUB_PULL_REQUEST}" ]; then
107 GEANY_VERSION
="${GEANY_VERSION}_ci_${TIMESTAMP}_${GEANY_GIT_REVISION}_pr${GITHUB_PULL_REQUEST}"
108 elif [ "${CI}" -a "${GEANY_GIT_REVISION}" ]; then
109 GEANY_VERSION
="${GEANY_VERSION}_ci_${TIMESTAMP}_${GEANY_GIT_REVISION}"
110 elif [ "${GEANY_GIT_REVISION}" ]; then
111 GEANY_VERSION
="${GEANY_VERSION}_git_${TIMESTAMP}_${GEANY_GIT_REVISION}"
113 GEANY_INSTALLER_FILENAME
="geany-${GEANY_VERSION}_setup.exe"
118 log
"Using environment"
119 CONFIGURE_OPTIONS
="--disable-silent-rules --host=${HOST} --prefix=${GEANY_RELEASE_DIR} --with-libiconv-prefix=/windows/mingw64"
120 echo "Geany version : ${GEANY_VERSION}"
121 echo "Geany GIT revision : ${GEANY_GIT_REVISION}"
122 echo "PATH : ${PATH}"
123 echo "HOST : ${HOST}"
124 echo "GCC : $(${HOST}-gcc -dumpfullversion) ($(${HOST}-gcc -dumpversion))"
125 echo "G++ : $(${HOST}-g++ -dumpfullversion) ($(${HOST}-g++ -dumpversion))"
126 echo "Libstdc++ : $(dpkg-query --showformat='${Version}' --show libstdc++6:i386)"
127 echo "GLib : $(pkg-config --modversion glib-2.0)"
128 echo "GTK : $(pkg-config --modversion gtk+-3.0)"
129 echo "CFLAGS : ${CFLAGS}"
130 echo "Configure : ${CONFIGURE_OPTIONS}"
134 patch_version_information
() {
135 log
"Patching version information"
137 if [ -z "${GEANY_GIT_REVISION}" ] && [ -z "${CI}" ]; then
141 # parse version string and decrement the patch and/or minor levels to keep nightly build
142 # versions below the next release version
143 regex
='^([0-9]*)[.]([0-9]*)([.]([0-9]*))?'
144 if [[ ${GEANY_VERSION} =~
$regex ]]; then
145 MAJOR
="${BASH_REMATCH[1]}"
146 MINOR
="${BASH_REMATCH[2]}"
147 PATCH
="${BASH_REMATCH[4]}"
148 if [ -z "${PATCH}" ] ||
[ "${PATCH}" = "0" ]; then
149 if [ "${MINOR}" = "0" ]; then
160 echo "Could not extract or parse version tag" >&2
163 # replace version information in configure.ac and for Windows binaries
164 sed -i -E "s/^AC_INIT.\[Geany\], \[(.+)\],/AC_INIT(\[Geany\], \[${GEANY_VERSION}\],/" ${GEANY_BUILD_DIR}/configure.ac
165 sed -i -E "s/^#define VER_FILEVERSION_STR[[:space:]]+\".*\"+/#define VER_FILEVERSION_STR \"${GEANY_VERSION}\"/" ${GEANY_BUILD_DIR}/geany_private.rc
166 sed -i -E "s/^#define VER_FILEVERSION[[:space:]]+[0-9,]+/#define VER_FILEVERSION ${MAJOR},${MINOR},${PATCH},90/" ${GEANY_BUILD_DIR}/geany_private.rc
167 sed -i -E "s
/^
[[:space
:]]+version
=\"[0-9.
]+\"/version
=\"${MAJOR}.${MINOR}.${PATCH}.90\"/" ${GEANY_BUILD_DIR}/geany.exe.manifest
168 sed -i -E "s/^!define PRODUCT_VERSION \"@VERSION@\"/!define PRODUCT_VERSION \"${GEANY_VERSION}\"/" ${GEANY_BUILD_DIR}/geany.nsi.
in
169 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
174 cd ${GEANY_BUILD_DIR}
175 log "Running autogen.sh
"
177 log "Running configure
"
178 ./configure ${CONFIGURE_OPTIONS}
181 log "Running install-strip
"
188 if [ -f /certificates/cert.pem ] && [ -f /certificates/key.pem ]; then
190 -certs /certificates/cert.pem \
191 -key /certificates/key.pem \
193 -i "https
://www.geany.org
/" \
194 -ts http://zeitstempel.dfn.de/ \
200 echo "Skip signing due to missing certificate
"
205 sign_geany_binaries() {
206 log "Signing Geany binary files
"
207 for binary_file_pattern in ${GEANY_RELEASE_BINARY_PATTERNS[@]}; do
208 for binary_file in $(ls ${binary_file_pattern}); do
209 sign_file ${binary_file}
215 create_gtk_bundle() {
216 log "Creating GTK bundle
"
217 mkdir ${GTK_BUNDLE_DIR}
219 bash ${GEANY_BUILD_DIR}/scripts/gtk-bundle-from-msys2.sh -x -3
221 # We use the "posix
" variant of the mingw64 cross compiler which has support for
222 # C++ features like "std
:future
". For this to work, we need to use the corresponding
223 # C++ runtime library and copy (and strip) it to the resulting bundle.
224 gcc_version="$
(${HOST}-gcc -dumpversion)/libstdc
++-6.dll
"
225 cp "/usr
/lib
/gcc
/${HOST}/${gcc_version}" "${GTK_BUNDLE_DIR}/bin
"
226 ${HOST}-strip "${GTK_BUNDLE_DIR}/bin
/libstdc
++-6.dll
"
230 fetch_geany_themes() {
231 log "Cloning Geany-Themes repository from
${GEANY_THEMES_REPOSITORY}"
232 git clone --depth 1 ${GEANY_THEMES_REPOSITORY} ${GEANY_THEMES_DIR}
237 log "Creating NSIS installer
"
241 -DGEANY_INSTALLER_NAME="${GEANY_INSTALLER_FILENAME}" \
242 -DGEANY_RELEASE_DIR=${GEANY_RELEASE_DIR} \
243 -DGEANY_THEMES_DIR=${GEANY_THEMES_DIR} \
244 -DGTK_BUNDLE_DIR=${GTK_BUNDLE_DIR} \
245 ${GEANY_BUILD_DIR}/geany.nsi
250 log "Signing NSIS installer
"
251 sign_file ${GEANY_BUILD_DIR}/${GEANY_INSTALLER_FILENAME}
256 log "Test NSIS installer
"
257 exiftool -FileName -FileType -FileVersion -FileVersionNumber ${GEANY_BUILD_DIR}/${GEANY_INSTALLER_FILENAME}
258 # install Geany: perform a silent install and check for installed files
259 mingw-w64-i686-wine ${GEANY_BUILD_DIR}/${GEANY_INSTALLER_FILENAME} /S /D=${GEANY_INSTALLATION_DIR_WIN}
260 # check if we have something installed
261 test -f ${GEANY_INSTALLATION_DIR}/uninst.exe || exit 1
262 test -f ${GEANY_INSTALLATION_DIR}/bin/geany.exe || exit 1
263 test -f ${GEANY_INSTALLATION_DIR}/lib/geany/export.dll || exit 1
264 test ! -f ${GEANY_INSTALLATION_DIR}/lib/geany/demoplugin.dll || exit 1
268 log_geany_version() {
269 log "Log installed Geany version
"
270 mingw-w64-x86_64-wine ${GEANY_INSTALLATION_DIR}/bin/geany.exe --version 2>/dev/null
271 exiftool -FileName -FileType -FileVersion -FileVersionNumber ${GEANY_INSTALLATION_DIR}/bin/geany.exe
276 log "Test NSIS uninstaller
"
277 # uninstall Geany and test if everything is clean
278 mingw-w64-i686-wine ${GEANY_INSTALLATION_DIR}/uninst.exe /S
279 sleep 10 # it seems the uninstaller returns earlier than the files are actually removed, so wait a moment
280 test ! -e ${GEANY_INSTALLATION_DIR}
284 copy_installer_and_bundle() {
285 log "Copying NSIS installer and GTK bundle
"
286 cp ${GEANY_BUILD_DIR}/${GEANY_INSTALLER_FILENAME} ${OUTPUT_DIRECTORY}
288 zip --quiet --recurse-paths ${OUTPUT_DIRECTORY}/gtk_bundle_$(date '+%Y%m%dT%H%M%S').zip *
293 git_clone_geany_if_necessary
297 patch_version_information
310 copy_installer_and_bundle