Skip to content

Commit acbaa52

Browse files
committed
Add AppImage generator for YACReader and YACReaderLibrary
1 parent 3b67605 commit acbaa52

4 files changed

Lines changed: 308 additions & 0 deletions

File tree

appimage/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# AppImage
2+
3+
To build the AppImages of `YACReader` and `YACReaderLibrary`, podman or docker is required using an ubuntu base image of 20.04:
4+
5+
```
6+
podman pull ubuntu:20.04
7+
podman run --device=/dev/fuse --cap-add SYS_ADMIN --cap-add MKNOD --tmpfs /tmp:exec -v ./:/tmp/out --rm -ti ubuntu:20.04 /tmp/out/appimage.sh
8+
```
9+
10+
The resulting AppImages will be placed in this directory.
11+
12+
## YACReader.c
13+
14+
`YACReaderLibrary` when trying to open `YACReader` will call this wrapper which will attempt to find the closest `YACReader` AppImage, then look into `PATH` and finally try to locate `YACReader` in the system if all else fails.

appimage/YACReader.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include <limits.h>
2+
#include <stdlib.h>
3+
#include <limits.h>
4+
#include <string.h>
5+
#include <libgen.h>
6+
#include <stdio.h>
7+
#include <unistd.h>
8+
#include <errno.h>
9+
10+
int main(int argc, char *argv[]) {
11+
char tmp[PATH_MAX], exe_base[NAME_MAX+1], exe_dir[PATH_MAX];
12+
strncpy(tmp, argv[0], PATH_MAX);
13+
strncpy(exe_base, basename(tmp), NAME_MAX+1);
14+
strncpy(tmp, argv[0], PATH_MAX);
15+
strncpy(exe_dir, dirname(tmp), PATH_MAX);
16+
17+
const char *appimage_path = getenv("APPIMAGE");
18+
if (appimage_path && *appimage_path) {
19+
char ai_base[NAME_MAX+1], ai_dir[PATH_MAX];
20+
strncpy(tmp, appimage_path, PATH_MAX);
21+
strncpy(ai_base, basename(tmp), NAME_MAX+1);
22+
strncpy(tmp, appimage_path, PATH_MAX);
23+
strncpy(ai_dir, dirname(tmp), PATH_MAX);
24+
25+
char *ai_last_part = strrchr(ai_base, '-');
26+
if (!ai_last_part || !*ai_last_part)
27+
ai_last_part = strrchr(ai_base, '.');
28+
if (ai_last_part && *ai_last_part) {
29+
snprintf(tmp, PATH_MAX, "%s/%s%s", ai_dir, exe_base, ai_last_part);
30+
argv[0] = tmp;
31+
execvp(argv[0], argv);
32+
if (errno != ENOENT)
33+
return 1;
34+
argv[0] = basename(tmp);
35+
execvp(argv[0], argv);
36+
if (errno != ENOENT)
37+
return 1;
38+
}
39+
snprintf(tmp, PATH_MAX, "%s/%s", ai_dir, exe_base);
40+
argv[0] = tmp;
41+
execvp(argv[0], argv);
42+
if (errno != ENOENT)
43+
return 1;
44+
}
45+
46+
const char *env_path = getenv("PATH");
47+
if (!env_path || !*env_path)
48+
return 1;
49+
50+
char exe_dir_rp[PATH_MAX];
51+
if (!realpath(exe_dir, exe_dir_rp))
52+
return 1;
53+
54+
char env_path_cp[PATH_MAX];
55+
strncpy(env_path_cp, env_path, PATH_MAX);
56+
57+
char ep_rp[PATH_MAX];
58+
for (char *p = strtok(env_path_cp, ":"); p ; p = strtok(NULL, ":")) {
59+
if (!realpath(p, ep_rp))
60+
continue;
61+
if (strcmp(exe_dir_rp, ep_rp)) {
62+
snprintf(tmp, PATH_MAX, "%s/%s", ep_rp, exe_base);
63+
argv[0] = tmp;
64+
execvp(argv[0], argv);
65+
if (errno != ENOENT)
66+
return 1;
67+
}
68+
}
69+
return 1;
70+
}

appimage/appimage.sh

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
#!/bin/bash
2+
#podman pull ubuntu:20.04
3+
#podman run --device=/dev/fuse --cap-add SYS_ADMIN --cap-add MKNOD --tmpfs /tmp:exec -v ./:/tmp/out --rm -ti ubuntu:20.04 /tmp/out/appimage.sh
4+
set -ex
5+
6+
OUT_DIR=/tmp/out
7+
DEST=/usr/local
8+
YACREADER_GIT_URL='https://github.com/YACReader/yacreader.git'
9+
YACREADER_GIT_TAG='9.8.2.2106204'
10+
UNARR_GIT_URL='https://github.com/selmf/unarr.git'
11+
UNARR_GIT_COMMIT='e6fb85e8cdd1b1f9086e6e42be8d385f44136faa'
12+
GN_GIT_URL='https://gn.googlesource.com/gn'
13+
GN_GIT_COMMIT='80a40b07305373617eba2d5878d353532af77da3'
14+
PDFIUM_GIT_URL='https://pdfium.googlesource.com/pdfium'
15+
# curl -sSL 'https://omahaproxy.appspot.com/linux?channel=stable' | cut -d'.' -f 3
16+
PDFIUM_GIT_VERSION='4896'
17+
PDFIUM_GIT_BRANCH="chromium/$PDFIUM_GIT_VERSION"
18+
PDFIUM_BUILD_GIT_URL='https://chromium.googlesource.com/chromium/src/build.git'
19+
# awk '/build_revision/ {print substr($2,2,40)}' pdfium/DEPS
20+
PDFIUM_BUILD_GIT_COMMIT='893ac785aa454dcf84dcc26af1a410095c1d4fa2'
21+
PDFIUM_ABSEIL_CPP_GIT_URL='https://chromium.googlesource.com/chromium/src/third_party/abseil-cpp'
22+
# awk '/abseil_revision/ {print substr($2,2,40)}' pdfium/DEPS
23+
PDFIUM_ABSEIL_CPP_GIT_COMMIT='9ffdb583473a319b3920c752badde40f91ffd609'
24+
25+
# building in temporary directory to keep system clean
26+
# use RAM disk if possible (as in: not building on CI system like Travis, and RAM disk is available)
27+
# if [[ -z "$CI" ]] && [[ -d /dev/shm ]]; then
28+
# TEMP_BASE=/dev/shm
29+
# else
30+
# TEMP_BASE=/tmp
31+
# fi
32+
33+
TEMP_BASE=/tmp
34+
BUILD_DIR="$(mktemp -d -p "$TEMP_BASE" appimage-build-XXXXXX)"
35+
36+
# make sure to clean up build dir, even if errors occur
37+
cleanup() {
38+
if [[ -d "$BUILD_DIR" ]]; then
39+
rm -rf "$BUILD_DIR"
40+
fi
41+
}
42+
trap cleanup EXIT
43+
44+
cd "$BUILD_DIR"
45+
46+
export DEBIAN_FRONTEND=noninteractive
47+
apt -q -y update && apt -q -y upgrade
48+
apt -q -y install build-essential \
49+
cmake \
50+
curl \
51+
fuse \
52+
git \
53+
libbz2-dev \
54+
libfreetype-dev \
55+
libfuse2 \
56+
libicu-dev \
57+
liblcms2-dev \
58+
liblzma-dev \
59+
libopenjp2-7-dev \
60+
libqt5multimedia5-plugins \
61+
libqt5network5 \
62+
libqt5sql5-sqlite \
63+
libqt5svg5-dev \
64+
libturbojpeg0-dev \
65+
mesa-common-dev \
66+
ninja-build \
67+
pkg-config \
68+
python3 \
69+
qt5-image-formats-plugins \
70+
qt5-qmake \
71+
qtbase5-dev \
72+
qtdeclarative5-dev \
73+
qtmultimedia5-dev \
74+
qtquickcontrols2-5-dev
75+
76+
# source the default compiler flags
77+
eval $(dpkg-buildflags --export=sh)
78+
# for gn
79+
export CC=gcc CXX=g++
80+
81+
# compile and install libunarr
82+
git clone "$UNARR_GIT_URL" unarr
83+
cd unarr
84+
git checkout "$UNARR_GIT_COMMIT"
85+
cmake -DENABLE_7Z=ON -DCMAKE_INSTALL_PREFIX="$DEST" -DCMAKE_INSTALL_LIBDIR=lib .
86+
make -j$(nproc)
87+
make install
88+
cd ..
89+
90+
# regenerate dynamic linker cache
91+
ldconfig
92+
93+
# compile and install gn
94+
git clone "$GN_GIT_URL" gn
95+
cd gn
96+
git checkout "$GN_GIT_COMMIT"
97+
./build/gen.py
98+
ninja -C out
99+
strip -s out/gn
100+
install -D out/gn "$DEST"/bin/gn
101+
cd ..
102+
103+
# https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=libpdfium-nojs
104+
# compile and install pdfium
105+
git clone --branch "$PDFIUM_GIT_BRANCH" --depth 1 "$PDFIUM_GIT_URL" pdfium
106+
git clone "$PDFIUM_BUILD_GIT_URL" pdfium/build
107+
git -C pdfium/build checkout "$PDFIUM_BUILD_GIT_COMMIT"
108+
# awk '/abseil_revision/ {print substr($2,2,40)}' pdfium/DEPS
109+
git clone "$PDFIUM_ABSEIL_CPP_GIT_URL" pdfium/third_party/abseil-cpp
110+
git -C pdfium/third_party/abseil-cpp checkout "$PDFIUM_ABSEIL_CPP_GIT_COMMIT"
111+
# Download and decode shim header script needed to unbundle icu (gittiles is weird)
112+
mkdir -p pdfium/tools/generate_shim_headers
113+
curl -sSL https://chromium.googlesource.com/chromium/src/+/master/tools/generate_shim_headers/generate_shim_headers.py?format=TEXT | base64 -d > pdfium/tools/generate_shim_headers/generate_shim_headers.py
114+
curl -sSL https://aur.archlinux.org/cgit/aur.git/plain/libpdfium.pc?h=libpdfium-nojs > libpdfium.pc
115+
# Fix visibility for system Freetype
116+
git -C pdfium/build cherry-pick -n bfd6ff0
117+
# Patch abseil build to be static
118+
sed -i -e 's/component(/static_library(/' -e 's/is_component_build(/false/' pdfium/third_party/abseil-cpp/BUILD.gn
119+
# Use system provided icu library (unbundling)
120+
mkdir -p pdfium/third_party/icu
121+
ln -sf ../../build/linux/unbundle/icu.gn pdfium/third_party/icu/BUILD.gn
122+
# Create fake gclient_args.gni file to satisfy include list for build/config/compiler/compiler.gni
123+
touch pdfium/build/config/gclient_args.gni
124+
# Exclude test fonts from build
125+
sed -i '/"\/\/third_party\/test_fonts",/s/^/#/g' pdfium/testing/BUILD.gn
126+
# Build
127+
gn --root=pdfium gen pdfium/out/Release --args="is_clang=false use_sysroot=false is_debug=false symbol_level=0 pdf_enable_v8=false pdf_enable_xfa=false treat_warnings_as_errors=false use_system_libjpeg=true use_system_zlib=true pdf_bundle_freetype=false use_system_freetype=true use_system_lcms2=true use_system_libpng=true use_custom_libcxx=false pdf_is_standalone=true use_system_libopenjpeg2=true is_component_build=true use_gold=false"
128+
ninja -C pdfium/out/Release pdfium
129+
sed -e 's/@VERSION@/'"$PDFIUM_GIT_VERSION"'/g' -e 's#^\s*prefix\s*=.*$#prefix='"$DEST"'#' -i libpdfium.pc
130+
# Install
131+
install -D -m644 pdfium/LICENSE "$DEST/share/licenses/pdfium/LICENSE"
132+
install -D pdfium/public/*.h --target-directory="$DEST/include/pdfium"
133+
install -D pdfium/public/cpp/* --target-directory="$DEST/include/pdfium/cpp"
134+
install -D pdfium/docs/* --target-directory="$DEST/share/doc/pdfium"
135+
install -Dm755 pdfium/out/Release/libpdfium.so --target-directory="$DEST/lib"
136+
install -Dm644 libpdfium.pc --target-directory="$DEST/lib/pkgconfig"
137+
138+
# regenerate dynamic linker cache
139+
ldconfig
140+
141+
# compile and install YACReader
142+
git clone --branch "$YACREADER_GIT_TAG" --depth 1 "$YACREADER_GIT_URL" yacreader
143+
cd yacreader
144+
qmake CONFIG+="unarr pdfium server_bundled"
145+
make -j$(nproc)
146+
mkdir -p "$BUILD_DIR"/AppDir{YACReader,YACReaderLibrary}
147+
make sub-YACReader-install_subtargets INSTALL_ROOT="$BUILD_DIR/AppDirYACReader"
148+
make sub-YACReaderLibrary-install_subtargets INSTALL_ROOT="$BUILD_DIR/AppDirYACReaderLibrary"
149+
cd ..
150+
151+
# compile wrapper for YACReaderLibrary in order to find YACReader
152+
gcc $CFLAGS $LDFLAGS -o "$BUILD_DIR/AppDirYACReaderLibrary/usr/bin/YACReader" "$OUT_DIR/YACReader.c"
153+
strip -s "$BUILD_DIR/AppDirYACReaderLibrary/usr/bin/YACReader"
154+
155+
# use a custom plugin to set the PATH inside the appimage and find the YACReader wrapper
156+
cp "$OUT_DIR/linuxdeploy-plugin-path.sh" .
157+
158+
# create appimages
159+
curl -sSLo linuxdeploy-x86_64.AppImage https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
160+
chmod +x linuxdeploy-x86_64.AppImage
161+
curl -sSLo linuxdeploy-plugin-qt-x86_64.AppImage https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
162+
chmod +x linuxdeploy-plugin-qt-x86_64.AppImage
163+
curl -sSLo linuxdeploy-plugin-appimage-x86_64.AppImage https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage
164+
chmod +x linuxdeploy-plugin-appimage-x86_64.AppImage
165+
166+
./linuxdeploy-x86_64.AppImage --appdir AppDirYACReader \
167+
--executable AppDirYACReader/usr/bin/YACReader \
168+
--desktop-file AppDirYACReader/usr/share/applications/YACReader.desktop \
169+
--icon-file AppDirYACReader/usr/share/icons/hicolor/scalable/apps/YACReader.svg \
170+
--plugin qt \
171+
--output appimage
172+
./linuxdeploy-x86_64.AppImage --appdir AppDirYACReaderLibrary \
173+
--executable AppDirYACReaderLibrary/usr/bin/YACReaderLibrary \
174+
--desktop-file AppDirYACReaderLibrary/usr/share/applications/YACReaderLibrary.desktop \
175+
--icon-file AppDirYACReaderLibrary/usr/share/icons/hicolor/scalable/apps/YACReaderLibrary.svg \
176+
--plugin qt \
177+
--plugin path \
178+
--output appimage
179+
mv YACReader*.AppImage "$OUT_DIR"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#! /bin/bash
2+
3+
# exit whenever a command called in this script fails
4+
set -e
5+
6+
appdir=""
7+
8+
show_usage() {
9+
echo "Usage: bash $0 --appdir <AppDir>"
10+
}
11+
12+
while [ "$1" != "" ]; do
13+
case "$1" in
14+
--plugin-api-version)
15+
echo "0"
16+
exit 0
17+
;;
18+
--appdir)
19+
appdir="$2"
20+
shift
21+
shift
22+
;;
23+
*)
24+
echo "Invalid argument: $1"
25+
echo
26+
show_usage
27+
exit 2
28+
esac
29+
done
30+
31+
if [[ "$appdir" == "" ]]; then
32+
show_usage
33+
exit 2
34+
fi
35+
36+
echo "linuxdeploy-plugin-path"
37+
echo "\$LINUXDEPLOY: \"$LINUXDEPLOY\""
38+
39+
# install a path AppRun hook
40+
# usually, they're not supposed to print anything, but remain as silent as possible
41+
set -x
42+
mkdir -p "$appdir"/apprun-hooks
43+
cat > "$appdir"/apprun-hooks/linuxdeploy-plugin-path.sh <<\EOF
44+
export PATH="$APPDIR/usr/bin:$PATH"
45+
EOF

0 commit comments

Comments
 (0)