diff --git a/.circleci/config.yml b/.circleci/config.yml
index 7534bb47d..2a30a4f75 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -20,33 +20,6 @@ jobs:
docker:
- image: fedora:36
steps:
- - run:
- name: "Install deps"
- command: dnf install -y diffutils
- gettext
- glib2-devel
- git-core
- gnutls-utils
- jq
- meson
- git
- gcc
- gcab
- ca-certificates
- python3-pip
- mingw32-nsis
- mingw64-brotli
- mingw64-gcc
- mingw64-gettext
- mingw64-pkg-config
- mingw64-glib2
- mingw64-gnutls
- mingw64-libusbx
- mingw64-sqlite
- mingw64-libarchive
- mingw64-json-glib
- mingw64-curl
- wine
- checkout
- run:
name: "Build Win32"
@@ -54,7 +27,7 @@ jobs:
- persist_to_workspace:
root: .
paths:
- - "dist/setup/*.exe"
+ - "dist/setup/*.msi"
- "dist/VERSION"
- "dist/news.txt"
- store_artifacts:
diff --git a/contrib/build-windows.sh b/contrib/build-windows.sh
new file mode 100755
index 000000000..6a8f33769
--- /dev/null
+++ b/contrib/build-windows.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+set -e
+
+root=$(pwd)
+export DESTDIR=${root}/dist
+build=$root/build-win32
+mkdir -p "$build" && cd "$build"
+
+# install deps
+if [ ! -f /usr/share/mingw/toolchain-mingw64.meson ]; then
+ ./contrib/ci/fwupd_setup_helpers.py -v mingw64 install-dependencies
+fi
+
+# try to keep this and ../contrib/ci/build_windows.sh in sync as much as makes sense
+meson .. \
+ --cross-file=/usr/share/mingw/toolchain-mingw64.meson \
+ --prefix=/ \
+ --sysconfdir="etc" \
+ --libexecdir="bin" \
+ --bindir="bin" \
+ -Dbuild=all \
+ -Ddocs=none \
+ -Dhsi=false \
+ -Dman=false \
+ -Dfish_completion=false \
+ -Dbash_completion=false \
+ -Dfirmware-packager=false \
+ -Dmetainfo=false \
+ -Dcompat_cli=false \
+ -Dsoup_session_compat=false \
+ -Dgcab:introspection=false \
+ -Dgcab:docs=false \
+ -Dgcab:nls=false \
+ -Dgcab:vapi=false \
+ -Dgcab:tests=false \
+ -Dlibxmlb:introspection=false \
+ -Dlibxmlb:gtkdoc=false \
+ -Dlibjcat:man=false \
+ -Dlibjcat:gpg=false \
+ -Dlibjcat:tests=false \
+ -Dlibjcat:introspection=false \
+ -Dgusb:tests=false \
+ -Dgusb:docs=false \
+ -Dgusb:introspection=false \
+ -Dgusb:vapi=false
+
+# run tests
+export WINEPATH="/usr/x86_64-w64-mingw32/sys-root/mingw/bin/;$build/libfwupd/;$build/libfwupdplugin/;$build/subprojects/libxmlb/src/;$build/subprojects/gcab/libgcab/;$build/subprojects/libjcat/libjcat/;$build/subprojects/gusb/gusb/"
+ninja -C "$build" install
+ninja -C "$build" test
+
+CERTDIR=/etc/pki/tls/certs
+MINGW32BINDIR=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
+
+# copy deps
+cp -f -v $MINGW32BINDIR/curl.exe \
+ $MINGW32BINDIR/gspawn-win64-helper-console.exe \
+ $MINGW32BINDIR/gspawn-win64-helper.exe \
+ $MINGW32BINDIR/iconv.dll \
+ $MINGW32BINDIR/libarchive-13.dll \
+ $MINGW32BINDIR/libbrotlicommon.dll \
+ $MINGW32BINDIR/libbrotlidec.dll \
+ $MINGW32BINDIR/libbz2-1.dll \
+ $MINGW32BINDIR/libcrypto-1_1-x64.dll \
+ $MINGW32BINDIR/libcurl-4.dll \
+ $MINGW32BINDIR/libffi-*.dll \
+ $MINGW32BINDIR/libgcc_s_seh-1.dll \
+ $MINGW32BINDIR/libgio-2.0-0.dll \
+ $MINGW32BINDIR/libglib-2.0-0.dll \
+ $MINGW32BINDIR/libgmodule-2.0-0.dll \
+ $MINGW32BINDIR/libgmp-10.dll \
+ $MINGW32BINDIR/libgnutls-30.dll \
+ $MINGW32BINDIR/libgobject-2.0-0.dll \
+ $MINGW32BINDIR/libhogweed-*.dll \
+ $MINGW32BINDIR/libidn2-0.dll \
+ $MINGW32BINDIR/libintl-8.dll \
+ $MINGW32BINDIR/libjson-glib-1.0-0.dll \
+ $MINGW32BINDIR/liblzma-5.dll \
+ $MINGW32BINDIR/libnettle-*.dll \
+ $MINGW32BINDIR/libp11-kit-0.dll \
+ $MINGW32BINDIR/libpcre-1.dll \
+ $MINGW32BINDIR/libsqlite3-0.dll \
+ $MINGW32BINDIR/libssh2-1.dll \
+ $MINGW32BINDIR/libssl-1_1-x64.dll \
+ $MINGW32BINDIR/libssp-0.dll \
+ $MINGW32BINDIR/libtasn1-6.dll \
+ $MINGW32BINDIR/libusb-1.0.dll \
+ $MINGW32BINDIR/libwinpthread-1.dll \
+ $MINGW32BINDIR/libxml2-2.dll \
+ $MINGW32BINDIR/zlib1.dll \
+ "$DESTDIR/bin/"
+cp -f -v "$CERTDIR/ca-bundle.crt" "$DESTDIR/bin/"
diff --git a/contrib/ci/build_windows.sh b/contrib/ci/build_windows.sh
index 5667e129d..e0bac1b7d 100755
--- a/contrib/ci/build_windows.sh
+++ b/contrib/ci/build_windows.sh
@@ -1,10 +1,28 @@
#!/bin/sh
set -e
+
+# if invoked outside of CI
+if [ "$CI" != "true" ]; then
+ echo "Not running in CI, please manually configure Windows build"
+ exit 1
+fi
+
+# install deps
+./contrib/ci/fwupd_setup_helpers.py --yes -o fedora -v mingw64 install-dependencies
+
+# update things that are not yet in Fedora updates-testing
+if [ "$(id -u)" -eq 0 ]; then
+ dnf install -y \
+ https://kojipkgs.fedoraproject.org//packages/msitools/0.101.32/5.fc36/x86_64/msitools-0.101.32-5.fc36.x86_64.rpm \
+ https://kojipkgs.fedoraproject.org//packages/msitools/0.101.32/5.fc36/x86_64/libmsi1-0.101.32-5.fc36.x86_64.rpm
+fi
+
#prep
export LC_ALL=C.UTF-8
root=$(pwd)
export DESTDIR=${root}/dist
build=$root/build-win32
+
rm -rf $DESTDIR $build
# For logitech bulk controller being disabled (-Dplugin_logitech_bulkcontroller=disabled):
@@ -14,9 +32,8 @@ rm -rf $DESTDIR $build
# 2. add protoc = /path/to/protoc-c.exe in mingw64.cross
# 3. Only enable when not a tagged release (Unsupported by Logitech)
-#build
+# try to keep this and ../contrib/build-windows.sh in sync as much as makes sense
mkdir -p $build $DESTDIR && cd $build
-python3 -m pip install --user "meson >= 0.60.0"
meson .. \
--cross-file=/usr/share/mingw/toolchain-mingw64.meson \
--prefix=/ \
@@ -27,6 +44,9 @@ meson .. \
-Ddocs=none \
-Dhsi=false \
-Dman=false \
+ -Dfish_completion=false \
+ -Dbash_completion=false \
+ -Dfirmware-packager=false \
-Dmetainfo=false \
-Dcompat_cli=false \
-Dsoup_session_compat=false \
@@ -39,14 +59,22 @@ meson .. \
-Dlibxmlb:gtkdoc=false \
-Dlibjcat:man=false \
-Dlibjcat:gpg=false \
+ -Dlibjcat:tests=false \
-Dlibjcat:introspection=false \
-Dgusb:tests=false \
-Dgusb:docs=false \
-Dgusb:introspection=false \
-Dgusb:vapi=false $@
VERSION=$(meson introspect . --projectinfo | jq -r .version)
-ninja -v
-ninja -v install
+
+# run tests
+export WINEPATH="/usr/x86_64-w64-mingw32/sys-root/mingw/bin/;$build/libfwupd/;$build/libfwupdplugin/;$build/subprojects/libxmlb/src/;$build/subprojects/gcab/libgcab/;$build/subprojects/libjcat/libjcat/;$build/subprojects/gusb/gusb/"
+ninja --verbose -C "$build" -v
+ninja -C "$build" test
+
+# switch to release optimizations
+meson configure -Dtests=false -Dbuildtype=release
+ninja -C "$build" -v install
#generate news release
cd $root
@@ -57,25 +85,94 @@ echo $VERSION > $DESTDIR/VERSION
sed -i 's,UpdateMotd=.*,UpdateMotd=false,' $DESTDIR/etc/fwupd/daemon.conf
# create a setup binary
-cd $DESTDIR
-mkdir -p $DESTDIR/setup
-makensis -NOCD $build/contrib/setup-win32.nsi
+CERTDIR=/etc/pki/tls/certs
+MINGW32BINDIR=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
-#so that it's actually executable
-cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/*.dll bin
+# deps
+find $MINGW32BINDIR \
+ -name curl.exe \
+ -o -name gspawn-win64-helper-console.exe \
+ -o -name gspawn-win64-helper.exe \
+ -o -name iconv.dll \
+ -o -name libarchive-13.dll \
+ -o -name libbrotlicommon.dll \
+ -o -name libbrotlidec.dll \
+ -o -name libbz2-1.dll \
+ -o -name libcrypto-1_1-x64.dll \
+ -o -name libcurl-4.dll \
+ -o -name "libffi-*.dll" \
+ -o -name libgcc_s_seh-1.dll \
+ -o -name libgio-2.0-0.dll \
+ -o -name libglib-2.0-0.dll \
+ -o -name libgmodule-2.0-0.dll \
+ -o -name libgmp-10.dll \
+ -o -name libgnutls-30.dll \
+ -o -name libgobject-2.0-0.dll \
+ -o -name "libhogweed-*.dll" \
+ -o -name libidn2-0.dll \
+ -o -name libintl-8.dll \
+ -o -name libjson-glib-1.0-0.dll \
+ -o -name liblzma-5.dll \
+ -o -name "libnettle-*.dll" \
+ -o -name libp11-kit-0.dll \
+ -o -name libpcre-1.dll \
+ -o -name libsqlite3-0.dll \
+ -o -name libssh2-1.dll \
+ -o -name libssl-1_1-x64.dll \
+ -o -name libssp-0.dll \
+ -o -name libtasn1-6.dll \
+ -o -name libusb-1.0.dll \
+ -o -name libwinpthread-1.dll \
+ -o -name libxml2-2.dll \
+ -o -name zlib1.dll \
+ | wixl-heat \
+ -p $MINGW32BINDIR/ \
+ --win64 \
+ --directory-ref BINDIR \
+ --var "var.MINGW32BINDIR" \
+ --component-group "CG.fwupd-deps" | \
+ tee $build/contrib/fwupd-deps.wxs
-#remove static archives
-find -type f -print0 -name "*.dll.a" | xargs rm -f
+# CA bundle
+echo $CERTDIR/ca-bundle.crt | wixl-heat \
+ -p $CERTDIR/ \
+ --win64 \
+ --directory-ref BINDIR \
+ --var "var.CRTDIR" \
+ --component-group "CG.fwupd-certs" | \
+ tee "$build/contrib/fwupd-certs.wxs"
-#remove stuff that we really don't need
-rm -fr gcab.exe \
- xb-tool.exe \
- share/man \
- include \
- fwupd \
- lib/*.a \
- lib/pkgconfig/ \
- var
+# our files
+find "$DESTDIR" | \
+ wixl-heat \
+ -p "$DESTDIR/" \
+ -x include/ \
+ -x share/fwupd/device-tests/ \
+ -x share/tests/ \
+ -x share/man/ \
+ -x share/doc/ \
+ -x lib/pkgconfig/ \
+ --win64 \
+ --directory-ref INSTALLDIR \
+ --var "var.DESTDIR" \
+ --component-group "CG.fwupd-files" | \
+ tee "$build/contrib/fwupd-files.wxs"
-export WINEPATH="/usr/x86_64-w64-mingw32/sys-root/mingw/bin/;$build/libfwupd/;$build/libfwupdplugin/;$build/subprojects/libxmlb/src/;$build/subprojects/gcab/libgcab/;$build/subprojects/libjcat/libjcat/;$build/subprojects/gusb/gusb/"
-ninja -C $build test
+MSI_FILENAME="$DESTDIR/setup/fwupd-$VERSION-setup-x86_64.msi"
+mkdir -p "$DESTDIR/setup"
+wixl -v \
+ "$build/contrib/fwupd.wxs" \
+ "$build/contrib/fwupd-deps.wxs" \
+ "$build/contrib/fwupd-certs.wxs" \
+ "$build/contrib/fwupd-files.wxs" \
+ -D CRTDIR=$CERTDIR \
+ -D MINGW32BINDIR=$MINGW32BINDIR \
+ -D Win64="yes" \
+ -D DESTDIR="$DESTDIR" \
+ -o "${MSI_FILENAME}"
+
+# check the msi archive can be installed and removed (use "wine uninstaller" to do manually)
+wine msiexec /i "${MSI_FILENAME}"
+ls -R ~/.wine/drive_c/Program\ Files/fwupd/
+wine ~/.wine/drive_c/Program\ Files/fwupd/bin/fwupdtool get-plugins --json
+wine msiexec /x "${MSI_FILENAME}"
diff --git a/contrib/ci/dependencies.xml b/contrib/ci/dependencies.xml
index 3be07e757..c8e6dca1e 100644
--- a/contrib/ci/dependencies.xml
+++ b/contrib/ci/dependencies.xml
@@ -62,6 +62,7 @@
+
@@ -96,6 +97,9 @@
+
+ mingw64-gcc
+
@@ -150,6 +154,7 @@
json-glib-devel
+ mingw64-json-glib
json-glib-devel
@@ -361,6 +366,8 @@
+
+ gcab
@@ -382,6 +389,9 @@
+
+ gettext
+ mingw64-gettext
@@ -452,6 +462,7 @@
+
@@ -480,6 +491,9 @@
glib2-devel
+
+ glib2-devel
+ mingw64-glib2
glib-devel
@@ -545,6 +559,7 @@
gnutls-devel
+ mingw64-gnutls
gnutls-devel
@@ -608,6 +623,7 @@
+
@@ -683,6 +699,7 @@
libarchive-devel
+ mingw64-libarchive
@@ -839,6 +856,7 @@
libgusb-devel
+ mingw64-libgusb
libgusb-devel
@@ -917,6 +935,7 @@
libcurl-devel
+ mingw64-curl
libcurl-devel
@@ -992,6 +1011,7 @@
+
@@ -1061,6 +1081,9 @@
+
+ mingw64-pkg-config
+
@@ -1330,6 +1353,7 @@
sqlite-devel
+ mingw64-sqlite
@@ -1634,4 +1658,10 @@
+
+
+
+ wine
+
+
diff --git a/contrib/fwupd.wxs.in b/contrib/fwupd.wxs.in
new file mode 100644
index 000000000..5b83f28b2
--- /dev/null
+++ b/contrib/fwupd.wxs.in
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NOT NEWERVERSIONDETECTED
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/contrib/meson.build b/contrib/meson.build
index d5493c7e4..f1513ed77 100644
--- a/contrib/meson.build
+++ b/contrib/meson.build
@@ -14,10 +14,9 @@ configure_file(
)
if host_machine.system() == 'windows'
- # replace @FWUPD_VERSION@
configure_file(
- input : 'setup-win32.nsi.in',
- output : 'setup-win32.nsi',
- configuration : con2,
+ input: 'fwupd.wxs.in',
+ output: 'fwupd.wxs',
+ configuration: conf
)
endif
diff --git a/contrib/setup-win32.nsi.in b/contrib/setup-win32.nsi.in
deleted file mode 100644
index 3e250044a..000000000
--- a/contrib/setup-win32.nsi.in
+++ /dev/null
@@ -1,101 +0,0 @@
-#!Nsis Installer Command Script
-#
-# To build an installer from the script you would normally do:
-#
-# dnf install mingw32-nsis
-# makensis setup-win32.nsi
-
-Name ""
-OutFile "setup/fwupd-@FWUPD_VERSION@-setup-x86_64.exe"
-InstallDir "$ProgramFiles\fwupd"
-InstallDirRegKey HKLM SOFTWARE\fwupd "Install_Dir"
-ShowInstDetails hide
-ShowUninstDetails hide
-XPStyle on
-Page directory
-Page instfiles
-
-ComponentText "Select which optional components you want to install."
-
-DirText "Please select the installation folder."
-
-Section "fwupd"
- SectionIn RO
-
- SetOutPath "$INSTDIR\bin"
-
- # deps
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/iconv.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libarchive-13.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libbrotlicommon.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libbrotlidec.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libbz2-1.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libcrypto-1_1-x64.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libssh2-1.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libssl-1_1-x64.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libssp-0.dll"
- File /r "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libffi-*.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgcc_s_seh-1.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgio-2.0-0.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libglib-2.0-0.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgmodule-2.0-0.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgmp-10.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgnutls-30.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgnutls-30.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgobject-2.0-0.dll"
- File /r "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libhogweed-*.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libidn2-0.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libintl-8.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libjson-glib-1.0-0.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/liblzma-5.dll"
- File /r "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libnettle-*.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libp11-kit-0.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libpcre-1.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libcurl-4.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libsqlite3-0.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libtasn1-6.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libusb-1.0.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libwinpthread-1.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libxml2-2.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/zlib1.dll"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/curl.exe"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/gspawn-win64-helper-console.exe"
- File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/gspawn-win64-helper.exe"
- File "/etc/pki/tls/certs/ca-bundle.crt"
-
- # fwupd
- File "bin/fwupdtool.exe"
- File "bin/libfwupd-2.dll"
- File "bin/libfwupdplugin-@FWUPD_PLUGINVER@.dll"
- File "bin/libgcab-1.0-0.dll"
- File "bin/libxmlb-2.dll"
- File "bin/libjcat-1.dll"
- File "bin/libgusb-2.dll"
- SetOutPath "$INSTDIR\fwupd-plugins-@FWUPD_PLUGINVER@"
- File /r "fwupd-plugins-@FWUPD_PLUGINVER@/libfu_plugin_*.dll"
- SetOutPath "$INSTDIR\etc\fwupd"
- File "etc/fwupd/daemon.conf"
- SetOutPath "$INSTDIR\etc\pki\fwupd"
- File "etc/pki/fwupd/LVFS-CA.pem"
- SetOutPath "$INSTDIR\share\fwupd\quirks.d"
- File /r "share/fwupd/quirks.d/*.quirk"
- SetOutPath "$INSTDIR\etc\fwupd\remotes.d"
- File "etc/fwupd/remotes.d/lvfs.conf"
- File "etc/fwupd/remotes.d/lvfs-testing.conf"
-
- ReadEnvStr $0 COMSPEC
- SetOutPath "$INSTDIR"
-SectionEnd
-
-Section "Uninstall"
- RMDir /rebootok /r "$SMPROGRAMS\fwupd"
- RMDir /rebootok /r "$INSTDIR\bin"
- RMDir /rebootok /r "$INSTDIR\etc"
- RMDir /rebootok /r "$INSTDIR\lib"
- RMDir /rebootok /r "$INSTDIR\share"
- RMDir /rebootok "$INSTDIR"
-SectionEnd
-
-Section -post
- WriteUninstaller "$INSTDIR\Uninstall fwupd.exe"
-SectionEnd
diff --git a/data/fwupd.ico b/data/fwupd.ico
new file mode 100644
index 000000000..d92df08b6
Binary files /dev/null and b/data/fwupd.ico differ
diff --git a/meson.build b/meson.build
index 4e893834e..f35386350 100644
--- a/meson.build
+++ b/meson.build
@@ -564,13 +564,3 @@ subdir('docs')
if build_daemon and libsystemd.found()
meson.add_install_script('meson_post_install.sh', systemdunitdir)
endif
-
-makensis = find_program('makensis', required : host_machine.system() == 'windows')
-if makensis.found()
- run_target(
- 'makensis',
- command: [
- makensis,
- join_paths(meson.project_source_root(), 'contrib', 'setup-win32.nsi'),
- ])
-endif
diff --git a/subprojects/gcab.wrap b/subprojects/gcab.wrap
index 35e59d0a7..52640dadb 100644
--- a/subprojects/gcab.wrap
+++ b/subprojects/gcab.wrap
@@ -2,3 +2,8 @@
directory = gcab
url = https://gitlab.gnome.org/GNOME/gcab.git
revision = b55268ac1020cd6c033acb52f2e6ae984bf5c9fd
+
+# disabled until we depend on a meson including https://github.com/mesonbuild/meson/pull/10291
+# and https://gitlab.gnome.org/GNOME/gcab/-/merge_requests/10 is merged
+# [provide]
+# program_names = gcab