feature/generador-instaladores-linux-windows
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# Descarga 7zz y bibliotecas ODBC para empaquetar en el binario Linux.
|
||||
# Descarga y EMBEBE (build-time) todo lo que el binario Linux necesita en runtime:
|
||||
# - 7zz (7-Zip para Linux)
|
||||
# - Driver MS ODBC 18 + unixODBC
|
||||
# - Libs de sistema de Qt (cluster xcb/X11 + EGL) y del stack ODBC
|
||||
# (libltdl, Kerberos/GSSAPI, OpenSSL) que PySide6/pyodbc cargan por dlopen
|
||||
# y que NO vienen dentro del wheel.
|
||||
# Objetivo: que el onefile corra en un servidor Linux "pelado" sin instalar nada.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
@@ -7,17 +13,55 @@ VERSIONS="$ROOT/packaging/bundled-versions.json"
|
||||
BUNDLED="$ROOT/packaging/bundled/linux"
|
||||
SEVEN="$BUNDLED/7zip"
|
||||
ODBC="$BUNDLED/odbc/lib"
|
||||
QTLIB="$BUNDLED/qt/lib" # libs de sistema extra a embeder en la raíz de _MEIPASS
|
||||
|
||||
mkdir -p "$SEVEN" "$ODBC"
|
||||
mkdir -p "$SEVEN" "$ODBC" "$QTLIB"
|
||||
|
||||
read_url() {
|
||||
python3 -c "import json; print(json.load(open('$VERSIONS'))['$1'])"
|
||||
}
|
||||
|
||||
LINUX_7Z_URL="$(read_url seven_zip_linux_x64)"
|
||||
MSODBC_DEB="$(read_url msodbcsql18_deb)"
|
||||
# Descarga uno o más paquetes .deb (y NO sus dependencias), extrae sus .so y los
|
||||
# copia al directorio destino con el NOMBRE DE SONAME (lo que busca el loader:
|
||||
# libfoo.so.N), dereferenciando symlinks para no dejar enlaces colgantes.
|
||||
# Requiere apt-get/dpkg-deb.
|
||||
fetch_pkg_libs() {
|
||||
local destdir="$1"; shift
|
||||
if ! command -v apt-get >/dev/null 2>&1; then
|
||||
echo " (apt-get no disponible; se omite descarga de $* — el entorno de build debe proveerlas)"
|
||||
return 0
|
||||
fi
|
||||
local tmp; tmp=$(mktemp -d)
|
||||
(
|
||||
cd "$tmp"
|
||||
apt-get download "$@" >/dev/null 2>&1 || {
|
||||
# Reintento tras refrescar índices (build env con red).
|
||||
apt-get update -qq >/dev/null 2>&1 || true
|
||||
apt-get download "$@" >/dev/null 2>&1 || true
|
||||
}
|
||||
for deb in *.deb; do
|
||||
[[ -f "$deb" ]] || continue
|
||||
dpkg-deb -x "$deb" x
|
||||
done
|
||||
[[ -d x ]] || exit 0
|
||||
# 1) Symlinks SONAME del propio paquete (libfoo.so.N -> libfoo.so.N.M.P):
|
||||
# copiar el contenido REAL bajo el nombre del symlink (= SONAME exacto).
|
||||
while IFS= read -r link; do
|
||||
cp -Lf "$link" "$destdir/$(basename "$link")" 2>/dev/null || true
|
||||
done < <(find x -type l -name '*.so.*')
|
||||
# 2) Archivos reales sin symlink: derivar SONAME por truncación de versión
|
||||
# (libfoo.so.N.M.P -> libfoo.so.N) para no dejarlos con nombre versionado.
|
||||
while IFS= read -r f; do
|
||||
local soname
|
||||
soname=$(basename "$f" | sed -E 's/(\.so\.[0-9]+)\..*/\1/')
|
||||
[[ -e "$destdir/$soname" ]] || cp -Lf "$f" "$destdir/$soname" 2>/dev/null || true
|
||||
done < <(find x -type f -name '*.so.*')
|
||||
)
|
||||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
echo "==> 7-Zip Linux (7zz)"
|
||||
LINUX_7Z_URL="$(read_url seven_zip_linux_x64)"
|
||||
if [[ ! -f "$SEVEN/7zz" ]]; then
|
||||
TMP=$(mktemp -d)
|
||||
curl -fsSL -o "$TMP/7z.tar.xz" "$LINUX_7Z_URL"
|
||||
@@ -31,6 +75,7 @@ else
|
||||
fi
|
||||
|
||||
echo "==> ODBC Driver 18 + unixODBC"
|
||||
MSODBC_DEB="$(read_url msodbcsql18_deb)"
|
||||
if [[ -z "$(ls -A "$ODBC" 2>/dev/null || true)" ]]; then
|
||||
TMP=$(mktemp -d)
|
||||
cd "$TMP"
|
||||
@@ -38,21 +83,74 @@ if [[ -z "$(ls -A "$ODBC" 2>/dev/null || true)" ]]; then
|
||||
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq
|
||||
apt-get update -qq || true
|
||||
apt-get install -y -qq unixodbc dpkg-dev > /dev/null 2>&1 || true
|
||||
if dpkg -l unixodbc 2>/dev/null | grep -q ^ii; then
|
||||
find /usr/lib -name 'libodbc*.so*' -exec cp -P {} "$ODBC/" \; 2>/dev/null || true
|
||||
find /usr/lib -name 'libodbcinst*.so*' -exec cp -P {} "$ODBC/" \; 2>/dev/null || true
|
||||
# -L: dereferencia symlinks para no dejar enlaces colgantes en el destino.
|
||||
find /usr/lib -name 'libodbc*.so*' -exec cp -Lf {} "$ODBC/" \; 2>/dev/null || true
|
||||
find /usr/lib -name 'libodbcinst*.so*' -exec cp -Lf {} "$ODBC/" \; 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
dpkg-deb -x msodbcsql18.deb msodbcsql
|
||||
find msodbcsql -name '*.so*' -exec cp -P {} "$ODBC/" \;
|
||||
# Copiar SOLO el archivo real versionado del driver (evita el symlink -> /opt).
|
||||
find msodbcsql -type f -name 'libmsodbcsql-18*.so*' -exec cp -Lf {} "$ODBC/" \;
|
||||
cd "$ROOT"
|
||||
rm -rf "$TMP"
|
||||
echo " Bibliotecas ODBC en $ODBC"
|
||||
|
||||
# Stack de dependencias del driver MS ODBC 18, JUNTO al driver, para que un
|
||||
# servidor pelado (sin unixODBC/krb5/openssl) pueda cargarlo. El driver se
|
||||
# patchelf-ea a RPATH=$ORIGIN (más abajo) para resolverlas en su propio dir.
|
||||
ODBC_DEP_PKGS=(
|
||||
libltdl7 libkrb5-3 libgssapi-krb5-2 libk5crypto3 libkrb5support0
|
||||
libcom-err2 libkeyutils1 libssl3 libodbc2 libodbcinst2
|
||||
)
|
||||
fetch_pkg_libs "$ODBC" "${ODBC_DEP_PKGS[@]}" || true
|
||||
fetch_pkg_libs "$ODBC" unixodbc || true
|
||||
echo " Bibliotecas ODBC + deps en $ODBC"
|
||||
else
|
||||
echo " ODBC ya existe"
|
||||
fi
|
||||
|
||||
# RPATH=$ORIGIN en TODAS las .so del cluster ODBC: así el driver y sus deps
|
||||
# (libkrb5 -> libk5crypto/libkrb5support/libkeyutils, libgssapi, libltdl,
|
||||
# libodbcinst, openssl) se resuelven entre sí en su propio directorio una vez
|
||||
# copiados a config/odbc/lib, sin depender de LD_LIBRARY_PATH.
|
||||
if command -v patchelf >/dev/null 2>&1; then
|
||||
for so in "$ODBC"/*.so*; do
|
||||
[[ -f "$so" && ! -L "$so" ]] || continue
|
||||
patchelf --set-rpath '$ORIGIN' "$so" 2>/dev/null || true
|
||||
done
|
||||
echo " RPATH=\$ORIGIN aplicado a todo el cluster ODBC"
|
||||
else
|
||||
echo " ADVERTENCIA: patchelf no disponible; el driver ODBC podría no resolver" >&2
|
||||
echo " sus deps en un servidor sin unixODBC/krb5. Instálalo en el entorno de build." >&2
|
||||
fi
|
||||
|
||||
echo "==> Libs de sistema Qt (cluster xcb/X11 + EGL) para la GUI con display"
|
||||
if [[ -z "$(ls -A "$QTLIB" 2>/dev/null || true)" ]]; then
|
||||
# Plataforma Qt xcb + su cierre X11/xcb + EGL. Van junto a las libs Qt en el
|
||||
# onefile (PySide6/Qt/lib) para que libQt6XcbQpa las encuentre por $ORIGIN.
|
||||
QT_XCB_PKGS=(
|
||||
libxcb-cursor0 libxcb-icccm4 libxcb-util1 libxcb-image0 libxcb-keysyms1
|
||||
libxcb-render-util0 libxcb-render0 libxcb-shape0 libxcb-xkb1
|
||||
libxkbcommon-x11-0 libxkbcommon0 libxtst6 libxcomposite1 libxdamage1
|
||||
libxrandr2 libxkbfile1 libxcb1 libx11-6 libx11-xcb1 libxext6 libxrender1
|
||||
libxi6 libxfixes3 libxcb-glx0 libxcb-randr0 libxcb-shm0 libxcb-sync1
|
||||
libxcb-present0 libxcb-dri2-0 libxcb-dri3-0 libxcb-xfixes0 libxau6
|
||||
libxdmcp6 libbsd0 libsm6 libice6
|
||||
)
|
||||
QT_GL_PKGS=(libglvnd0 libegl1 libgl1 libopengl0 libglx0 libgles2)
|
||||
fetch_pkg_libs "$QTLIB" "${QT_XCB_PKGS[@]}"
|
||||
fetch_pkg_libs "$QTLIB" "${QT_GL_PKGS[@]}"
|
||||
COUNT=$(find "$QTLIB" -type f -name '*.so*' 2>/dev/null | wc -l)
|
||||
echo " $COUNT libs Qt embebidas en $QTLIB"
|
||||
if [[ "$COUNT" -eq 0 ]]; then
|
||||
echo " ADVERTENCIA: no se embebió ninguna lib Qt. El entorno de build" >&2
|
||||
echo " (docker-build-linux.sh) debe traerlas para que PyInstaller las incluya." >&2
|
||||
fi
|
||||
else
|
||||
echo " Libs Qt ya existen ($(find "$QTLIB" -type f -name '*.so*' | wc -l) archivos)"
|
||||
fi
|
||||
|
||||
echo "Listo: $BUNDLED"
|
||||
|
||||
Reference in New Issue
Block a user