Page MenuHome GnuPG

No OneTemporary

diff --git a/build.sh b/build.sh
index f0456ae7..92d098ca 100755
--- a/build.sh
+++ b/build.sh
@@ -1,694 +1,694 @@
#!/bin/bash
# Copyright (C) 2024 g10 Code GmbH
#
# Software engineering by Andre Heinecke <aheinecke@gnupg.org>
#
# This file is part of GPG4Win.
#
# GPG4Win is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# GPG4Win is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <https://www.gnu.org/licenses/>.
# SPDX-License-Identifier: GPL-2.0-or-later
set -e
PGM=build.sh
usage()
{
cat <<EOF
Usage: $PGM [OPTIONS]
Build Gpg4win in a docker containter.
Options:
--appimage Build the AppImage instead of the NSIS installer.
--v3 Use packages.3 instead of the default
--w32 Use 32 bit Windows as primary host arch
--clean Remove a pre-existing build directory
--shell Start a shell instead of starting the build script
--builddir=DIR Directory where the build should take place
(default is ~/b/SRCDIRNAME-playground for gpg4win
and ~/b/SRCDIRNAME-appimage for the AppImage)
--force Force configure run
--update-image Update the docker image before build
--msi Building MSI packages
--user=name Use NAME as FTP server user
--download Download packages first
--runcmd CMD Run a command via a pair of FIFOs
--git-pkgs Use latest git versions for the frontend
packages:
libkleo kleopatra gpgol gpgol.js
gpgpass gpg4win-tools mimetreeparser
This script is used to build either the Appimage or the Windows
installer. The build is done in a build directory with the suffix
"-playground". Use the option --builddir to use a non-default build
directory. Take care not to use the source directory for building.
Examples:
./$PGM
Build in the default build directory ~/b/SRCDIRNAME-playground
./$PGM --builddir=/foo/bar/my-playground
Build in the given directory.
EOF
exit $1
}
# Other constants
WINE=wine
WINHOST=win10
WINLIGHT=c:/wix/light.exe
# WINEPREFIX - determined at runtime or passed by caller
# WIXPREFIX - determined at runtime or passed by caller
# Store the original command line
# for diagnostic reasons
commandline="$0 $@"
# Preset variables.
indocker="no"
gpg22="no"
shell="no"
clean="no"
branch="master"
srcdir=$(cd $(dirname $0); pwd)
is_tmpbuild="no"
update_image="no"
w64="yes"
download="no"
runcmd="no"
fromgit="no"
withmsi="no"
force=no
ftpuser=
verbose=
quiet=
# Get UID for use by docker.
userid=$(id -u)
groupid=$(id -g)
# Parse the command line options.
skipshift=
while [ $# -gt 0 ]; do
case "$1" in
--*=*)
optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'`
;;
*)
optarg=""
;;
esac
case "$1" in
--appimage) appimage="yes";;
--v3) gpg22="yes";;
--shell) shell="yes";;
--clean|-c) clean="yes";;
--update-image|--update-img|-u) update_image="yes";;
--w32) w64="no";;
--w64) w64="yes";;
--force) force="yes";;
--download) download="yes";;
--runcmd) runcmd="yes";;
--git|-g|--git-pkgs) fromgit="yes";;
--builddir|--builddir=*) builddir="${optarg}" ;;
--user|--user=*) ftpuser="${optarg}" ;;
--msi|--with-msi) withmsi=yes ;;
--verbose|-v) verbose=yes ;;
--*) usage 1 1>&2; exit 1;;
*) skipshift=1; break ;;
esac
[ -z "$skipshift" ] && shift
done
[ -z "$verbose" ] && quiet="--quiet"
if [ -z "$builddir" ]; then
if [ "$appimage" = "yes" ]; then
builddir="${HOME}/b/$(basename "$srcdir")-appimage"
else
builddir="${HOME}/b/$(basename "$srcdir")-playground"
fi
fi
# Check whether we are running in the docker container.
if [ -d /src/src -a -d /src/patches -a -d /build ]; then
indocker="yes"
srcdir=/src
builddir=/build
echo >&2 "$PGM: running in docker"
fi
echo >&2 "$PGM: source directory: $srcdir"
echo >&2 "$PGM: build directory: $builddir"
# The main GUI packages. check the gen-tarball script to see which
# branches are used.
FRONTEND_PKGS="
libkleo
kleopatra
gpgol
gpgoljs
gpgpass
gpg4win-tools
mimetreeparser"
# Function to download the packages. Optionally generate new tarballs
# for the main GUI components.
download_packages() {
if [ "$indocker" = yes ]; then
echo >&2 "$PGM: error: downloading files from docker is not possible"
exit 2
fi
cd packages
if [ "$fromgit" = yes ]; then
echo >&2 "$PGM: Creating new tarballs and updating packages file ... "
myargs=
[ -n "$ftpuser" ] && myargs="$myargs --user=$ftpuser"
./gen-tarball.sh $myargs -u $FRONTEND_PKGS
echo >&2 "$PGM: Generating tarballs done"
fi
echo "$PGM: Downloading packages"
myargs=
[ "$gpg22" = yes ] && myargs="$myargs --v3"
./download.sh $quiet $myargs
echo >&2 "$PGM: downloading done"
cd ..
}
# Run a command using the FIFOs. This needs to be called via a FIFO
# from the docker. Note that we don't explicit serialize access to the
# FIFO, hopefully no parallel make rules are run.
if [ "$runcmd" = yes ]; then
if [ "$indocker" != yes ]; then
echo >&2 "$PGM: Option --runcmd must be called from docker"
echo >&2 "$PGM: Available commands are:"
echo >&2 "$PGM: ping - Wait for a pong"
echo >&2 "$PGM: gpg - Run a gpg command"
echo >&2 "$PGM: msibase - Prepare MSI linking"
echo >&2 "$PGM: litcandle - Run candle.exe"
exit 2
fi
# Running in docker
if [ -z "$1" ]; then
echo >&2 "usage: /src/build.sh --runcmd COMMAND ARGS"
exit 2
fi
[ -f /build/S.build.sh-rc ] && rm /build/S.build.sh-rc
echo "$@" >/build/S.build.sh-in
cat /build/S.build.sh-out
while [ ! -f /build/S.build.sh-rc ]; do sleep 0.05; done
rc=$(sed -ne 's/EXITSTATUS=\([0-9]*\).*$/\1/p' \
</build/S.build.sh-rc 2>/dev/null || true)
[ -z "$rc" ] && rc=0
exit $rc
fi
# Check whether we are in the docker image run appropriate commands.
# Note that this script is used to start the docker container and also
# within the docker container to run the desired commands.
if [ "$indocker" = yes ]; then
# NB: In docker the builddir is always /build and the source /src
cd /build
if [ ! -f config.status ]; then
force=yes
elif [ /src/configure -nt config.status ]; then
force=yes
fi
if [ $force = no ]; then
echo >&2 "$PGM: Not running configure (--force not used)"
elif [ "$w64" = "yes" ]; then
/src/autogen.sh --build-w64
else
/src/autogen.sh --build-w32
fi
export CMAKE_COLOR_DIAGNOSTICS=OFF
make TOPSRCDIR=/src PLAYGROUND=/build
if [ $? = 0 -a $withmsi = yes ]; then
make TOPSRCDIR=/src PLAYGROUND=/build msi
fi
exit $?
fi # (end of script use inside the docker container) #
# Setup for using the Wix tools under Wine if requested.
if [ $withmsi = yes ]; then
if [ -z "$(which $WINE)" ]; then
echo >&2 "$PGM: error: For MSI packaging Wine needs to be installed"
exit 1
fi
[ -z "$WINEPREFIX" ] && WINEPREFIX="$HOME/.wine"
if [ ! -e "$WINEPREFIX/dosdevices" ]; then
echo 2>&1 "PGM: error: No value for WINEPREFIX found"
exit 1
fi
if [ -z "$WIXPREFIX" ]; then
tmp="$(readlink -f ~/w32root/wixtools)"
if [ -d "$tmp" ]; then
WIXPREFIX="$tmp"
echo 2>&1 "$PGM: Using $WIXPREFIX as WIXPREFIX"
else
echo 2>&1 "$PGM: error: You must set WIXPREFIX" \
" to an installation of wixtools"
exit 1
fi
fi
WINEINST="$WINEPREFIX/dosdevices/k:"
WINESRC="$WINEPREFIX/dosdevices/i:"
WINEINSTEX="$WINEPREFIX/dosdevices/j:"
WINEBLD="$WINEPREFIX/dosdevices/l:"
die=no
for f in "$WINEINST" "$WINESRC" "$WINEINSTEX" "$WINEBLD" ; do
if [ -e "$f" -a ! -h "$f" ]; then
echo 2>&1 "$PGM: error: '$f' already exists. Please remove."
die=yes
fi
done
[ $die = yes ] && exit 1
fi
# Determine the needed docker image
if [ "$appimage" = "yes" ]; then
cmd=/src/src/appimage/build-appimage.sh
docker_image=g10-build-appimage:sles15
dockerfile=${srcdir}/docker/appimage
else
# We will run our self again in the docker image.
if [ "$w64" = "yes" ]; then
cmd="/src/build.sh --w64"
else
cmd="/src/build.sh --w32"
fi
[ $force = yes ] && cmd="$cmd --force"
[ $withmsi = yes -a $shell = no ] && cmd="$cmd --msi"
docker_image=g10-build-gpg4win:bookworm
dockerfile=${srcdir}/docker/gpg4win-bookworm
fi
# Update the docker image if requested or if it does not exist.
drep=$(echo $docker_image | cut -d : -f 1)
dtag=$(echo $docker_image | cut -d : -f 2)
if [ -z "$(docker images | grep $drep | grep $dtag)" \
-o "$update_image" = "yes" ]; then
echo >&2 "$PGM: Local image $docker_image not found"
echo >&2 "$PGM: Building docker image"
docker build -t $docker_image $dockerfile 2>&1
fi
# Make sure we have a BUILDTYPE file
if [ ! -e packages/BUILDTYPE ]; then
echo >&2 "PGM: packages/BUILDTYPE not found - see README"
- return 1
+ exit 1
fi
# If --shell was used override the command for docker.
# if not used try to download first.
if [ "$shell" = "yes" ]; then
cmd="bash"
elif [ "$download" = yes ]; then
download_packages
else
echo >&2 "$PGM: package download skipped"
fi
start_time=$(date +"%s")
log_file="${builddir}/build-log.txt"
# Kill the given process and all its descendants
killtree() {
local parent=$1 child
for child in $(ps -o ppid= -o pid= | awk "\$1==$parent {print \$2}"); do
killtree $child
done
kill $parent
}
# Remove FIFO files.
remove_fifos() {
[ -e "${builddir}/S.build.sh-in" ] && rm "${builddir}/S.build.sh-in"
[ -e "${builddir}/S.build.sh-out" ] && rm "${builddir}/S.build.sh-out"
return 0
}
# Create FIFO files.
create_fifos() {
remove_fifos
mkfifo -m 600 "${builddir}/S.build.sh-in"
mkfifo -m 600 "${builddir}/S.build.sh-out"
return 0
}
# Make sure we have an absolute build directory and the fifos
# so that docker does not create it with root as owner.
[ -d "${builddir}" ] || mkdir -p "${builddir}"
builddir=$(cd "${builddir}"; pwd)
[ -d "${builddir}/po" ] || mkdir -p "${builddir}/po"
create_fifos
# Function to stop our command runner
runnerpid=
stop_runner() {
printf >&2 -- "$PGM: stop-runner called\n"
if [ -n "$runnerpid" ]; then
echo >&2 "$PGM: stopping runner ..."
killtree $runnerpid
runnerpid=
remove_fifos
fi
return 0
}
# Transform a directory from docker to host directory
transform_dir() {
echo "$1"|sed -e "s,^/build/,$builddir/," -e "s,/src/,$srcdir/,"
}
# Transform all directories in the provided string
# Fixme: This sed expression is not robust enough.
transform_multi_dir() {
echo "$1"|sed -e "s, /build/, $builddir/,g" -e "s, /src/, $srcdir,g"
}
# Run a gpg command
runner_cmd_gpg() {
local cmd="$1"
cmd=$(transform_multi_dir "$cmd")
printf >&2 -- "$PGM(runner): invoking gpg\n"
set +e
$cmd </dev/null
rc=$?
set -e
printf >&2 -- "$PGM(runner): gpg returned $rc\n"
return 0
}
# Run the gpg-authcode-sign command
runner_cmd_gpg_authcode_sign() {
local cmd="$1"
printf >&2 -- "$PGM(runner): gpg-authcode-sign.sh --stamp $cmd\n"
set +e
[ -n "$verbose" ] && set -x
( cd "$builddir"/install && gpg-authcode-sign.sh --stamp $cmd </dev/null )
rc=$?
[ -n "$verbose" ] && set +x
set -e
printf >&2 -- "$PGM(runner): gpg-authcode-sign.sh returned $rc\n"
return 0
}
# Copy some files to the Windows host to prepare the MSI linking
# Args are: See below
runner_cmd_msibase() {
local version="$1" gnupgmsi="$2"
set +e
[ -n "$verbose" ] && set -x
ssh "$WINHOST" "mkdir AppData\\Local\\Temp\\gpg4win-$version" || true
scp "$srcdir"/packages/gnupg-msi-${gnupgmsi}-bin.wixlib \
"$WINHOST":AppData/Local/Temp/gpg4win-"$version";
scp "$srcdir"/src/icons/shield.ico \
"$WINHOST":AppData/Local/Temp/gpg4win-"$version"
scp "$srcdir"/doc/logo/gpg4win-msi-header_install-493x58.bmp \
"$WINHOST":AppData/Local/Temp/gpg4win-"$version"/header.bmp
scp "$srcdir"/doc/logo/gpg4win-msi-wizard_install-493x312.bmp \
"$WINHOST":AppData/Local/Temp/gpg4win-"$version"/dialog.bmp
scp "$srcdir"/doc/logo/gpg4win-msi-wizard_install-493x312.bmp \
"$WINHOST":AppData/Local/Temp/gpg4win-"$version"/dialog.bmp
scp "$srcdir"/doc/logo/gpg4win-msi-wizard_install-info-32x32.bmp \
"$WINHOST":AppData/Local/Temp/gpg4win-"$version"/info.bmp
scp "$srcdir"/doc/logo/gpg4win-msi-wizard_install-exclamation-32x32.bmp \
"$WINHOST":AppData/Local/Temp/gpg4win-"$version"/exclamation.bmp
scp "$srcdir"/po/gpg4win-en.wxl \
"$WINHOST":AppData/Local/Temp/gpg4win-"$version"
scp "$srcdir"/po/gpg4win-de.wxl \
"$WINHOST":AppData/Local/Temp/gpg4win-"$version"
scp WixUI_Gpg4win.wxs \
"$WINHOST":AppData/Local/Temp/gpg4win-"$version"
rc=0
[ -n "$verbose" ] && set +x
set -e
return 0
}
# Copy files to the Windows host
runner_cmd_cptowinhost() {
local version="$1"
local target="$WINHOST":AppData/Local/Temp/gpg4win-"$version"
local files
shift
files=
for f in $@; do
files="$files $(transform_dir "$f")"
done
set +e
echo 2>&1 "$PGM: running scp $files $target"
scp $files "$target"
rc=$?
set -e
return 0
}
# Copy file from the Windows host
runner_cmd_cpfromwinhost() {
local version="$1" prefix="$2" name="$3" vsdvers="$4"
local mydir="$WINHOST":AppData/Local/Temp/gpg4win-"$version"
set +e
scp "$mydir/$prefix-$version-$name.msi" \
"$builddir/src/installers/$prefix-$vsdvers-$name.msi"
rc=$?
set -e
return 0
}
# Copy files to the Windows host
runner_cmd_lightwinhost() {
local version="$1" prefix="$2" name="$3" intlopt="$4" msivers="$5"
[ -n "$verbose" ] && set -x
set +e
ssh "$WINHOST" "cd AppData/Local/Temp/gpg4win-$version \
&& $WINLIGHT \
-cc . -reusecab -spdb \
-ext WixUIExtension \
-ext WixUtilExtension \
-out $prefix-$version-$name.msi \
$(echo "$intlopt" | sed 's,%20, ,g') \
-dcl:high -pedantic \
$prefix-$version.wixlib gnupg-msi-$msivers-bin.wixlib $name-$version.wixlib" \
| grep -v "ICE80" | grep -v "ICE57"
rc="${PIPESTATUS[0]}"
set -e
[ -n "$verbose" ] && set +x
# FIXME:
echo 2>&1 "$PGM(runner): cmd lightwinhost exited with $rc - forcing 0"
rc=0
return 0
}
# Run the Wix tools under Wine.
runner_cmd_litcandle() {
local mode="$1" version="$2" prefix="$3" idir="$4" exidir="$5"
local dwixobj fwxs
if [ $withmsi = no ]; then
echo 2>&1 "$PGM(runner): litcandle requires --with-msi option"
rc=2
return 0
fi
idir=$(transform_dir "$idir")
exidir=$(transform_dir "$exidir")
fwixlib="$prefix"-"$version".wixlib
fwixobj="$prefix"-"$version".wixobj
if [ "$mode" = ui ]; then
fwxs="l:\\src\\gnupg-vsd\\$prefix\\$prefix".wxs
fextraobj="k:\\gpg4win-ui.wixobj"
else
fwxs="l:\\src\\$prefix"-"$version".wxs
fextraobj=
fi
# Create symlinks into the Wine dosdevices directory
ln -sf "$idir" "$WINEINST"
ln -sf "$exidir" "$WINEINSTEX"
ln -sf "$srcdir" "$WINESRC"
ln -sf "$builddir" "$WINEBLD"
# Run the tools
rc=0
[ -n "$verbose" ] && set -x
set +e
if [ $rc -eq 0 ]; then
$WINE "$WIXPREFIX/candle.exe" \
-dInstDir=k: \
-dInstDirEx=j: \
-dSrcDir=i:\\src \
-dBldDir=l:\\src \
-dVersion="$version" \
-dWin64="yes" \
-out k:\\"$fwixobj" \
-pedantic -wx "$fwxs" \
-arch x64
rc=$?
fi
if [ $rc -eq 0 -a -n "$fextraobj" ]; then
$WINE "$WIXPREFIX/candle.exe" \
-dInstDir=k: \
-dInstDirEx=j: \
-dSrcDir=i:\\src \
-dBldDir=l:\\src \
-dVersion="$version" \
-dWin64="yes" \
-out "$fextraobj" \
-arch x64 \
-pedantic -wx i:\\src\\WixUI_Gpg4win.wxs
rc=$?
fi
if [ $rc -eq 0 ]; then
$WINE "$WIXPREFIX/lit.exe" \
-out k:\\"$fwixlib" \
-bf \
-wx \
-pedantic \
k:\\"$fwixobj" "$fextraobj"
rc=$?
fi
set -e
[ -n "$verbose" ] && set +x
# Remove the symlinks
rm "$WINEINST" "$WINESRC" "$WINEINSTEX" "$WINEBLD" || true
return 0
}
# Run a command received from the fifo. Args are command and the line
# with args for the command.
runner_exec_cmd() {
local cmd="$1" line="$2" rc
printf >&2 -- "$PGM: cmd='%s' line='%s'\n" "$cmd" "$line"
# The called functions need to set RC to the desired exit status
rc=42
case "$cmd" in
ping) echo pong; rc=0 ;;
gpg) runner_cmd_gpg "gpg $line" ;;
gpg-authcode-sign) runner_cmd_gpg_authcode_sign "$line" ;;
msibase) runner_cmd_msibase $line ;;
cptowinhost) runner_cmd_cptowinhost $line ;;
cpfromwinhost) runner_cmd_cpfromwinhost $line ;;
lightwinhost) runner_cmd_lightwinhost $line ;;
litcandle) runner_cmd_litcandle $line ;;
*) echo "$PGM(runner): $cmd: no such command"; rc=4 ;;
esac
echo >&2 "$PGM: runner cmd '$cmd' returned $rc"
# Make sure that we have a final LF in the output and then write
# the error line
echo
echo "EXITSTATUS=$rc" > "${builddir}/S.build.sh-rc"
return 0
}
# Start our FIFO command runner.
runner_loop() {
echo >&2 "$PGM: command runner started pid=$$"
while : ; do
if read -r cmd line < "${builddir}/S.build.sh-in" ; then
echo >&2 "$PGM(runner): executing cmd"
runner_exec_cmd "$cmd" "$line" >"${builddir}/S.build.sh-out" &
echo >&2 "$PGM(runner): waiting for cmd"
wait
echo >&2 "$PGM(runner): cmd finished"
fi
done
echo >&2 "$PGM: command runner stopped"
exit 0
}
# Start our FIFO command runner
trap stop_runner EXIT SIGTERM SIGINT SIGHUP
runner_loop &
runnerpid=$!
echo >&2 "$PGM: command runner pid is $runnerpid"
# Run docker
docker_cmdline="run -it --rm --user $userid:$groupid"
docker_cmdline="$docker_cmdline -v "${srcdir}":/src:ro"
docker_cmdline="$docker_cmdline -v "${builddir}":/build:rw"
docker_cmdline="$docker_cmdline -v "$HOME/.gnupg-autogen.rc":/.gnupg-autogen.rc:ro"
docker_cmdline="$docker_cmdline $docker_image $cmd"
echo >&2 "$PGM: running: docker $docker_cmdline"
docker $docker_cmdline 2>&1 | tee -a ${log_file}
err="${PIPESTATUS[0]}"
echo >&2 "$PGM: docker finished. rc=$err"
end_time=$(date +"%s")
duration=$((end_time - start_time))
hours=$((duration / 3600))
minutes=$((duration % 3600 / 60))
seconds=$((duration % 60))
buildtime=$(printf "%02d:%02d:%02d\n" "$hours" "$minutes" "$seconds")
if [ "$err" = "1" -a "$appimage" = "yes" ]; then
echo >&2 "$PGM: Return code 1 on AppImage build. Treating as success."
err=0
fi
if [ "$err" = "0" ]; then
mkdir -p "${builddir}/artifacts"
if [ "$appimage" = "yes" ]; then
results=$(find "${builddir}" -maxdepth 1 -iname \*.appimage \
-a -type f -printf '%p ')
else
results=$(find "${builddir}/src/installers" -type f -printf '%p ')
fi
echo >&2 ""
echo >&2 "$PGM: ############### Success 🥳 ####################"
for result in $results; do
ln -sf -t "${builddir}/artifacts/" "$result"
echo >&2 "$PGM: Created: ${builddir}/artifacts/$(basename $result)"
done
else
echo >&2 "$PGM: ############### Failure 😪 ####################"
fi
echo >&2 "$PGM: Logfile: ${log_file}"
echo >&2 "$PGM: Build command: ${commandline}"
echo >&2 "$PGM: Build time: $buildtime"
echo >&2 "$PGM: ##############################################"

File Metadata

Mime Type
text/x-diff
Expires
Mon, Dec 8, 3:28 AM (1 d, 18 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
72/21/827a7221e155ac47c1c73432fea5

Event Timeline