bgrabitmap / lazpaint

🎨 Cross-platform image editor with raster and vector layers similar to Paint.Net written in Lazarus (Free Pascal)
https://lazpaint.github.io/
GNU General Public License v3.0
401 stars 55 forks source link

Release 7.2.2 does not run in Debian 11 64 bit. #531

Open fredvs opened 2 years ago

fredvs commented 2 years ago

Hello.

I try to run, on last Debian 11, LazPaint from _lazpaint7.2.2_linux64_noinstall.tar but get this error.

> /home/fred/Downloads/lazpaint/lazpaint

/home/fred/Downloads/lazpaint/lazpaint: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /home/fred /Downloads/lazpaint/lazpaint)

This means that you have compiled + linked with a version of libc.so.6 newer than the one of Debian 11 ( GLIBC 2.31for Debian 11) ( Note that libc.so.6 is also a executable!)

fred@fred-80m0 ~> /lib/x86_64-linux-gnu/libc.so.6

GNU C Library (Debian GLIBC 2.31-13+deb11u3) stable release version 2.31. Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 10.2.1 20210110.

My humble advice is, for release, to be compatible with a maximum of distros, to compile it with a older version of libc.so.6, maybe from the last Debian LTS: https://wiki.debian.org/LTS/Extended It is Debian 10 “Buster”

circular17 commented 2 years ago

I think that it is not possible to have multiple versions in one binary.

So in this case, that would mean making a version for this older Debian by compiling it on an older Debian.

fredvs commented 2 years ago

I will try to explain better.

When you compile Lazpaint, it will link with libc.so.6 installed on your system. I dont know what distro you did use for the release but this distro has one of the last (instable) version of libc.so.6.

So a distro with a libc.so.6 older than the one linked at compilation will not be able to run LazPaint (is the case for last Debian 11 that uses last stable version of libc.so.6.)

The good news is that libc.so.6 is backward compatible, a new libc.so.6 accept a old linked libc.so.6 ( but not reverse).

So the easy solution:

circular17 commented 2 years ago

Oh ok there are various versions of libc.so.6. I suppose that's doable.

fredvs commented 2 years ago

Oh ok there are various versions of libc.so.6.

Yes, that is the problem (and also that fpc still needs to link with libc but this is a other hot story)

fredvs commented 2 years ago

Just by incurable curiosity.

What do you get doing this in console?:

~> /lib/x86_64-linux-gnu/libc.so.6

Is it mentioned "stable release" like in Debian 11?

GNU C Library (Debian GLIBC 2.31-13+deb11u3) stable release version 2.31.

circular17 commented 2 years ago

It tells me: "Permission non accordée"

fredvs commented 2 years ago

Perfect.

And with that: ~>sudo /lib/x86_64-linux-gnu/libc.so.6

( Strange that you need sudo )

fredvs commented 2 years ago

Maybe your libc.so.6 is in other place...

To find it, in console, just do -> find /lib/ -name libc.so.6

If nothing found, do this: -> find /usr/ -name libc.so.6

circular17 commented 2 years ago

With sudo it says it doesn't recognize the command.

The file is there, it shows with ls.

fredvs commented 2 years ago

Ha it was not a joke... Very strange. What distro are you using? Or maybe your libc.so.6 was not set as executable. To do it in console:

sudo chmod +x /path/to/your/libc.so.6

You may also get the version of libc.so.6 with lld (but less infos).

ldd --version

circular17 commented 2 years ago

Setting +x did the trick. Here is what it says: GNU C Library (Ubuntu GLIBC 2.35-0ubuntu3.1) stable release version 2.35.

fredvs commented 2 years ago

Hum, Debian package version 2.35 is set a "experimental".

Anyway, that version is higher than 2.31 and if you link with that version the executable will not run on Debian 11. I have to check what is the libc version used in last Ubuntu.

I know that ArchLinux always uses the last experimental version of libc in their release. Imho, ArchLinux is ok for developers of Linux kernel but it is not a stable OS.

My 0.01 cent of course.

fredvs commented 2 years ago

packages.debian.org/search?keywords=libc6 libc6

fredvs commented 2 years ago

GNU C Library (Ubuntu GLIBC 2.35-0ubuntu3.1) stable release version 2.35.

Ha sorry, I did not note that it gives the distro too. Well, ok, Ubuntu uses experimental libc.so, good to know. The thing is that fpc needs only very few exported methods form libc.so.6, but the law is the law, if you use even only one method, you must link all the library.

fredvs commented 2 years ago

By the way, please dont try to install a other version of libc.so.6 on your system. I did try this already ( and have read all the "do it on your own risk" in the fora ) , and I loose everything, no boot anymore. It is mainly because the kernel needs his proper libc.so.6 version and all others dont work.

fredvs commented 2 years ago

Allez, le dernier. The very good thing is that you have a distro using last libc.so.6 version, so perfect to test a binary linked with a older libc.so.6. Even more yo may test until what older version of libc.so.6 it is still working and so cover much more distro, even older on old machine.

OK, I stop.

fredvs commented 1 year ago

Yeeep! https://forum.lazarus.freepascal.org/index.php/topic,58888.msg483626.html#msg483626

circular17 commented 1 year ago

I admit it is beyond my understanding

fredvs commented 1 year ago

Bon, je resume. Lors du linkage, juste apres la compilation, toutes les methodes de la libraire libc sont assignees avec le symbole de la libraire presente sur le syteme. ( C'est comme ca que fpc fonctionne )

Donc si tu compiles LazPaint sur un systeme qui a la derniere version GCLIB_2.34., ce binary ne fonctionnera pas sur un syteme avec une version de clib precedente.

Et le truc magic de Robert est de, au linkage, a la place d'assigner les memes symboles que la libraire presente sur le systeme qui compile, de les assigner "unsigned". Dans ce cas le binary lors de l'execution va chercher les methodes dans libc sans se soucier des symboles, il va prendre le symbole "par default" qui est le dernier installe dans sa libc.

Donc, ok, c'est complique mais c'est une bonne nouvelle/trouvaille.

circular17 commented 1 year ago

Ok, donc en utilisant cette version magique sur le système, on obtient un binaire qui fonctionne sur toutes les versions. Mais est-ce que cette version bidon fonctionne vraiment, en fait ? Les programmes fonctionnent toujours ?

fredvs commented 1 year ago

J ai teste sur une ancienne version Debian 5 de 2009 et cela fonctionne. En fait tout fonctionne parfaitement. J'espere que les devs de fpc vont enfin piger le principe. Pas evident a comprendre le mechanisme des "versioned/unversioned symbols" mais, si bien compris, c'est genial car on peut avoir une compatibilite parfaite pour tous OS, meme les plus anciens.

En fait c'est pas grave si les devs de fpc ne veulent rien changer (ils sont terrorises par le linkeur) car la solution du "fake libdl.so" est geniale et facile.

PS: Sympas vos manifs un peu frivolles des derniers jours/nuits... ;-)

fredvs commented 1 year ago

Back to EN. Of course, if you are interested by the "universal" Linux binary of LazPaint, I will prepare all the tools (fake libdl.so + instructions) with pleasure.

circular17 commented 1 year ago

J'aime bien l'idée que le programme fonctionne avec plusieurs version des librairies. C'est l'approche que j'ai choisie d'ailleurs pour les librairies graphiques (webp, avif).

Je suppose que la position Debian est que les applications sont compilées au niveau paquet pour la dernière version du système. Cela dit, pour les binaires téléchargés sur le site de LazPaint, ce serait bien d'avoir un max de compatibilité.

Cela dit, je me demande les cas d'utilisation, dans le sens où en principe, les gens mettent à jour leur système Linux.

PS: je n'ai pas trop suivi les fêtes nocturnes récentes, trop occupée que j'étais à penser à mes vacances, enfin, et gérer mon emménagement.

So what would be the target actually? A Debian package for old Debian distros?

fredvs commented 1 year ago

Je suppose que la position Debian est que les applications sont compilées au niveau paquet pour la dernière version du système.

C'est plus compliqué, je pense. Je ne crois pas que Debian se soucie comment le linkage a ete fait et avec quelle table de symbole. La librairie qui pose probleme est libc.so. Et les developpeurs de libc.so, pour qui la compatibilite est importante, on introduit le concept "signature de methodes". Dans chaque librairie libc.so les nouvelles comme les anciennes il y a des "tables de signatures" qui permettent d'assurer la compatibilite.

Par example, la plus ancienne table de signatures qui fonctionne sur les libc.so actuelles est "@GLIBC2.2.5" et est incluse dans chaque libc.so.

Recemment, les dev de glibc on introduit une nouvelle table de signature: GLIBC_2.34. Avec fpc, au linkage chaque methode est signee avec la derniere table de signatures disponible de libc.so.

Note que la version de libc.so ne change pas en fonction des dates, elle reste libc.so.6 meme quand une table de symboles a ete ajoutee.

Mais il existe d' autre methode de linkage, par example celle qui utilise "unsigned" symbols. Dans ce cas lors de l'execution, comme les symboles ne sont pas signes, libc.so va utiliser la derniere table de symboles qu'elle possede.

Une autre methode de linkage qui fonctionne bien est d'assigner l'ancienne table "GLIBC2.2.5". Dans ce cas le binary est signe mais avec la plus ancienne table (que la librairie, meme nouvelle, accepte).

FPC n utilise pas les subtilites des differentes tables donc c'est etrange de signer le binary. Heureusement le passe-passe de Robert arrange tout.

For the target, sure all the __linux_noinstall assets_ and for the Debian asset, I should do it too so you could use the debian package also for older distro.

Bon emménagement.

Fre;D

circular17 commented 1 year ago

Je suis en train de me dire que ce serait possible d'inclure ce hack dans le makefile. En ayant le source libdl.c et en le compilant avec gcc avant de compiler avec fpc ou lazbuild.

Merci pour les explications. Si je comprends bien, il y a en principe plusieurs versions possibles proposées par une librarie mais fpc ne gère pas cela et au lieu de cela associe systématiquement avec la dernière version.

fredvs commented 1 year ago

En ayant le source libdl.c et en le compilant avec gcc avant de compiler avec fpc ou lazbuild.

C'est le nouveau script-option inclus dans msegui, compiler libdl.c juste avant de compiler le fpc programme et l' effacer apres linkage. Meme pas besoin de copier le binary de quelque part!

et au lieu de cela associe systématiquement avec la dernière version.

Du systeme qui compile le binary ( la solution de Rob associe avec la derniere version du systeme qui acceuille le binary )

fredvs commented 1 year ago

Huh, a propos de ton message: "il n'est pas raisonnable que des développeurs indépendants construisent pour différentes versions"

Donc tu trouves qu'il n'est pas raisonable d'avoir un exe qui fonctionne sur plusieurs systemes? ( Ou peut etre mon google translate veut dire autre chose ) ​

circular17 commented 1 year ago

La traduction est ambiguë je suppose. Build veut dire compiler, pas développer.

fredvs commented 1 year ago

Ha ok. Derniere chose. A propos de la methode "catholique" de creer un binary en utilisant une machine virtuelle avec une ancienne distro. Ok, ca marche mais, comme tu l'as appris avec les precedents posts, en compilant avec une ancienne machine, au linkage c'est la derniere table de signature-symboles-du-systeme-qui-compile qui sera assignee. Donc si tu utilises le binary sur une distro plus recente, la table qui sera utilisee ne sera pas la derniere du systeme d'acceuil (qui possede de nouvelles tables qui n'existaient pas dans la vielle version). En soi ce n'est pas grave car libc.so peut dealer avec d'ancienne version. (mais ce n'est pas parfait)

Mais si tu utilises le truc de la fake libdl.so, meme si tu compiles sur une ancienne distro, la table assignee est la derniere du systeme d'acceuil (pas de compilation) donc si tu utilises le binary dans une version plus recente, c'est la derniere table qui sera utilisee.

Bon, je pense avoir tout dit. (et promis je n'irai plus mettre le feu au forum Lazarus) (Ce combat a ete tres rude et tres fastidieux, je suis heureux que cela s arrete).

Fre;D

circular17 commented 1 year ago

Je comprends et alors je me dis pourquoi pas faire référence à une ancienne version de la table. En quoi ce n'est pas parfait ? D'une certaine façon cela garantie que les fonctions ont bien les bonnes signatures. Est-ce qu'il y a des choses qui ne fonctionnent pas alors ?

Je comprends que tu aies été taquin sur le slogan. Effectivement, la discussion semble s'être un peu calmée, ce qui est toujours préférable à mon avis. Cela dit, l'inflexibilité parfois de l'équipe de FPC me donne envie de faire un fork.

fredvs commented 1 year ago

Je comprends et alors je me dis pourquoi pas faire référence à une ancienne version de la table. En quoi ce n'est pas parfait ?

C'est ce que Robert a essaye de faire passer comme message aux FPC dev (avant de trouver la solution libdl.so ). ( En fait Robert et moi avons bosse par mail, avec de nombreuses nuits blanches ( Rob habite en New Zeeland) ) L'idee etait de continuer a utiliser une version signee mais a la place de la derniere du systeme qui compile, utiliser la plus ancienne qui est compatible: "GLIBC_2.2.5". Suite au refus catagorique des fpc dev de changer un coma de code, apres plein de tatonnements, la solution miracle libdl.so est apparue. A mon avis cette solution est plus "parfaite" que la solution "la plus ancienne table compatible" car elle utilise la derniere table du systeme d'acceuil. Mais, ok, "parfaite" n'est pas le mot correct, meilleur serait "aussi parfaite ". Note que la solution "GLIBC_2.2.5" ne demande qu'une ligne de code a changer (mais je sais c'est deja trop).

Je comprends que les devs soient inflexibles mais je ne supporte pas qu'ils manquent de respect a qui que ce soit.

fredvs commented 1 year ago

Et a propos de la solution "installe une ancienne disto, avec tout le bazar (fpc, dependances, ...) et compile y ton programme" est une solution "Jurassic IT".

Je te souhaite plein de bonheur dans ta nouvelle demeure.

Fre;D

circular17 commented 1 year ago

Effectivement, je trouve aussi que c'est important de respecter les autres personnes, même si on est en désaccord.

Une ligne de code peut être changée et hop cela ferait référence à l'ancienne version de libc ?

circular17 commented 1 year ago

Effectivement, installer une ancienne distro n'est pas pratique du tout.

Merci pour tes souhaits pour ma nouvelle demeure ❤️

fredvs commented 1 year ago

Une ligne de code peut être changée et hop cela ferait référence à l'ancienne version de libc ?

Oui. https://forum.lazarus.freepascal.org/index.php/topic,58888.msg483544.html#msg483544

circular17 commented 1 year ago

Je ne comprends pas la réticence de changer cette ligne. Éventuellement, cela peut être avec une directive de compilation / une option de compilation. Comme cela, par défaut ça prendrait bien la dernière version mais que l'on puisse avoir cette option quand on compile un paquet qu'on va proposer au téléchargement.

fredvs commented 1 year ago

La solution optimale (proposee et bien sur refusee) serait d'ajouter un parametre/option pour fpc. Et donner la possibilite au user de choisir la table de systeme a utiliser.

"-use_last_table_of_compiler_system" (default), "-use_oldest_table_of_compiler_system", "-use_last_table_of_host_system", "-use_custom_table={thetable} ".

Mais ca, bien sur, ne sera jamais accepte ( et j 'avoue que cela demanderait beaucoup de travail ).

circular17 commented 1 year ago

On peut faire plus simple, comme une option "-libc225" voire simplement une directive de compilation -dLIBC225.

J'arrive un peu après, ok je note que vous avez proposé quelque chose comme cela. Cela me parait raisonnable.

Juste ajouter un $IFDEF LIBC225 me parait pas beaucoup d'effort.

fredvs commented 1 year ago

Huh, pour MSEgui, il y a l'option: -dglibc225 ((Texto la meme!) (Pas encore commitee, je veux d'abord tout tester profondement)

ideu_glibc225

Et biensur la solution "libdl.so".

combefore

comafter

L'avantage avec msegui, c'est que je peux changer le code sans que on me hurle dessus. ;-)

circular17 commented 1 year ago

Les grands esprits se rencontrent

Enfin, le temps que je comprenne le sujet 😄

Oui c'est mieux quand on se fait pas gronder !

fredvs commented 1 year ago

J'ai fait les modifs dans fpc-ootb mais apres la trouvaille libdl.so j'hesite a commiter.

En fait pour msegui l'option d'assigner la plus ancienne table GLIBC_2.5.5 n'est pas entierement OK. En effet, msegui utilise la methode pipe2() qui est apparue a la version GLIBC_2.9. J'ai donc assigne, pour pipe2(), GLIBC_2.9. (oui, je sais, c'est un peu de la triche)

Pour fpc, ce n est pas un probleme car il n'utilse pas pipe2(). Donc, amha (imho), pour msegui, la solution fake libdl.so, qui utilise la derniere version du systeme hote, est la panacee (et donc il faut rien changer au code fpc, fake libdl.so s'occupe de tout).

circular17 commented 1 year ago

Pourquoi pas utiliser GLIBC_2.9.

En fait, la librairie sans version, cela fonctionne si on suppose que les signatures des fonctions ne seront pas changées. À priori c'est peu probable, mais bon, dans la théorie je trouve préférable de spécifier la version minimum nécessaire.

fredvs commented 1 year ago

Pourquoi pas utiliser GLIBC_2.9.

Oui c'est une option pour msegui d'assigner GLIBC_2.9 pout toutes les methodes. (et pas comme je l'ai fait, individuellement pour chaque methode utilisees) Mais pour les programmes qui n'utilisent pas les particuarites de 2.9., c'est un peu triste de les boquer a 2.9 alors qu'ils pouraient utiliser des distros plus anciennes.

A propos des differentes signatures pour chaque methode. A ce que j'ai compris, pour une meme methode, peu importe les versions utilisees, elle aura toujours les memes parametres (heureusement d'ailleurs). Mais il se peut que certaines nouvelles versions permettent d'utiliser des parametres "etendus" (difficile a expliquer) par example un parametre dans un ancienne version permet d'assigner 1 a 10, et la suivante 1 a 15,...

FPC n'est pas concerne car il utilise les methodes "de base" sans utiliser les particularites ajoutees aux nouvelles versions.

En fait, la librairie sans version, cela fonctionne si on suppose que les signatures des fonctions ne seront pas changées.

Si la librairie a ete linkee sans signature dans l'executable, alors les signatures des fonctions qui seront chargees seront les dernieres de la librairie hote.

Une table de signature sera toujours chargee a l'execution (meme si au linkage on demande de ne pas signer les symboles).

Je sais, c'est hyper complique et y a peu de doc, j'ai donc surement mal compris ta question.

fredvs commented 1 year ago

Du forum Lazarus:

The problem is that if you compile a C program it takes the header from the system to define the stat

Mwouais si c'est le cas lors d'un compilation-link fpc, ils doivent revoir tout leur code car stat est defini "hard-coded" et n'a pas change depuis toujours.

Aaaargh, je m'etais promis de ne plus consulter Lazarus forum.

Sorry for the noise.

fredvs commented 1 year ago

I presume this is handled by the legacy version (glibc 2.2.5) of the functions.

Mais bien sur, glibc a ete concu pour ca.

OK, ok, je sors.

fredvs commented 1 year ago

Allez, un dernier qui resume le probleme. Le trouble fete est "external", voici 3 cas:

1) function readdir(__dirp:PDIR):Pdirent64;cdecl;external clib name 'readdir';
C'est ce qu'utilise fpc dans tout ses codes, le "name" pur. Cela signifie que, pour readdir(), la derniere table du systeme compilateur sera assignee. La confusion est que, utiliser le "name" pur, n'est pas assigner "unsigned" mais la derniere table du systeme compilateur.

2) function readdir(__dirp:PDIR):Pdirent64;cdecl;external clib name 'readdir@GLIBC_2.2.5'; Dans ce cas on assigne la table GLIBC_2.2.5, peu importe la version du systeme compilateur. Ce cas demande quelques modifications dans le source fpc.

3) Utilisation de la fake libdl.so Ici, lors du linkage, on force le linkeur d'oublier les tables assignees par le code du programme et a la place d'utiliser la derniere version du systeme hote (unsigned).

Je suppose que ton coeur balance pour l'option 2) (comme Robert et moi au depart) mais cela demande des modifs au code fpc qui prendront des siecles avant d'etre publiees.

Et apres tous les profonds tests ok qu'on a fait , l'option 3) me semble ideale, tout le monde est content, pas touche a fpc et on a ce qu'on veut. [EDIT] On a essaye d'assigner GLIBC_2.2.5 a la fake libdl.so mais sans succes jusqu'a present, le truc ne marche que si la fake librairie est "unsigned" (qui moi me convient).

circular17 commented 1 year ago

Mais pour les programmes qui n'utilisent pas les particuarites de 2.9., c'est un peu triste de les boquer a 2.9 alors qu'ils pouraient utiliser des distros plus anciennes.

On peut faire un compromis comme cela : on suppose que les gens mettent à jour un peu leurs distributions de temps en temps, simplement on permet une certaine rétrocompatibilité.

A ce que j'ai compris, pour une meme methode, peu importe les versions utilisees, elle aura toujours les memes parametres (heureusement d'ailleurs). Mais il se peut que certaines nouvelles versions permettent d'utiliser des parametres "etendus" (difficile a expliquer) par example un parametre dans un ancienne version permet d'assigner 1 a 10, et la suivante 1 a 15,...

Ah ok je pense que je comprends. Cela me fait penser aux structures qui contiennent une indication de leur taille, comme cela on sait quels paramètres peuvent être définis, ceux qui dépassent prenant la valeur par défaut.

Si c'est le cas, alors on peut se baser juste sur le nom et effectivement, ne pas versioner est en fait ok.

Dans le cas de pipe2, cela veut dire que si la version de libc est trop ancienne, la fonction ne sera pas disponible. Cela est vérifiable à l'exécution je présume.

Mwouais si c'est le cas lors d'un compilation-link fpc, ils doivent revoir tout leur code car stat est defini "hard-coded" et n'a pas change depuis toujours.

Si cela n'a pas changé, je vois pas ce qu'ils auraient à revoir.

Je suppose que ton coeur balance pour l'option 2) (comme Robert et moi au depart) mais cela demande des modifs au code fpc qui prendront des siecles avant d'etre publiees.

Oui cela parait logique, mais comme tu m'a expliqué le principe de compatibilité des fonctions elles-mêmes, je suppose que l'option 3 est aussi ok.

fredvs commented 1 year ago

Dans le cas de pipe2, cela veut dire que si la version de libc est trop ancienne, la fonction ne sera pas disponible. Cela est vérifiable à l'exécution je présume.

Oui, c'est la limite du systeme "symbols signes", si une seule methode demande une version posterieure au systeme, l'application ne pourra pas fonctionner et il y aura le meme message d'erreur que mentionne le premier post.

Ceci dit, GLIBC_2.9 date de 2008-11-13, c'est pas mal ( mais moins bien que GLIBC_2.2.5: 2002-01-20 ).

Ca c'est pour libc.so, il y a evidemment aussi la question des versions des widgetsets ( mais c'est une autre histoire ) MSEgui est OK partir de 2008-11-13, sinon il y a le challenge d'imiter pipe2() en utilisant pipe() .

fredvs commented 1 year ago

MSEgui est OK partir de 2008-11-13, sinon il y a le challenge d'imiter pipe2() en utilisant pipe() .

Challenge remporté !

{$ifdef glibc225}
   pipe(connectpipe);
   fcntl(connectpipe.ReadDes, F_SETFL, o_cloexec or o_nonblock); 
   fcntl(connectpipe.WriteDes, F_SETFL, o_cloexec or o_nonblock); 
{$else}
   pipe2(connectpipe,o_cloexec or o_nonblock);
{$endif}

Donc, petite rectification, MSEgui est OK a partir de 2002-01-20 pour Linux 64 bit. Pour la librairie graphique X11, pas de problemes (et pas de tables de signatures), la version X11R6 (toujours utilisee) date de 1994-05-16. Et donc pour Linux 32 bit, MSEgui est OK a partir de 1994-05-16.

circular17 commented 1 year ago

Félicitations ! Plus de 20 ans de compatibilité !