KevinB: PHP Module API und PHP API unterschiedlich

Hallo (und ein frohes neues Jahr),

ich habe unter Linux (Ubuntu 22.0.4.3 LTS, PHP 8.3) ein PHP-Modul kompiliert über

phpize
./configure
make 
make test

Bei make test wird aber dennoch angemeckert, dass die module API unterschiedlich ist:

Module compiled with module API=20190902
PHP    compiled with module API=20230831

Ich habe es auch schon versucht mit ./configure --with-php-config=/usr/bin/php-config Leider auch ohne Änderung.

Wie kann ich das Module so kompilieren, damit die API Version übereinstimmt? Oder kann ich (dreist) einfach die Module API Version ändern?

LG Kevin

  1. Sieht so aus, als wäre Dein phpize gegenüber Deinem PHP schwer veraltet oder es verwendet überaltere libs… 2019-09-02 vers. 2023-08-31

    Womöglich hilft Dir das hier:

    https://serverfault.com/questions/44668/how-to-set-the-php-api-version-for-phpize

    Edit Rolf B: URL zum Link gemacht (spitze Klammern drum)

    1. Phpize sollte aktuell sein. Hier die Ausgabe:

      Configuring for:
      PHP Api Version:         20230831
      Zend Module Api No:      20230831
      Zend Extension Api No:   420230831
      

      Ich befürchte daher eher überaltete libs. Das heißt wohl, dass ich das Modul so schnell nicht für PHP8.x erstellt bekomme. PHP8 gibt es ja erst seit fast 4 Jahren 😢

      Konkret geht es um den Zugriff auf SAP über das Modul saprfc. Nicht zu verwechseln mit sapnwrfc.

      Ich befürchte, dass es mir nicht erspart bleibt, auf das andere Modul zu wechseln und damit umfangreichen Sourcecode umzuschreiben.

      1. (Hint: Ich hab noch nie was mit phpize gemacht ... kenn mich aber mit Linux ganz gut aus…)

        Du hast offenbar mehr als eine PHP-Version installiert... und irgendwo einen Miss-Match

        $ phpize -v
        Configuring for:
        PHP Api Version:         20220829
        Zend Module Api No:      20220829
        Zend Extension Api No:   420220829
        
        $ which phpize
        /usr/bin/phpize
        $ ls -l /usr/bin/phpize
        lrwxrwxrwx 1 root root 24  9. Jun 2023  /usr/bin/phpize -> /etc/alternatives/phpize
        $ ls -l /etc/alternatives/phpize
        lrwxrwxrwx 1 root root 18  9. Jun 2023  /etc/alternatives/phpize -> /usr/bin/phpize8.2
        

        und … Wer suchet, der findet(1):

        $ ls -l /usr/lib/php
        
        drwxr-xr-x 3 root root 4096  4. Aug 15:46 20220829
        drwxr-xr-x 3 root root 4096  4. Aug 15:46 8.2
        -rwxr-xr-x 1 root root  309  9. Jun 2023  php8.2-fpm-reopenlogs
        -rwxr-xr-x 1 root root  514 13. Jul 2022  php-fpm-socket-helper
        -rw-r--r-- 1 root root 4845 13. Jul 2022  php-helper
        -rw-r--r-- 1 root root 9234 13. Jul 2022  php-maintscript-helper
        -rwxr-xr-x 1 root root 2976 13. Jul 2022  sessionclean
        

        Nicht wundern: sessionclean haben nur Debian-artige…

        Womöglich willst Du mal schauen, dass Du dasjenige phpize8.x im Ordner /usr/bin/ benutzt, welches zu dem PHP passt, für welches Du kompilieren willst...

        Wer suchet, der findet(2):

        $ cd /usr/bin
        $ for file in $(ls phpize*); do echo $file " : " $($file -v); done
        phpize  :  Configuring for: PHP Api Version: 20220829 Zend Module Api No: 20220829 Zend Extension Api No: 420220829
        phpize8.2  :  Configuring for: PHP Api Version: 20220829 Zend Module Api No: 20220829 Zend Extension Api No: 420220829
        
        

        Und dann musst Dich nur noch entscheiden. Ich würde, wenn ich mehrere PHP-Verionen installiert habe, einfach das phpize* nutzen, welches ich brauche... hab aber nur eines.

        Du nimmst also

        • /usr/phpize8.0 -v
        • /usr/phpize8.1 -v
        • /usr/phpize8.2 -v
        • /usr/phpize8.3 -v

        und schaust, welches da ist und dann passt.

        Bei mir sieht da so aus:

        * /usr/bin/php -> /etc/alternatives/php
        * /etc/alternatives/php -> /usr/bin/php.default
        * /usr/bin/php.default -> /usr/bin/php8.2
        
        1. phpize -v
          Configuring for:
          PHP Api Version:         20230831
          Zend Module Api No:      20230831
          Zend Extension Api No:   420230831
          
          which phpize
          /usr/bin/phpize
          
          ls -l /usr/bin/phpize
          lrwxrwxrwx 1 root root 24 Dec 29 08:56 /usr/bin/phpize -> /etc/alternatives/phpize
          
          ls -l /etc/alternatives/phpize
          lrwxrwxrwx 1 root root 18 Dec 29 08:56 /etc/alternatives/phpize -> /usr/bin/phpize8.3
          
          ls -l /usr/lib/php
          drwxr-xr-x 2 root root 4096 Jan  2 06:53 20160303
          drwxr-xr-x 2 root root 4096 Jan  2 06:53 20220829
          drwxr-xr-x 3 root root 4096 Jan  3 13:10 20230831
          drwxr-xr-x 2 root root 4096 Jan  2 06:53 7.1
          drwxr-xr-x 2 root root 4096 Dec 29 08:56 8.2
          drwxr-xr-x 3 root root 4096 Jan  2 16:10 8.3
          -rw-r--r-- 1 root root   13 Jul 13  2022 packaging
          -rwxr-xr-x 1 root root  514 Jul 13  2022 php-fpm-socket-helper
          -rw-r--r-- 1 root root 4845 Jul 13  2022 php-helper
          -rw-r--r-- 1 root root 9234 Jul 13  2022 php-maintscript-helper
          -rwxr-xr-x 1 root root 2976 Jul 13  2022 sessionclean
          
          cd /usr/bin
          for file in $(ls phpize*); do echo $file " : " $($file -v); done
          
          phpize  :  Configuring for: PHP Api Version: 20230831 Zend Module Api No: 20230831 Zend Extension Api No: 420230831
          phpize8.3  :  Configuring for: PHP Api Version: 20230831 Zend Module Api No: 20230831 Zend Extension Api No: 420230831
          

          Nach allem, was ich bisher gesehen habe, wird phpize für php8.3 verwendet.

          1. Und vergiss nicht, ins Handbuch Deines Projektes mit aufzunehmen, dass - und wie GENAU - Dein Modul im Falle eines PHP-Upgrades neu zu kompilieren ist.

            • Sonst macht irgendein Dödel jahrelang keine Updates des PHP mehr („weil die Webseite dann nicht mehr funktioniert“) und die Firma steht eines Montags bei heise.de unter „Frisch Gehacktes“.

            Und alle wissen, wer dann „Schuld“ hat…

            1. Es wird bereits fleissigst und haarklein dokumentiert. Aber dieses verzwickte saprfc will einfach nicht richtig kompliliert werden.

              1. Du kannst Dir auch einfach eine virtuelle Maschine hernehmen, auf der GENAU eine (1) PHP-Version exisiert (die selbe, die auf dem Server genutzt werden soll, natürlich) - und das Modul auf dieser Maschine „backen“, sodann auf den Server übertragen und dessen Nutzung konfigurieren…

                1. Ich denke, ich bin nun ein klein wenig schlauer... Ich hatte das Verzeichnis mit dem Sourcecode vom alten Server kopiert. Nachdem ich nun aber mal einen phpize --clean ausgeführt habe, sieht die Welt ganz anders aus, wenn auch definitiv nicht besser...

                  Es werden jetzt jede Menge Fehler ausgeworfen:

                  saprfc.c:134:52: error: expected ‘;’, ‘,’ or ‘)’ before ‘TSRMLS_DC’
                  134 | static void _free_resource_rfc(zend_resource *rsrc TSRMLS_DC)
                  
                  

                  usw.

                  Diese Thread-Safe Resource Manager Dinger sind aber alle wohl seit PHP5 obsolete und mit PHP8 rausgeworfen worden und können wohl einfach weggelassen werden.

                  Aber dann kommen, neben einigen Warnungen, neue Fehler:

                  saprfc.c: In function ‘zif_saprfc_server_accept’:
                  saprfc.c:1963:1: error: expected ‘;’ before ‘}’ token
                  saprfc.c:2550:1: error: expected declaration or statement at end of input
                  

                  Das fehlende Semikolon habe ich hinzugefügt und konnte danach tatsächlich ohne Fehler kompililieren, aber pbp -v zeigt nun zahlreiche Warnungen:

                  PHP Warning:  Missing arginfo for saprfc_open() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_function_discover() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_function_define() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_function_interface() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_function_debug_info() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_optional() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_import() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_export() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_table_init() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_table_append() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_table_insert() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_table_modify() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_table_remove() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_table_read() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_table_rows() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_call_and_receive() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_error() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_function_free() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_close() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_set_code_page() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_attributes() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_server_accept() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_server_import() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_server_export() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_server_dispatch() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_trfc_install() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_trfc_dispatch() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_trfc_call() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_trfc_tid() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_set_trace() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_server_register_check() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_server_register_cancel() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_function_name() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_exception() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_allow_start_program() in Unknown on line 0
                  PHP Warning:  Missing arginfo for saprfc_get_ticket() in Unknown on line 0
                  PHP 8.3.1 (cli) (built: Dec 21 2023 20:12:13) (NTS)
                  

                  Ob das Modul jetzt trotzdem funktioniert, trotz der Warnungen, muss ich morgen dann mal testen... Ich mache mir aber keine großen Hoffnungen.

                  1. Ich mache mir aber keine großen Hoffnungen.

                    Ist es das hier?

                    https://saprfc.sourceforge.net/

                    Dort steht:

                    „SAPRFC is a extension module for PHP 4 and PHP 5.“

                    und kein Wort von einem Nachfolger... Laut sourceforge ist die „neueste“ Version vom 14.8.2009. Also fast 15 Jahre alt.

                    Ich kann dessen Verwendung allenfalls nur dann empfehlen, wenn Du das Modul selbst weiter entwickeln kannst, willst und sollst. Ansonsten ist das Zeug „KotEoL“ („Krass over the End of Live“) und Du musst doch die Bibliothek wechseln.

                    Nachdem ich nun aber mal einen phpize --clean ausgeführt habe, sieht die Welt ganz anders aus

                    Ja. Das wird in vielen Anleitungen vergessen: Ist (wie in Deinem Fall) .configure oder gar das darauf folgende make bereits ausgeführt worden, dann bedarf es regelmäßitg eines make clean (oder hier halt des phpize --clean) vor dem neuen .configure. Es sei denn, wirklich alles ist seit dem beim alten geblieben. Dann brauchts aber das neue phpize und .configure nicht…

                    1. Guten Morgen,

                      ja, die ursprüngliche Quelle bzw. der ursprüngliche Entwickler hat wohl nicht mehr weiterentwickelt, aber da der Sourcecode quelloffen ist, gab es immer wieder welche, die eine neue Version kompiliert hatten. Die letzte Version, die ich gefunden habe, ist mindestens vom 07.12.2018, also "immerhin nur" 6 Jahre her. Ist aber auch für Computer prähistorisch. Sollte das Modul jetzt klappen, habe ich möglicherweise Zeit bis PHP9 und muss entweder bis dahin mehr C++ können oder doch auf sapnwrfc umstellen, das immerhin auch PHP8 unterstützen soll.

                      Vielleicht schaue ich mir auch mal das "Missing arginfo" an. Möglicherweise ist das auch schnell korrigiert, auch ohne selbst C++ zu können.

                      LG Kevin

                      1. Leider stellt sich heraus, dass diese Warnung "Missing arginfo" leider nicht ignoriert werden kann. Aus den Release Notes von PHP 8:

                        All internal functions and methods are now required to specify arginfo 
                        information, otherwise warnings will be thrown on startup.
                        

                        Das bedeutet wohl, dass der Source code umgeschrieben werden muss, damit die Aufruf-Parameter deklariert sind.

                        Im Soruce code steht:

                        zend_function_entry saprfc_functions[] = {
                            PHP_FE(saprfc_open,    NULL)
                            PHP_FE(saprfc_function_discover,    NULL)
                        etc.
                        

                        Das PHP_FE sollte wohl auch durch ZEND_FE ersetzt werden, aber ich muss auch noch herausfinden, wieviele Parameter denn die Funktion erwartet 😩

                        Und ob es ausreicht, nur zu deklarieren, dass es Parameter gibt...

                        ZEND_BEGIN_ARG_INFO_EX(arginfo_saprfc_open, 0, 0, 3) ZEND_ARG_INFO(0, param1) ZEND_ARG_INFO(0, param2) ZEND_ARG_INFO(0, param3) ZEND_END_ARG_INFO()

                        ... oder ob ich auch angeben muss, welcher Typ erwartet wird...

                        1. Ich habe die ganze Deklarationen mal eingebaut, also für jede Funktion sowas wie:

                          ZEND_BEGIN_ARG_INFO_EX(arginfo_saprfc_open, 0, 0, 1)
                              ZEND_ARG_INFO(0, param1)
                          ZEND_END_ARG_INFO()
                          

                          Für mehrere Parameter z.B.

                          ZEND_BEGIN_ARG_INFO_EX(arginfo_saprfc_optional, 0, 0, 3)
                              ZEND_ARG_INFO(0, param1)
                              ZEND_ARG_INFO(0, param2)
                              ZEND_ARG_INFO(0, param3)
                          ZEND_END_ARG_INFO()
                          

                          Und ich hab die Funktionsdefinition dann entsprechend angepasst von bspw.

                          PHP_FE(saprfc_open,    NULL)
                          

                          auf

                          ZEND_FE(saprfc_open,    arginfo_saprfc_open)
                          

                          Nachdem Kompilieren tauchen jetzt keine Warnungen mehr auf...

                          Aber es funktioniert leider noch immer nicht:

                          Fatal error: Uncaught TypeError: saprfc_table_read(): 
                          Argument #3 ($param3) must be of type unknown, 
                          int given in /srv/www/htdocs/saptest.php:31
                          

                          Nachdem ich nicht verstehe, warum beim dritten Parameter "unknown" erwartet wird, denn

                          PHP_FUNCTION(saprfc_table_read)
                          {
                              zval *fce;
                              zend_string *name;
                              zend_long index;
                          

                          "zend_long" ist doch int und bei der Prüfung

                              if (zend_parse_parameters(ZEND_NUM_ARGS(), "rSL", &fce, &name, &index) == FAILURE) {
                                  return;
                              }
                          

                          wird der dritte Parameter dann plötzlich als "Unknown" erwartet???

                          Nachdem ich den dritten Parameter bei der Prüfung auf optional gesetzt habe ("rS|l"), funktioniert jetzt zum ersten Mal eine Testfunktion.

                          Jetzt noch alle anderen Funktionen testen (zumindest die, die ich brauche) und dann endlich fertig !

                          1. Hallo KevinB,

                            vielen Dank, dass Du uns an deinem steinigen Weg teilhaben lässt 😉

                            Rolf

                            --
                            sumpsi - posui - obstruxi
          2. Ach so.

            Ich habe es auch schon versucht mit ./configure --with-php-config=/usr/bin/php-config Leider auch ohne Änderung.

            Überprüfe ergo auch

            $ ls -l /etc/alternatives/php-config
            

            (Das zeigt die Einstellung des Systems)

            bzw.

            $ ls -l /usr/bin/php-config*
            

            (Das zeigt, was Du angeben kannst. Diese Skripte setzen einen Haufen Pfade...)

            In Deinem Fall wäre das wohl:

            ./configure --with-php-config=/usr/bin/php-config8.3
            

            also

            for vers in "8.2" "8.3"; do
               phpize${vers};
               ./configure --with-php-config=/usr/bin/php-config${vers};
               make;
               make test;
            done