Skip to content
Snippets Groups Projects

Add a Makefile to bare build Duniter

Closed Stéphane Veyret requested to merge feature/barebuild into dev
All threads resolved!

Lié au ticket #1405 (closed), voici un Makefile pour fabriquer la version « nue » de Duniter.

Edited by Stéphane Veyret

Merge request reports

Loading
Loading

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
  • Stéphane Veyret marked as a Work In Progress

    marked as a Work In Progress

  • Nouvelle version suite à renommage de branche.

  • Stéphane Veyret added 3 commits

    added 3 commits

    Compare with previous version

  • Stéphane Veyret added 7 commits

    added 7 commits

    Compare with previous version

  • Stéphane Veyret unmarked as a Work In Progress

    unmarked as a Work In Progress

  • Je pense avoir terminé @librelois, mais je n'ai pas réussi à monter un environment adéquat pour comparer les résultats entre l'ancienne méthode et la nouvelle.

    Je voulais récupérer le résultat du CI, mais il semble ne pas réussir à le publier. Est-ce que tu peux me dire comment récupérer l'image Docker de test et un paquet v1.8 fabriqué avec l'ancienne méthode ? Et si tu as une idée de pourquoi les paquets que je fabrique ne se chargent pas dans la CI…

  • @sveyret l'image docker est publiée sur notre registry sous le tag test-image, tu peut la récupérée ainsi: registry.duniter.org/nodes/typescript/duniter:test-image

    C'est un registry public en lecture, ça devrait marcher sans droits particuliers.

    Par contre je pense que l'image docker ne fonctionnera pas, car tu a supprimé le flag RUSTFLAGS="-C target-feature=-crt-static" qui est essentiel pour que le binaire Rust fonctionne sous Alpine.

    Concernant le résultat de la CI, s'il ne publie pas c'est parce que les artifacts générés sont trop gros, il faudrait que tu supprime les binaires intermédiaires et autres fichiers objets liés la compilation de leveldb et sqlite.

  • Stéphane Veyret marked as a Work In Progress

    marked as a Work In Progress

  • closed

  • reopened

  • oups fausse manip, je crois que j'ai supprimé ta branche :/
    Excuse moi, je fais faire plus attention, peut tu la repushée ?

  • Stéphane Veyret restored source branch feature/barebuild

    restored source branch feature/barebuild

  • Stéphane Veyret added 7 commits

    added 7 commits

    Compare with previous version

  • Stéphane Veyret added 3 commits

    added 3 commits

    Compare with previous version

  • Je pense avoir trouvé pourquoi j'ai un résultat si gros alors que je fais un ménage bien plus important : en fait, nw et nw-gyp sont des dépendances uniquement pour le dev, et pas pour le runtime. Et ce sont de grosses dépendances, du coup, il faut que je les supprime à la fin.

  • Éloïs changed milestone to %1.8

    changed milestone to %1.8

  • nw et nw-gyp sont des dépendances uniquement pour le dev, et pas pour le runtime. Et ce sont de grosses dépendances, du coup, il faut que je les supprime à la fin.

    Bien vu, espérons que ce soit ça :)

  • @librelois, je vois aussi que le livrable ne contient pas du tout de répertoire neon. Est-ce qu'il peut être totalement supprimé après la génération du livrable ?

  • Stéphane Veyret added 2 commits

    added 2 commits

    Compare with previous version

  • Stéphane Veyret added 8 commits

    added 8 commits

    Compare with previous version

  • Stéphane Veyret added 8 commits

    added 8 commits

    Compare with previous version

  • Stéphane Veyret unmarked as a Work In Progress

    unmarked as a Work In Progress

  • @librelois ça m'a l'air bon maintenant. J'ai fait quelques tests rapides, mais il serait bien que des tests plus poussés soient fait, si tu as du temps pour ça…

  • Yep je vais tester le livrable server dans la soirée, je vais aussi essayer de lancer le script arm sur mon rpi4 :)

  • Stéphane Veyret added 3 commits

    added 3 commits

    Compare with previous version

  • Est-ce que ton RPi4 est en 64 bits ?

    C'est pour savoir si je peux considérer l'arm64 comme valide sur le paquet Gentoo.

    Edited by Stéphane Veyret
  • @librelois, lorsque j'essaie de démarrer la version bureau nue (sans toute la mise en paquet qu'il y a autour), j'ai le message « The server is not starting ». Tu as une idée de la raison ?

  • @librelois, autre question: pourquoi est-ce qu'on installe nw en tant que dépendance de duniter juste pour la compilation, puis qu'on le télécharge ensuite pour la livraison ? Ne pourrait-on pas se contenter de la version installée par npm ?

  • Est-ce que ton RPi4 est en 64 bits ?

    Mon rpi4 a un processeur 64 bits mais un OS 32 bits : voir ici pourquoi c'est ainsi par défaut : https://www.raspberrypi.org/forums/viewtopic.php?t=252369

    Comme il me sert de test pour le livrable dédié aux utilisateurs sous rpi3 et autres micro ordinateur sous architecture armv7l, je compte le laisser sur l'os 32 bits présent par défaut.

    Donc l'arm64 je ne peut pas te dire si c'est valide ou non.

    lorsque j'essaie de démarrer la version bureau nue (sans toute la mise en paquet qu'il y a autour), j'ai le message « The server is not starting ». Tu as une idée de la raison ?

    Non aucune, tout ce qui est relatif a la version desktop c'est cgeek qui a mis ça en place, il faut demander à @c-geek

    pourquoi est-ce qu'on installe nw en tant que dépendance de duniter juste pour la compilation, puis qu'on le télécharge ensuite pour la livraison ? Ne pourrait-on pas se contenter de la version installée par npm ?

    Il me semble que nw est nécessaire au runtime pour la version desktop justement, mais je me trompe peut-être, @c-geek peut tu nous éclairer ? :)

  • Donc l'arm64 je ne peut pas te dire si c'est valide ou non.

    Pas de soucis. Si quelqu'un m'indique que c'est valide, je modifierai le paquet Gentoo à ce moment là. :smile:

    Il me semble que nw est nécessaire au runtime pour la version desktop

    C'est le cas, mais j'arrive à démarrer avec la version installée par npm, donc je me demandais pourquoi télécharger en plus une version autonome…

    Bon, je suis en train de m'arracher les cheveux pour ma version nue. Je pense avoir retiré tout ce qui est bundled dans la version générée, et tout fonctionne bien. J'ai l'impression que j'ai bien les mêmes fichiers que dans la version nue. Et pourtant, le serveur de la version nue ne démarre pas…

  • j'arrive à démarrer avec la version installée par npm, donc je me demandais pourquoi télécharger en plus une version autonome…

    Bonne question, il devait y avoir une bonne raison pour laquelle @c-geek a fait comme ça a l'époque :)

    Et pourtant, le serveur de la version nue ne démarre pas…

    Mince, même la variante server ? Je croyais que tu n'avais des problèmes qu'avec la variante desktop ?

    Le paquet deb server buildé par la CI fonctionne bien chez moi.

    J'ai également buildé un paquet deb pour armv7l sur mon rpi4 et il semble bien fonctionner sur mon rpi4 :)

    Edited by Éloïs
  • Mince, même la variante server ? Je croyais que tu n'avais des problèmes qu'avec la variante desktop ?

    Non, le serveur à l'air de fonctionner. C'est le serveur de la version desktop qui ne fonctionne pas.

  • Il me semble que nw est nécessaire au runtime pour la version desktop justement, mais je me trompe peut-être, @c-geek peut tu nous éclairer ? :)

    Oui nw est nécessaire au runtime de la version Desktop. Par contre pour nw-gyp c'est plutôt au runtime a priori.

    lorsque j'essaie de démarrer la version bureau nue (sans toute la mise en paquet qu'il y a autour), j'ai le message « The server is not starting ». Tu as une idée de la raison ?

    C'est que la partie serveur crashe.

    Quand on lance la commande duniter-desktop depuis un poste Debian, c'est en réalité /opt/duniter/nw qui est lancé avec les paramètres définis dans /opt/duniter/package.json à savoir :

    "main": "index.html",
    "node-main": "./bin/duniter"

    Autrement dit :

    • la partie front va être lancée via nw + le fichier index.html ==> cette partie fonctionne bien chez toi @sveyret
    • la partie back va être lancée via un NodeJS embarqué par NW (fichier /opt/duniter/lib/libnode.so*).

    Pour savoir ce qui plante, c'est un peu casse-tête car il n'y a pas de logs tous faits. Il te faut le produire en modifiant un peu de code JS. Mais dans 99% des cas c'est une librairie écrite en C/C++, et probablement aussi en Rust.

    Ma méthode (utilisée de nombreuses fois pour Windows car c'était la plateforme la plus capricieuse vis-à-vis du code compilé) :

    1. Editer le fichier /opt/duniter/bin/duniter
    2. Remplacer son contenu en ajoutant des require("fs").writeFileSync('/tmp/etape1', 'Debug-message') aux étapes clés du lancement. Exemple :
    #!/usr/bin/env node
    "use strict";
    
    require("fs").writeFileSync('/tmp/etape1', 'Avant import des ExitCodes') // Test 1
    const ExitCodes = require("../app/lib/common-libs/exit-codes").ExitCodes;
    require("fs").writeFileSync('/tmp/etape2', 'Avant import de NewLogger') // Test 2
    const logger = require("../app/lib/logger").NewLogger();
    
    // Specific errors handling
    process.on('uncaughtException', (err) => {
      // Dunno why this specific exception is not caught
      if (err.code && err.code !== "EADDRNOTAVAIL" && err.code !== "EINVAL" && err.code !== "ENOENT") {
        logger.error(err.stack || err.message || err);
        process.exit(ExitCodes.UNCAUGHT_EXCEPTION);
      }
    });
    
    (async () => {
    
      try {
        require("fs").writeFileSync('/tmp/etape3', 'Avant autoStack') // Test 3
        const stack = require('../index').Statics.autoStack();
        require("fs").writeFileSync('/tmp/etape4', 'Avant executeStack') // Test 4
        await stack.executeStack(process.argv);
        require("fs").writeFileSync('/tmp/etape1', 'Apres executeStack') // Test 5
        // Everything went well, close Duniter quietly.
        process.exit(ExitCodes.OK);
      } catch (e) {
        require("fs").writeFileSync('/tmp/etape_error', e && e.message || e) // Erreur
        // If an unhandled error occured
        logger.error(e.stack || e.message || e);
        process.exit(ExitCodes.UNHANDLED_ERROR);
      } finally {
        // If we did not succeed to close before, force close with error.
        process.exit(ExitCodes.FORCE_CLOSE_AFTER_ERROR);
      }
    })()

    Avec l'exemple ci-dessus tu auras déjà un début de réponse avec les six logs d'étape/erreur.

    Je n'ai pas plus pratique à proposer. Par contre, cette méthode fonctionne à 100%.

    Edited by Cédric Moreau
  • Pour observer ce qui s'est passé :

    $ ll /tmp/etape*
    -rw-rw-r-- 1 cgeek cgeek 26 mai   10 16:21 /tmp/etape1
    -rw-rw-r-- 1 cgeek cgeek 25 mai   10 16:21 /tmp/etape2
    -rw-rw-r-- 1 cgeek cgeek 15 mai   10 16:21 /tmp/etape3
    -rw-rw-r-- 1 cgeek cgeek 18 mai   10 16:21 /tmp/etape4

    Ici, je n'ai eu aucun problème et Duniter fonctionne.

    Si tu as eu une erreur, tu n'auras peut-être pas été jusqu'à l'étape 4 voire tu auras eu la production d'un fichier /tmp/etape_error.

    Edited by Cédric Moreau
  • C'est le cas, mais j'arrive à démarrer avec la version installée par npm, donc je me demandais pourquoi télécharger en plus une version autonome…

    Je n'ai pas compris la question ? Tu parles du fait que Duniter Desktop embarque un node et un npm en plus ?

  • Je n'ai pas compris la question

    Actuellement, on télécharge (avec curl) une version de NW, mais lors de la compilation, on utilise une version installée par npm install nw. J'ai essayé de démarrer le bureau en utilisant cette dernière version, et cela fonctionne aussi bien. Ce que je me demandais, du coup, c'est est-ce qu'on ne pourrait pas ne plus télécharger NW et se contenter de la version installée par npm.

    Si tu as eu une erreur, tu n'auras peut-être pas été jusqu'à l'étape 4

    Non, cela s'arrête à l'étape 2 et je n'ai pas d'erreur…

    Il faudrait que j'en sache un peu plus sur NW. Sur Gentoo, je peux parfaitement installer la bonne version avec npm install nw@0.33.1, mais je ne peux pas vraiment controller la version de node que l'utilisateur souhaite utiliser. Peut-on trouver automatiquement la version ADDON_VERSION utilisée par la version de node ?

  • Pour être plus clair, j'ai une version qui fonctionne, qui a été générée par la CI, et une qui ne fonctionne pas, générée sur mon poste.

    La version qui fonctionne, fonctionne même si je supprime les fichiers installés par la version NW livrée et que j'installe nw par npm.

  • Je pense que c'est un problème de compatibilité :

    Error: /home/stephane/Developpements/duniter/work/neon/native/index.node: undefined symbol: _ZN2v82V818GlobalizeReferenceEPNS_8internal7IsolateEPm at Object.Module._extensions..node (internal/modules/cjs/loader.js:760:18) at Module.load (internal/modules/cjs/loader.js:623:32) at tryModuleLoad (internal/modules/cjs/loader.js:562:12) at Function.Module._load (internal/modules/cjs/loader.js:554:3) at Module.require (internal/modules/cjs/loader.js:661:17) at require (internal/modules/cjs/helpers.js:20:18) at Object.<anonymous> (/home/stephane/Developpements/duniter/work/neon/lib/index.js:3:16) at Module._compile (internal/modules/cjs/loader.js:713:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:730:10) at Module.load (internal/modules/cjs/loader.js:623:32)

  • Oui c'est possible, cela peut revenir au même si le nw téléchargé par npm est identique. Par contre je ne vois aucune instruction npm install nw dans les procédures de livraison, donc je ne sais pas comment tu l'obtiens.

    Non, cela s'arrête à l'étape 2 et je n'ai pas d'erreur…

    C'est typique d'un crash au chargement d'une des libraires compilées. Quand on regarde le fichier app/lib/logger.js, on voit que lui même importe app/lib/system/directory.js qui lui-même charge des dépendances à SQLite et LevelDB, qui sont compilés.

    Le plus probable c'est que ces librairies n'ont pas été compilées pour nw comme c'est réalisé par la CI :

    npm install -g node-pre-gyp || exit 1
    
    # [...]
    
    nw_compile() {
    	[[ -z ${1} ]] && exit 1
    	cd ${1} || exit 1
    	node-pre-gyp --runtime=node-webkit --target=${NW_VERSION} configure || exit 1
    	node-pre-gyp --runtime=node-webkit --target=${NW_VERSION} build || exit 1
    	[[ -z ${2} ]] || ${2} ${1} ${3}
    	cd ..
    }
    
    # [...]
    
    cd "${RELEASES}/desktop_/node_modules/"
    nw_compile leveldown nw_copy "build/Release/"
    nw_compile sqlite3 nw_copy_node
    Edited by Cédric Moreau
  • Le plus probable c'est que ces librairies n'ont pas été compilées pour nw comme c'est réalisé par la CI

    Normalement, si… Par contre, ce n'est pas la même version de node qui le fait. Est-ce que ça peut jouer ?

  • Oui complètement, l'ABI de Node 8 n'est pas celle de Node 9, et même au sein d'une même version majeure il y a des modifications d'ABI.

    Pour plus de tests :

    sudo sed '16 a require("fs").writeFileSync("/tmp/etape2.1", "Chargement SQLite")' app/lib/system/directory.js -i
    sudo sed '18 a require("fs").writeFileSync("/tmp/etape2.2", "Chargement CFS")' app/lib/system/directory.js -i
    sudo sed '22 a require("fs").writeFileSync("/tmp/etape2.3", "Chargement LevelDB")' app/lib/system/directory.js -i
    sudo sed '24 a require("fs").writeFileSync("/tmp/etape2.3", "Chargement LevelDB OK")' app/lib/system/directory.js -i

    Résultat :

    $ ll /tmp/etape*
    -rw-rw-r-- 1 cgeek cgeek 26 mai   10 17:06 /tmp/etape1
    -rw-rw-r-- 1 cgeek cgeek 25 mai   10 17:06 /tmp/etape2
    -rw-rw-r-- 1 cgeek cgeek 17 mai   10 17:06 /tmp/etape2.1
    -rw-rw-r-- 1 cgeek cgeek 14 mai   10 17:06 /tmp/etape2.2
    -rw-rw-r-- 1 cgeek cgeek 21 mai   10 17:06 /tmp/etape2.3
    -rw-rw-r-- 1 cgeek cgeek 15 mai   10 17:06 /tmp/etape3
    -rw-rw-r-- 1 cgeek cgeek 18 mai   10 17:06 /tmp/etape4
  • Ça s'arrête en étape 2.1 pour moi.

    @c-geek, du coup, comment est-ce que je peux gérer automatiquement la compilation si je ne connais pas la version de node utilisée, et que je ne contrôle que la version de nw ?

  • Oui je pense, étant donné qu'à une version de NW correspond une version de Node. Voir titre de chaque release. Exemple :

    [2018/09/11] - NW.js v0.33.1 Released with Node.js v10.10.0

    Ce qui explique dans le contenu du script build-lin.sh qu'on retrouve ces valeurs :

    ADDON_VERSION=64 # Correspond au n° de version d'addon généré pour NW en version 0.33.1
    NW_VERSION=0.33.1 # Car NW 0.33.1 embarque NodeJS 10.10.0 qui a un n° de version d'addon `64`

    Mais en fait tout ça est géré par l'instruction :

    node-pre-gyp --runtime=node-webkit --target=${NW_VERSION} configure || exit 1
    node-pre-gyp --runtime=node-webkit --target=${NW_VERSION} build || exit 1

    D'ailleurs cette commande doit générer un livrable dont l'ABI (matérialisée par un numéro de version d'addon) doit être 64, comme matérialisé par le ${ADDON_VERSION} dans le script :

    
    nw_copy() {
        # [...]
        local dest=lib/binding/Release/node-v${ADDON_VERSION}-linux-x64
        # [...]
    }
    
    # [...]
    
    ADDON_VERSION=64

    Autrement dit, tu peux vérifier la version d'addon générée par les outils que tu utilises en vérifiant le nom du fichier présent dans lib/binding/Release/ de chaque module requérant compilation (SQLite, LevelDB).

    Par contre, pas sûr que tu puisses utiliser autre chose que les versions ci-dessus (ça peut marcher mais je n'ai pas testé).

    Edited by Cédric Moreau
  • Justement, dans la nouvelle procédure, j'ai repris ces instructions, mais j'ai vu qu'il avait généré à la fois un node-v64-linux-x64 et un node-v72-linux-x64. Je vais essayer de comprendre pourquoi et si je peux m'en sortir. Sinon, tant pis, les Gentoo-istes vont m'en vouloir, mais la version Gentoo sera une version purement binaire récupérée de la génération automatique du CI.

  • Si j'ai bien compris, neon (qui fait partie de rust ?) compile également un certain nombre de choses. Mais neon ne va pas utiliser la même version de node que celle fournie pas NW… Je me demande si ce n'est pas de là qui viendrait le problème…

  • v72 ça correspond à un NodeJS v12.

    Tu dois avoir deux versions de Node en conflit quelque part dans le script.

  • @sveyret non je pense pas car c'est SQLite qui plante.

  • comment est-ce que je peux gérer automatiquement la compilation si je ne connais pas la version de node utilisée

    @sveyret tu ne peut pas, ne serait ce qu'a cause du code Rust. En effet, le binaire Rust (neon/native/index.node) est compilé pour une version de node spécifique. La version de node utilisée au runtime doit être strictement la même que celle utilisée lors de la compilation, ce n'est pas possible de faire autrement car Neon ne supporte pas la N-api.

    Edited by Éloïs
  • Si j'ai bien compris, neon (qui fait partie de rust ?) compile également un certain nombre de choses. Mais neon ne va pas utiliser la même version de node que celle fournie pas NW… Je me demande si ce n'est pas de là qui viendrait le problème…

    Neon sert à compiler du code Rust sous un format binaire utilisable par NodeJs, Neon compile pour la version de node sélectionnée par nvm (ou à défaut, la version de node installée sur le système).

    Edited by Éloïs
  • OK, donc, si j'ai bien compris, sur mon poste (qui est en node v12), neon va compiler un certain nombre de choses en v12, tandis que nw, en version 0.33.1 compile pour du v10. Du coup, j'ai des versions compilées en conflit. Dans l'idéal, il faudrait que je force neon a utiliser la version de nw, mais ça me semble difficile, d'autant que neon a déjà terminé sa compilation lorsque l'on ajoute nw.

    Tant pis, si je ne peux pas forcer node 10, j'utiliserai une version binaire de duniter pour Gentoo. Ça veut dire que l'objectif initial de ce Makefile n'est pas atteint, mais ce n'est pas grave, cela pourra peut-être servir plus tard.

    Merci à vous deux pour votre aide. Je vais encore faire quelques corrections, notamment pour utiliser le nw ajouté par npm, ça évitera les conflits de version, puis ça sera bon pour moi.

  • Stéphane Veyret added 3 commits

    added 3 commits

    Compare with previous version

  • @librelois c'est bon pour moi…

    Pour Gentoo, je pense que je ferai 2 versions, l'une en source imposant node 10, l'autre en binaire n'imposant rien.

  • @librelois zut, je n'aurai pas dû lancer les derniers tests, ils échouent systématiquement en timeout. Tu as moyen de fusionner quand même où tu veux que je pousse une nouvelle version ?

  • @sveyret oui je peut fusionner quand même mais je ne vais pas le faire ce soir, c'est un changement lourd de conséquence, j'aimerais tester les livrables docker et desktop de mon coté, ce qui va me demander un peu de temps.

    Ne t'inquiète pas, je ne sortirai pas la version 1.8 sans avoir mergé cettte MR ;)

    Edited by Éloïs
  • Quelques tests supplémentaires ne seraient effectivement pas de trop !

    Pour info :

    • je n'ai pas pu tester la dernière version de Docker car celle qui est disponible est toujours celle d'hier et je ne sais pas pourquoi elle ne se met pas à jour, même si je suis plutôt confiant puisque les dernières modifications ne concernent pas Docker ;
    • je n'ai pas testé les paquets Debian non plus, même si leur contenu n'a pas dû changer avec les dernières modifications.

    Merci, bonne fin de weekend…

    Edited by Stéphane Veyret
  • @sveyret le paquet deb desktop ne fonctionne pas, ça plante à l'installation du paquet (script postinst):

    Paramétrage de duniter-desktop (20200510.1706.51) ...
    chmod: impossible d'accéder à '/opt/duniter//locales': Aucun fichier ou dossier de ce type

    Je pense que tu supprime trop de truc, la version desktop a besoin du dossier locales.

  • Stéphane Veyret added 3 commits

    added 3 commits

    Compare with previous version

  • @librelois Voilà, j'ai un peu modifié la procédure. Les chmod ne sont pas nécessaires parce que le .zip conserve les droits adéquats. J'ai également modifié la fabrication du zip pour qu'il conserve les liens symboliques. Et j'ai créé un nouveau script pour démarrer duniter-desktop. Mes tests (manuels, je n'ai pas de Debian sous la main) ont réussis.

  • @sveyret le lanceur de la version desktop ne fonctionne plus du coup. Il faut que tu modifie le fichier release/extra/debian/package/DEBIAN/postinst pour créer le bon lien symbolique, faut remplacer la ligne 17 :

    ln -s $DUN_SOURCES/nw /usr/bin/duniter-desktop

    par

    ln -s $DUN_SOURCES/duniter-desktop /usr/bin/duniter-desktop
    Edited by Éloïs
  • @sveyret en fait tu avais déjà modifié le lien symbolique dans postinst, mais tu avais oublié de modifier la condition permettant de détecter que l'on est dans le cas "desktop", je viens de corriger ce détail moi-même et de merger ta branche, merci beaucoup pour cette excellente contribution :)

    ps: J'ai mergé manuellement après un rebase, c'est pour cela que gitlab n'arrive pas a détecté que la MR a été mergée, mais ton code est bien sur la branche dev.

    Edited by Éloïs
  • closed

  • Éloïs resolved all threads

    resolved all threads

  • @librelois super, merci pour tes tests (et corrections finales) !

Please register or sign in to reply
Loading