Ich denke nicht. Aber ich kenne mich ziemlich gut mit dem QPKG-System aus und kann dir helfen.
Für alle, die eine App entwickeln wollen oder irgendetwas für QNAP entwickeln möchten, sage ich (weiß nicht wo), aber das Kompilieren für QTS6+ ist ziemlich einfach:
1) QTS 6 und QuTS hero basieren auf Ubuntu 24.04 / glibc.
Überprüfe es selbst auf dem Gerät: ldd --version zeigt 2.39 an. Das ist genau Ubuntu 24.04. Du brauchst also kein SDK, keine Cross-Toolchain und keinen Container für x86_64-Modelle. Einfach eine Ubuntu 24.04 VM installieren, dort bauen, Binary rüberkopieren, fertig. (Das gilt NICHT für QTS 5.x, das eine viel ältere glibc hat. Erst prüfen.)
2) Wähle ein Zielverzeichnis außerhalb von /opt.
# /opt gehört zu Entware. Wenn du Entware ein- oder ausschaltest, verschwinden deine Symlinks.
# Gib deiner App ein festes Verzeichnis und pack alles hinein:
MY_APP_DEST_DIR=/usr/bin/my_app
3) Die einzige wirklich wichtige Regel: Statische Abhängigkeiten, dynamische glibc.
Baue jede Library, die du brauchst, als statisches .a und linke sie in dein Binary. Nur glibc bleibt dynamisch.
- NICHT full-static linken (
-static). Das bricht NSS, sodass getaddrinfo() und Benutzer-Abfragen zur Laufzeit fehlschlagen.
- NICHT eigene
.so-Dateien ins /usr/lib auf der NAS kopieren. Das kollidiert mit QNAP-eigenen Libraries und kann Dinge zerstören, die nicht dir gehören.
4) Komplettes, echtes Beispiel: ncurses (Library) + htop (App).
SYSROOT=$HOME/build/sysroot # privates Präfix für Libraries, nie auf der NAS installiert
MY_APP_DEST_DIR=/usr/bin/my_app # wo die App auf der NAS liegen wird
# --- die Library: ncurses, nur statisch -------------------------------------
# --without-shared --with-normal : nur .a bauen, kein .so
# --enable-widec : libncursesw, UTF-8
# --with-fallbacks + --disable-db-install : Terminalbeschreibungen IN die Library kompilieren,
# sodass du keine terminfo-Datenbank versenden musst
# und es trotzdem auf einer blanken NAS funktioniert
cd ncurses-6.6
./configure --prefix=$SYSROOT \
--without-shared --with-normal --enable-widec \
--enable-pc-files --with-pkg-config-libdir=$SYSROOT/lib/pkgconfig \
--with-fallbacks=xterm,xterm-256color,screen,linux,vt100,dumb \
--disable-db-install \
--without-debug --without-ada --without-cxx-binding --without-tests --without-manpages \
CFLAGS="-O2 -pipe -fPIC"
make -j3 && make install # landet in $SYSROOT, nicht im System
# --- die App: htop, gegen das statische ncurses gelinkt ---------------------
# PKG_CONFIG="pkg-config --static" : Libs.private ziehen, also die volle statische Endung
# PKG_CONFIG_LIBDIR=... : NUR im sysroot suchen, nie bei Host-Libs
# --prefix : Pfad, den die App auf der NAS haben wird
# -static-libgcc : für C++-Apps auch -static-libstdc++ hinzufügen
cd ../htop-3.3.0
PKG_CONFIG="pkg-config --static" \
PKG_CONFIG_LIBDIR="$SYSROOT/lib/pkgconfig" \
./configure --prefix=$MY_APP_DEST_DIR --enable-unicode \
CFLAGS="-O2 -pipe" \
CPPFLAGS="-I$SYSROOT/include -I$SYSROOT/include/ncursesw" \
LDFLAGS="-L$SYSROOT/lib -static-libgcc"
make -j3
make install DESTDIR=$PWD/../out # Staging; DESTDIR + prefix = das Verzeichnis, das du versendest
--prefix ist der Pfad, den die Binary auf der NAS haben wird, DESTDIR ist das Staging-Verzeichnis auf der Build-Maschine. Halte sie getrennt, sonst sucht deine App ihre Config am falschen Ort.
5) Prüfe, bevor du etwas auf die NAS kopierst. Drei Kommandos für jedes Binary.
B=out/usr/bin/my_app/bin/htop
readelf -h $B | grep Machine
# Advanced Micro Devices X86-64 <- richtige Architektur
readelf -d $B | grep NEEDED
# libm.so.6, libc.so.6 <- nur glibc. ncurses ist verschwunden: steckt im Binary.
objdump -T $B | grep -oE 'GLIBC_[0-9.]+' | sort -uV | tail -1
# GLIBC_2.38 <- max. 2.39, sonst startet das Binary auf der NAS nicht
Wenn NEEDED etwas auflistet, das nicht libc/libm/libpthread/libdl/librt/libresolv/ld-linux/libgcc_s ist,
hast du vergessen, diese Abhängigkeit statisch zu linken. Geh zurück und baue die Library um, nicht die App.
6) patchelf: für die eine Library, die du nicht statisch machen kannst.
Im Beispiel oben zieht htop immer noch libcap.so.2 vom Build-Host. Zwei echte Möglichkeiten:
Option A, Feature weg lassen: ./configure --disable-capabilities. Nichts mehr zu versenden.
Option B, Library im eigenen Verzeichnis ausliefern und das Binary darauf verweisen. Dafür gibt es patchelf,
und $ORIGIN ist der Teil, den viele übersehen: Es meint „das Verzeichnis, in dem dieses Binary liegt“, zur Laufzeit aufgelöst, und funktioniert egal, wo das Paket landet.
mkdir -p out/usr/bin/my_app/lib
cp -L /lib/x86_64-linux-gnu/libcap.so.2 out/usr/bin/my_app/lib/
patchelf --set-rpath '$ORIGIN/../lib' out/usr/bin/my_app/bin/htop
# ^ einfache Anführungszeichen. Die Shell darf $ORIGIN NICHT expandieren.
readelf -d out/usr/bin/my_app/bin/htop | grep -E 'RUNPATH|NEEDED'
# RUNPATH [$ORIGIN/../lib]
ldd out/usr/bin/my_app/bin/htop | grep libcap
# libcap.so.2 => .../my_app/bin/../lib/libcap.so.2 <- deine Kopie, nicht die systemeigene
Zwei weitere Tricks mit patchelf, die du kennen solltest:
patchelf --remove-rpath $B # den absoluten Build-Maschinen-RPATH entfernen,
# den libtool gern einbackt (/home/du/build/...)
patchelf --replace-needed libfoo.so.1 libfoo.so.2 $B # Binary umleiten, wenn es nicht neu gebaut werden kann
Beachte, dass RUNPATH nur Libraries auflöst, die du tatsächlich auslieferst. Damit holt man sich keine QNAP-Libraries — und das solltest du auch nicht tun: Die ändern sich zwischen Firmware-Versionen.
7) ARM-Modelle.
Gleiche Vorgehensweise, eine Zusatzzeile. Ubuntu 24.04 liefert die Cross-Compiler mit, also installiere
gcc-aarch64-linux-gnu oder gcc-arm-linux-gnueabihf und füge zu jedem ./configure
--host=aarch64-linux-gnu (oder arm-linux-gnueabihf) hinzu und exportiere
CC/CXX/AR/RANLIB/STRIP mit passendem Präfix. Alles andere, auch die drei Prüf-Kommandos, sind identisch. Hinweis für armv7: Die alten Marvell-Geräte haben kein NEON, also handgeschriebenes NEON-Assembly entweder zur Laufzeit erkennen oder abschalten.
Alles oben wurde unter Ubuntu 24.04 als End-to-End-Test gebaut und ausgeführt: ncurses 6.6 statisch,
htop 3.3.0, GLIBC_2.38 maximal, libcap per $ORIGIN/../lib verschoben, Binary startet und zeigt Version an.
Wenn du das QNAP QPKG ganz verstehen willst, installiere einfach StorageDiag Workbench & Utilities und schau dir im CmdHelper den Workflow rund um Start/Stop-Skripte genauer an:
Frag mich, was du brauchst – ich versuche es dir zu erklären.