Ce guide décrit une méthode reproductible pour construire un environnement Windrop portable sous Cygwin autour des composants suivants : OpenSSL 3.6.1, Tcl 9.0.3, TclTLS 2.0, tcllib 2.0 et Eggdrop 1.10.1, avec les modules additionnels optionnels : botnetop, gseen et stats
L’objectif est de produire un arbre propre, isolé et relançable, sans dépendre d’un état implicite de la session ni d’un ancien build.
Le principe est simple :
Un grand merci à Michael Ortmann pour le guide original. Il a fourni une excellente base de départ, très utile pour reproduire un build Windrop portable moderne. Ce HOWTO s’appuie sur ce travail et documente les étapes supplémentaires, les correctifs et les détails de packaging nécessaires pour rendre l’ensemble réellement reproductible en pratique.
Installer au minimum les paquets suivants :
text autoconf2.7 automake1.17 binutils gcc-core gcc-g++ make mingw64-x86_64-gcc-core pkg-config git wget curl zip unzip tar xz patch perl python3 python3-devel rebase dash zlib zlib-devel
for cmd in gcc g++ make autoconf pkg-config tar wget; do printf '%-12s ' "$cmd" if command -v "$cmd" >/dev/null 2>&1; then "$cmd" --version 2>/dev/null | head -1 else echo "KO" fi done printf '%-12s ' "nproc" if command -v nproc >/dev/null 2>&1; then nproc else echo "KO" fi
Comme Eggdrop peut construire python.mod, vérifier aussi :
echo "python3: $(command -v python3 2>/dev/null || echo KO)" echo "python version: $(python3 --version 2>/dev/null || echo KO)" echo "python3-config: $(readlink -f /usr/bin/python3-config 2>/dev/null || echo KO)" echo "includes: $(/usr/bin/python3-config --includes 2>/dev/null || echo KO)" echo "ldflags: $(/usr/bin/python3-config --ldflags 2>/dev/null || echo KO)"
Point important sous Cygwin
Le flux ci-dessous permet aussi d’intégrer, de façon optionnelle, trois modules externes souvent associés aux builds Windrop récents
Ils sont récupérés via git clone, d’où la présence de git dans les prérequis.
Sous Cygwin, les compilations peuvent être accélérées avec :
nproc make -j"$(nproc)"
Dans ce guide :
Définir ces variables au début de la session :
export BUILD_ROOT=/home/eggbox/windrop-build export WINDROP_ROOT=/home/eggbox/windrop-root export OPENSSL_PREFIX=$WINDROP_ROOT/openssl export TCL_PREFIX=$WINDROP_ROOT/tcl export PATH="$TCL_PREFIX/bin:$OPENSSL_PREFIX/bin:/bin:/usr/bin:$PATH" export LD_LIBRARY_PATH="$OPENSSL_PREFIX/lib:$OPENSSL_PREFIX/lib64:$TCL_PREFIX/lib" export TCLLIBPATH="$TCL_PREFIX/lib" export PKG_CONFIG_PATH="$OPENSSL_PREFIX/lib/pkgconfig:$OPENSSL_PREFIX/lib64/pkgconfig"
echo "BUILD_ROOT=$BUILD_ROOT" echo "WINDROP_ROOT=$WINDROP_ROOT" echo "OPENSSL_PREFIX=$OPENSSL_PREFIX" echo "TCL_PREFIX=$TCL_PREFIX"
Si vous ouvrez plus tard une nouvelle session Cygwin, il suffit de relancer ce bloc.
Créer l’arborescence de travail :
mkdir -p "$BUILD_ROOT"/{src,build} "$WINDROP_ROOT"
find "$BUILD_ROOT" -maxdepth 2 -type d | sort find "$WINDROP_ROOT" -maxdepth 2 -type d | sort
Se placer dans le répertoire des sources :
mkdir -p "$BUILD_ROOT/src" cd "$BUILD_ROOT/src"
wget -O openssl-3.6.1.tar.gz "https://github.com/openssl/openssl/releases/download/openssl-3.6.1/openssl-3.6.1.tar.gz" wget -O tcl9.0.3-src.tar.gz "https://prdownloads.sourceforge.net/tcl/tcl9.0.3-src.tar.gz" wget -O tcltls-2.0-src.tar.gz "https://core.tcl-lang.org/tcltls/uv/tcltls-2.0-src.tar.gz" wget -O eggdrop-1.10.1.tar.gz "https://ftp.eggheads.org/pub/eggdrop/source/1.10/eggdrop-1.10.1.tar.gz" wget -O tcllib-2.0.tar.gz "https://core.tcl-lang.org/tcllib/tarball/tcllib-2.0.tar.gz?r=tcllib-2-0"
Ces modules ne sont pas fournis sous forme d’archives .tar.gz dans ce guide. Ils seront récupérés plus tard directement dans l’arbre Eggdrop via Git.
Pour éviter les cd fragiles, utiliser systématiquement cette méthode :
cd "$BUILD_ROOT/build" export ARCHIVE="$BUILD_ROOT/src/monarchive.tar.gz" export SRC_DIR="$(tar tzf "$ARCHIVE" | head -1 | cut -d/ -f1)" echo "$SRC_DIR" tar xzf "$ARCHIVE" cd "$SRC_DIR"
rm -rf "$OPENSSL_PREFIX" mkdir -p "$OPENSSL_PREFIX"
cd "$BUILD_ROOT/build" export ARCHIVE="$BUILD_ROOT/src/openssl-3.6.1.tar.gz" export SRC_DIR="$(tar tzf "$ARCHIVE" | head -1 | cut -d/ -f1)" tar xzf "$ARCHIVE" cd "$SRC_DIR"
./Configure --prefix="$OPENSSL_PREFIX" shared Cygwin-x86_64
La cible doit être Cygwin-x86_64 avec un C majuscule.
make -j"$(nproc)" make install_sw
chmod 755 "$OPENSSL_PREFIX/bin/cygcrypto-3.dll" 2>/dev/null || true chmod 755 "$OPENSSL_PREFIX/bin/cygssl-3.dll" 2>/dev/null || true
"$OPENSSL_PREFIX/bin/openssl" version -a ls -l "$OPENSSL_PREFIX/bin"/cyg*.dll
rm -rf "$TCL_PREFIX" mkdir -p "$TCL_PREFIX" mkdir -p "$TCL_PREFIX/man/mann"
cd "$BUILD_ROOT/build" export ARCHIVE="$BUILD_ROOT/src/tcl9.0.3-src.tar.gz" export SRC_DIR="$(tar tzf "$ARCHIVE" | head -1 | cut -d/ -f1)" tar xzf "$ARCHIVE" cd "$SRC_DIR/unix"
./configure --prefix="$TCL_PREFIX" make -j"$(nproc)" make install ln -sf "$TCL_PREFIX/bin/tclsh9.0" "$TCL_PREFIX/bin/tclsh"
"$TCL_PREFIX/bin/tclsh9.0" <<'EOF' puts "Tcl=[info patchlevel]" puts "auto_path=$auto_path" EOF
Résultat attendu : Tcl=9.0.3
rm -rf "$TCL_PREFIX/lib/tcltls2.0"
cd "$BUILD_ROOT/build" export ARCHIVE="$BUILD_ROOT/src/tcltls-2.0-src.tar.gz" export SRC_DIR="$(tar tzf "$ARCHIVE" | head -1 | cut -d/ -f1)" tar xzf "$ARCHIVE" cd "$SRC_DIR"
make distclean 2>/dev/null || true make clean 2>/dev/null || true
./configure --prefix="$TCL_PREFIX" --with-tcl="$TCL_PREFIX/lib" --with-tclinclude="$TCL_PREFIX/include" \ CPPFLAGS="-I$OPENSSL_PREFIX/include -I$TCL_PREFIX/include" \ LDFLAGS="-L$OPENSSL_PREFIX/lib -L$OPENSSL_PREFIX/lib64 -L$TCL_PREFIX/lib"
make -j"$(nproc)" make install
chmod 755 "$TCL_PREFIX/lib/tcltls2.0/cygtcl9tls2.0.dll" 2>/dev/null || true chmod 755 "$OPENSSL_PREFIX/bin/cygcrypto-3.dll" 2>/dev/null || true chmod 755 "$OPENSSL_PREFIX/bin/cygssl-3.dll" 2>/dev/null || true find "$TCL_PREFIX/lib/tcltls2.0" -type d -exec chmod 755 {} \; 2>/dev/null || true
"$TCL_PREFIX/bin/tclsh9.0" <<'EOF' puts "Tcl=[info patchlevel]" puts "tls=[package require tls]" EOF
Résultat attendu :
cd "$BUILD_ROOT/build" export ARCHIVE="$BUILD_ROOT/src/tcllib-2.0.tar.gz" export SRC_DIR="$(tar tzf "$ARCHIVE" | head -1 | cut -d/ -f1)" tar xzf "$ARCHIVE" cd "$SRC_DIR"
make clean 2>/dev/null || true rm -rf "$TCL_PREFIX/lib/tcllib2.0" rm -rf "$TCL_PREFIX/man" mkdir -p "$TCL_PREFIX/man/mann"
Dans cet environnement, tcllib 2.0 peut échouer avec le message error deleting ”…/tcllib2.0/page/plugins”: directory not empty
Sauvegarde cp -a installer.tcl installer.tcl.orig
Patch Perl
perl -0pi -e 's/run file delete \$sub/set __visible [glob -nocomplain [file join \$sub *]]\n set __hidden [glob -nocomplain -types hidden [file join \$sub *]]\n if {![llength [concat \$__visible \$__hidden]]} {\n catch {run file delete -force -- \$sub}\n }/s' installer.tcl
Vérification visuelle nl -ba installer.tcl | sed -n '129,140p'
./configure --prefix="$TCL_PREFIX"
Ne pas utiliser make simple : il essaie aussi de lancer une étape critcl.
make install-tcl
"$TCL_PREFIX/bin/tclsh9.0" <<'EOF' package require fileutil puts "tcllib OK" EOF
rm -rf "$WINDROP_ROOT/eggdrop-1.10.1"
cd "$BUILD_ROOT/build" export ARCHIVE="$BUILD_ROOT/src/eggdrop-1.10.1.tar.gz" export SRC_DIR="$(tar tzf "$ARCHIVE" | head -1 | cut -d/ -f1)" tar xzf "$ARCHIVE" cd "$SRC_DIR"
Si l’objectif est de reproduire un build enrichi avec botnetop, gseen et stats, cloner les dépôts dans src/mod avant la configuration :
cd "$BUILD_ROOT/build/$SRC_DIR/src/mod" env -i HOME="$HOME" USER="$USER" TERM="$TERM" PATH="/bin:/usr/bin" git clone --depth=1 https://github.com/michaelortmann/botnetop.mod.git env -i HOME="$HOME" USER="$USER" TERM="$TERM" PATH="/bin:/usr/bin" git clone --depth=1 https://github.com/michaelortmann/gseen.mod.git env -i HOME="$HOME" USER="$USER" TERM="$TERM" PATH="/bin:/usr/bin" git clone --depth=1 https://github.com/michaelortmann/stats.mod.git cd "$BUILD_ROOT/build/$SRC_DIR"
Cette étape est optionnelle. Si ces modules ne sont pas nécessaires, passer directement à la configuration.
Eggdrop autodétecte correctement Tcl dans ce contexte. En revanche, il faut fournir explicitement les chemins vers leaders OpenSSL, les bibliothèques OpenSSL et python3-config
export PYTHON_CONFIG=/usr/bin/python3-config ./configure \ --prefix="$WINDROP_ROOT/eggdrop-1.10.1" \ --with-sslinc="$OPENSSL_PREFIX/include" \ --with-ssllib="$OPENSSL_PREFIX/lib" \ --with-python-config="$PYTHON_CONFIG"
make config
Contrôler les flags générés :
grep -n '^PYTHON_CFLAGS\|^PYTHON_LDFLAGS' src/mod/python.mod/Makefile
Résultat attendu :
Si //include ou //lib apparaissent encore, interrompre ici et corriger la détection Python avant compilation.
make -j"$(nproc)"
make install DEST="$WINDROP_ROOT/eggdrop-1.10.1"
cd "$BUILD_ROOT" export PATH="$TCL_PREFIX/bin:$OPENSSL_PREFIX/bin:/bin:/usr/bin:$PATH" export LD_LIBRARY_PATH="$OPENSSL_PREFIX/lib:$OPENSSL_PREFIX/lib64:$TCL_PREFIX/lib" export TCLLIBPATH="$TCL_PREFIX/lib" "$TCL_PREFIX/bin/tclsh9.0" <<'EOF' puts "Tcl=[info patchlevel]" puts "tls=[package require tls]" catch {package require fileutil} r1 puts "fileutil=$r1" EOF
Ne poursuivre que si tout répond correctement.
Pour qu’un bundle Windrop portable puisse être lancé directement depuis Windows, il ne suffit pas d’installer Eggdrop : il faut aussi copier dans la racine du bot les DLL runtime nécessaires. Copier les fichiers nécessaires dans $WINDROP_ROOT/eggdrop-1.10.1/
cd "$WINDROP_ROOT/eggdrop-1.10.1/" cp -f /bin/cygwin1.dll "$WINDROP_ROOT/eggdrop-1.10.1/" cp -f /bin/cygz.dll "$WINDROP_ROOT/eggdrop-1.10.1/" cp -f /bin/cyggcc_s-seh-1.dll "$WINDROP_ROOT/eggdrop-1.10.1/" cp -f "$OPENSSL_PREFIX/bin/cygcrypto-3.dll" "$WINDROP_ROOT/eggdrop-1.10.1/" cp -f "$OPENSSL_PREFIX/bin/cygssl-3.dll" "$WINDROP_ROOT/eggdrop-1.10.1/" cp -f "$TCL_PREFIX/bin/cygtcl9.0.dll" "$WINDROP_ROOT/eggdrop-1.10.1/"
À ce stade, la racine du bot doit contenir au minimum eggdrop.exe-1.10.1, cygwin1.dll, cygz.dll, cyggcc_s-seh-1.dll, cygcrypto-3.dll, cygssl-3.dll et cygtcl9.0.dll
Sans cette étape, un lancement direct depuis cmd.exe peut échouer avec un message indiquant qu’une DLL est manquante.
Le bundle portable repose sur scripts/autoload_pkgs.tcl pour charger les packages Tcl depuis l’arborescence locale ./lib, sans dépendre d’un environnement Tcl installé ailleurs sur la machine.
Ce script doit donc être présent dans scripts/autoload_pkgs.tcl
La configuration minimale fournie charge explicitement ce fichier avant le wrapper HTTPS et avant les autres scripts Tcl.
# Chargeur portable depuis ./lib uniquement source scripts/autoload_pkgs.tcl
Le bundle doit donc embarquer au minimum les éléments suivants : scripts/autoload_pkgs.tcl, lib/tcl9, lib/tcllib2.0 et, si le support TLS Tcl est utilisé dans les scripts, le répertoire TclTLS portable correspondant au build.
Si le fichier fourni Windrop-portable-1.10.1-minimal.conf est utilisé avec le wrapper HTTPS Tcl 9, il faut embarquer un bundle de certificats CA dans le répertoire du bot.
L’emplacement attendu est : ssl/certs/cacert.pem
Créer l’arborescence puis télécharger cacert.pem :
mkdir -p "$WINDROP_ROOT/eggdrop-1.10.1/ssl/certs" wget -O "$WINDROP_ROOT/eggdrop-1.10.1/ssl/certs/cacert.pem" "https://curl.se/ca/cacert.pem"
Vérification de la présence du bundle CA :
ls -lh "$WINDROP_ROOT/eggdrop-1.10.1/ssl/certs/cacert.pem"
Si le fichier de configuration est inclus dans le bundle, il est alors possible d’y utiliser :
set ::httpscompat::cafile "ssl/certs/cacert.pem"
Puis de décommenter le chargement du wrapper HTTPS si nécessaire :
source scripts/https_compat_tcl9.tcl
Cette étape n’est utile que si des scripts Tcl utilisent réellement package http, en particulier avec des URLs https://.
Une installation Eggdrop sous Cygwin peut laisser des liens symboliques dans l’arbre installé, notamment :
Pour obtenir un répertoire réellement portable et facile à copier depuis le filesystem Windows, il est préférable de remplacer ces liens par de vrais fichiers et de vrais répertoires.
cd "$WINDROP_ROOT/eggdrop-1.10.1" rm -f eggdrop.exe cp -f eggdrop.exe-1.10.1 eggdrop.exe rm -rf modules cp -a modules-1.10.1 modules
Si botnetop.mod, gseen.mod et stats.mod ont été clonés et compilés, copier ensuite leurs fichiers de configuration et de langue dans l’arbre installé :
cd "$BUILD_ROOT/build/$SRC_DIR" cp src/mod/botnetop.mod/botnetop.conf "$WINDROP_ROOT/eggdrop-1.10.1" 2>/dev/null || true cp src/mod/gseen.mod/gseen.conf "$WINDROP_ROOT/eggdrop-1.10.1" 2>/dev/null || true cp src/mod/gseen.mod/*.lang "$WINDROP_ROOT/eggdrop-1.10.1/language/" 2>/dev/null || true cp src/mod/stats.mod/stats.conf "$WINDROP_ROOT/eggdrop-1.10.1" 2>/dev/null || true cp src/mod/stats.mod/language/* "$WINDROP_ROOT/eggdrop-1.10.1/language/" 2>/dev/null || true cp -r src/mod/stats.mod/templates "$WINDROP_ROOT/eggdrop-1.10.1" 2>/dev/null || true
Ces copies sont elles aussi optionnelles et n’ont de sens que si les modules ont été ajoutés plus tôt dans l’arbre Eggdrop.
find "$WINDROP_ROOT/eggdrop-1.10.1" -maxdepth 3 -ls
Le fichier fourni (Windrop-portable-1.10.1-minimal.conf) sert de base de départ.
Avant le premier lancement, vérifier au minimum :
Le wrapper HTTPS Tcl 9 est prévu mais reste désactivé par défaut :
#source scripts/https_compat_tcl9.tcl
Le wrapper HTTPS Tcl 9 / TclTLS 2.0 rétablit une compatibilité propre pour les scripts Tcl utilisant package http, en particulier avec des URLs en https, dans un bundle Windrop portable basé sur Tcl 9, TclTLS 2.0 et tcllib 2.0.
Ce wrapper doit être chargé avant les scripts Tcl qui utilisent HTTP/HTTPS.
Archive fournie : https_compat_tcl9-1.4.zip
# Optional overrides before loading: # set ::httpscompat::debug 1 # set ::httpscompat::cafile "ssl/certs/cacert.pem" # set ::httpscompat::selftest_host "google.com" source scripts/https_compat_tcl9.tcl
Si ce wrapper est activé, il est aussi recommandé d’embarquer un bundle CA portable dans ssl/certs/cacert.pem et de définir dans la configuration :
set ::httpscompat::cafile "ssl/certs/cacert.pem"
Cette annexe complète la section du HOWTO consacrée au bundle CA portable et à la configuration initiale.
Dans l’arbre installé, eggdrop.exe peut être un lien symbolique ou un stub non directement exploitable selon le contexte Windows. Le vrai binaire à lancer est généralement eggdrop.exe-1.10.1.
Le plus simple consiste donc à fournir un lanceur eggdrop.cmd placé dans le répertoire d’installation Eggdrop.
Ce wrapper :
@echo off setlocal EnableExtensions set "BASE_DIR=%~dp0" if "%BASE_DIR:~-1%"=="\" set "BASE_DIR=%BASE_DIR:~0,-1%" set "EGGDIR=%BASE_DIR%" set "OPENSSL_DIR=%EGGDIR%\..\openssl" set "TCL_DIR=%EGGDIR%\..\tcl" set "BINARY=%EGGDIR%\eggdrop.exe-1.10.1" if not exist "%BINARY%" ( echo [ERROR] Could not find binary : "%BINARY%" exit /b 1 ) set "PATH=%OPENSSL_DIR%\bin;%TCL_DIR%\bin;%PATH%" set "TCL_LIBRARY=%TCL_DIR%\lib\tcl9" set "TCLLIBPATH=%TCL_DIR%\lib" set "SSL_CERT_DIR=%EGGDIR%\ssl\certs" set "SSL_CERT_FILE=%EGGDIR%\ssl\certs\cacert.pem" pushd "%EGGDIR%" >nul 2>&1 if errorlevel 1 ( echo [ERROR] Could not change directory to "%EGGDIR%" exit /b 1 ) "%BINARY%" %* set "RC=%ERRORLEVEL%" popd >nul 2>&1 exit /b %RC%
À ce stade de l’installation, il ne faut plus utiliser le shell Cygwin mais une cmd.exe classique. Le répertoire /home/eggbox/windrop-root/eggdrop-1.10.1 peut être copié n’importe où sur le filesystem Windows.
bot.conf est donné ici à titre indicatif. En pratique, il faut partir du fichier Windrop-portable-1.10.1-minimal.conf, l’adapter, puis l’utiliser avec ce lanceur.
La séquence recommandée est :
Cette méthode reste volontairement conservatrice. Elle privilégie la reproductibilité, la lisibilité et la reprise propre d’un build en cas d’échec.