frazap has asked for the wisdom of the Perl Monks concerning the following question:

Background:

Some years ago I succeed in having Gtk2 script packed with PAR after including dll with --link option.

These were Glib.dll, Gtk2.dll, Cairo.dll, Pango.dll.

The trick that was working then was to include the above dll and to rename the the Glib, Gtk2, Pango folders in lib/auto to hide them from the search path.

The dll were then taken from the par archive at shlib\MSWin32-x86-multi-thread-64int\ folder and the exe works.

More details here https://www.mail-archive.com/par@perl.org/msg05033.html

The problem:

I did a new perl install (strawberry perl v. 5.24) when my OS was changed. I compile the Gtk2 from source.

I can't find these dll (Glib.dll, Gtk2.dll) in my new perl install, I have instead Glib.xs.dll, Gtk2.xs.dll etc. I did find the first group in my tmp folders under C:/Users... where par archives are extracted: I have copied these dll in c:/docs/perl_dll

I tried to pack the following script
use strict; use warnings; use Gtk2 '-init'; use Glib qw/TRUE FALSE/; my $window = Gtk2::Window->new; $window->signal_connect (destroy => sub { Gtk2->main_quit; }); $window->show_all(); Gtk2->main;

Using Shawn Laffan's pp_autolink.pl https://github.com/shawnlaffan/perl-pp-autolink or the -x option of pp without any dll included make an exe that crash

Can't load 'C:\Users\rappazf\AppData\Local\Temp\par-...\778ce824.xs.dl +l' for module Pango: load_file:The specified module could not be found at + C:/strawberry/perl/lib/DynaLoader.pm line 193.
Running
objdump -x 778ce824.xs.dll | grep "DLL Name" gives DLL Name: libcairo-2.dll DLL Name: libglib-2.0-0.dll DLL Name: libgobject-2.0-0.dll DLL Name: libpango-1.0-0.dll DLL Name: libpangocairo-1.0-0.dll DLL Name: msvcrt.dll DLL Name: Cairo.xs.dll DLL Name: Glib.xs.dll DLL Name: KERNEL32.dll DLL Name: perl524.dll
Adding the xs.dll with --link did change the errors, but the inclusion of the 4 xs.dll does not give a working exe.

With these dll on the option for pp

-l 'C:/strawberry/perl/site/lib/auto/Cairo/Cairo.xs.dll' -l 'C:/strawberry/perl/site/lib/auto/Glib/Glib.xs.dll' -l 'C:/strawberry/perl/site/lib/auto/Gtk2/Gtk2.xs.dll' -l 'C:/strawberry/perl/site/lib/auto/Pango/Pango.xs.dll' -l 'C:\docs\perl_dll\Pango.dll' -l 'C:\docs\perl_dll\Glib.dll' -l 'C:\docs\perl_dll\Gtk2.dll' -l 'C:\docs\perl_dll\Cairo.dll'
Without hidding the lib/auto/Glib .../Gtk2 .../Pango I get the error
GLib-GObject-CRITICAL **: g_boxed_type_register_static: assertion `g_t +ype_from_name (name) == 0' failed at C:/strawberry/perl/lib/DynaLoade +r.pm line 210. cannot register alias Gtk2::Pango::Attribute for the unregistered type + (null) at C:/strawberry/perl/lib/DynaLoader.pm line 210. Compilation failed in require at script/simple.pl line 12. BEGIN failed--compilation aborted at script/simple.pl line 12.
Renaming these folder and adding the dll above still gives the error below
Can't locate loadable object for module Glib in @INC (@INC contains: C +:\Users\rappazf\AppData\Local\Temp\par-72617070617a66\cache-6d3232558 +24cd4b77983f4c61ece5aa2d701ac21\inc\lib C:\Users\rappazf\AppData\Loca +l\Temp\par-72617070617a66\cache-6d323255824cd4b77983f4c61ece5aa2d701a +c21\inc CODE(0x31e7e8c) CODE(0x31e8084)) at C:/strawberry/perl/site/l +ib/PAR/Heavy.pm line 99. Compilation failed in require at Gtk2.pm line 30. That's were 'use Gib +;' is called in Gtk2.pm and adding the Glib.dll, Gtk2.dll from the pe +rl_dll folder does not change this.

Can someone explains the difference between Glib.dll and Glib.xs.dll ? How come the first group is missing from my perl tree and my scripts are still working ?

How can I packed this script ?

François

Replies are listed 'Best First'.
Re: On the road again with Gtk2 and PAR::Packer
by syphilis (Archbishop) on Feb 13, 2019 at 10:48 UTC
    Can someone explains the difference between Glib.dll and Glib.xs.dll ?

    The only difference is the name.
    On my own builds of perl (on Windows) the dll would be named Glib.dll, but on Strawberry the same file gets named Glib.xs.dll.
    On my builds of Windows perls:
    C:\>perl -V:dlext dlext='dll';
    On recent builds of Strawberry Perl:
    C:\>perl -V:dlext dlext='xs.dll';
    That's about all there is to it.
    That Config setting is detected by EU::MM and influences the Makefile generated by the 'perl Makefile.PL' step.

    I'm not sure how this will impact upon PAR::Packer, but this part of what you provided looks correct to me:
    -l 'C:/strawberry/perl/site/lib/auto/Cairo/Cairo.xs.dll' -l 'C:/strawberry/perl/site/lib/auto/Glib/Glib.xs.dll' -l 'C:/strawberry/perl/site/lib/auto/Gtk2/Gtk2.xs.dll' -l 'C:/strawberry/perl/site/lib/auto/Pango/Pango.xs.dll'
    whereas this part looks incorrect to me:
    -l 'C:\docs\perl_dll\Pango.dll' -l 'C:\docs\perl_dll\Glib.dll' -l 'C:\docs\perl_dll\Gtk2.dll' -l 'C:\docs\perl_dll\Cairo.dll'
    IIRC, Strawberry chose this option to avoid name clashes.
    Say you are building an extension named Some::Module that accesses a C library named "module" via its dll named "module.dll".
    When you build Some::Module, you create a dll named "Module.dll".
    Both "Module.dll" and "module.dll" are different files and both are needed by Some::Module - but Windows, being case-insensitive, is unable to distinguish between them and you won't even be able to get Some::Module to load.
    So ... Strawberry names the perl dll "Module.xs.dll", and windows has no problems distinguishing between the 2 dlls that are needed.

    Cheers,
    Rob

      Edit: Sorry, the files are differently named here, so the first para does not entirely apply here (although the xs.dll files should not need to be packed). My guess is the path.

      ---

      If I understand correctly, the two Gtk2.dll, Glib.dll etc files in this case serve different purposes. One is the actual Gtk2 dll, the other is the xs file. PAR::Packer will pack the xs versions automatically, so they should need to be specified using --link/-l. The others do need to be packed.

      I wonder if the issue is some other Gtk2.dll is earlier in the path?

      If one uses the PPMs provided by Syphilis then Gtk2.dll is called s1sgtk-win32-2.0-0.dll so there is considerably less chance of ambiguity in the path. That file also lives next to the Gtk2.dll file so is found by the PAR search. (This differs from the other related dlls from that source, which are in the ...\perl\bin folder, which is maybe relevant).

        If I understand correctly, the two Gtk2.dll, Glib.dll etc files in this case serve different purposes. One is the actual Gtk2 dll, the other is the xs file.

        The names of the actual Gtk2 dlls should all begin with "lib" - eg "libglib-2.0-0.dll", "libcairo-2.dll", "libpango-1.0-0.dll",etc. (At least that's how it is with *my* gtk2 installation.)
        I think any files named "Gtk2.dll" and "Glib.dll" would be the ones that were created for the Gtk2 and Glib perl modules.

        PAR::Packer will pack the xs versions automatically

        Ok - to have stated otherwise would be *my* mistake.
        This would then suggest to me that it's unnecessary (and possibly error-prone) to specifically pack any files named "Glib.dll", "Gtk2.dll", "Pango.dll", "Cairo.dll".

        The structure of the ppm packages has changed a bit in recent years.
        Currently, the s1s*.dll files should all be installed into perl/bin. I figure your chances of encountering another dll with the same name is about the same as winning a major lottery without even having a ticket.

        Cheers,
        Rob
        PAR::Packer will pack the xs versions automatically, so they should need to be specified using --link/-l. The others do need to be packed.

        PAR::Packer packed the xs.dll with including lib/auto/Gtk2 ... But with these inclusion, I have the error

        GLib-GObject-CRITICAL. See https://www.mail-archive.com/par@perl.org/msg05011.html
      Rob,

      How comes that in the Gtk2 stack you compiled for sisyphusion, the pango.dll which need Glib.dll and Cairo.dll find them in the packed exe (in inc/lib/auto/ ...) despite they are not in the shlib/ARCH/ folder ?

      Is that obvious for you ?

      F

Re: On the road again with Gtk2 and PAR::Packer
by Lotus1 (Vicar) on Feb 13, 2019 at 15:06 UTC

    Your question is very well stated but I'm curious about one thing you mentioned:

    The trick that was working then was to include the above dll and to rename the the Glib, Gtk2, Pango folders in lib/auto to hide them from the search path.
    The dll were then taken from the par archive at shlib\MSWin32-x86-multi-thread-64int\ folder and the exe works.

    Are you renaming the folders so that you can test that the exe works without them and should work on a different machine where they don't exist?

      Are you renaming the folders so that you can test that the exe works without them and should work on a different machine where they don't exist?

      I did renamed the folders to avoid the problem of mangled dll names made by PAR::Packer that resulted (?) in the error

      GLib-GObject-CRITICAL **: g_boxed_type_register_static: assertion `g_t +ype_from_name (name) == 0' failed

      Yes, the exe did worked on other pc without any perl installed

      F.
        I did renamed the folders to avoid the problem of mangled dll names made by PAR::Packer that resulted (?) in the error

        So that's the same error as you're now getting - but last time you were able to work around it, and this time you can't.
        Have I got that right ?

        From your original post:
        objdump -x 778ce824.xs.dll | grep "DLL Name" gives DLL Name: libcairo-2.dll DLL Name: libglib-2.0-0.dll DLL Name: libgobject-2.0-0.dll DLL Name: libpango-1.0-0.dll DLL Name: libpangocairo-1.0-0.dll DLL Name: msvcrt.dll DLL Name: Cairo.xs.dll DLL Name: Glib.xs.dll DLL Name: KERNEL32.dll DLL Name: perl524.dll
        That's the Pango.xs.dll by a different name - and you can see that it cross-references the Cairo and Glib xs.dlls.
        That's the cross-referencing that Roderick said was the cause of the issue (in https://www.mail-archive.com/par@perl.org/msg05011.html).

        If you take the Pango.dll from the older package (ie the one that worked) and "objdump -x" it in the same way, does it also report a dependency on "Cairo.dll" and "Glib.dll" (or "Cairo.xs.dll" and "Glib.xs.dll", as the case may be ) ?
        If so, then that pretty much proves that the cross-referencing is not the issue.
        Else it supports Roderick's view.

        Cheers,
        Rob
Re: On the road again with Gtk2 and PAR::Packer
by bliako (Abbot) on Feb 14, 2019 at 10:21 UTC

    I have been climbing the "perl embedding and static linking" learning curve for some time now and it just seems that there is some logic behind what my first impression was, madness. And of course I now see opportunities to use static/embedded Perl everywhere. Your case for example...

    If you are really desperate to get that working, then you can try to create a perl.exe which contains all the libraries it needs statically resulting in a very big exe which still needs to load pure-perl modules in the usual manner (so you would still need PAR for that) but does not need to load any XS libraries. They are all in there provided that you told the linker that you will need the functions in those libraries (read on).

    Similar to building a static perl, you can also build statically a very basic C-Perl-embedding, see perlembed, Re: Embed perl problem and Pass signals and argv from C to embedded Perl for such program, which will load your script and execute it in the embedded perl interpreter. That means you still have your Perl program which loads up now via your own myperl.exe, instead of via perl.exe. What you achieve with that is to place in your C-program dummy statements requesting GTK and XS functions so that the linker does actually links them statically instead of scanning your C program (and not your Perl program of course, so you see now why these dummy statements are useful) for function calls and linking only those that it sees you use. This can be achieved by the newXS() call.

    If I am not missing the point entirely about your situation and you decide to give this option a try, then let me know and can share my experience (I am planning to do it anyway in a couple of weeks when my stuff is more stable).

    But to get you an idea of the workload and workflow:

    1. install perlbrew (dont mess with your system perl!) and tell it to install a new perl and use "-Uusedl" - i.e. do not use dynamic loading (=loading XS on the fly) but instead static loading. There are some other options which may improve speed
    2. Now the fun starts, you need to fetch all modules you will ever need and their dependencies and compile those that contain XS code with "LINKTYPE=static" option. Static libraries will be created and installed, e.g. Sort/XS/XS.a in my linux box). This will be a long and repeating process, especially because there are some modules which seem to fail with static linking, case in point: Term::ReadKey, a hell of a time to install that for me.
    3. Now copy paste that C-Perl-embed program and start adding newXS() calls so that the linker does link the XS code you will need (remember the linker does not read Perl code!), for example newXS("Sort::XS::bootstrap", boot_Sort__XS, file) and add the Sort/XS/XS.a to the LDFLAGS.
    4. From time to time your program will complain about missing libraries if you omitted including a very indirect XS dependency

    ps. There are of course apps (which claim) to do static linking, like staticperl and fatpack. Maybe I have too much static (electricity, (c) BOFH) in my hands and none worked for me.

    bw, bliako

      Thanks for the detailed answer.

      Well, I would be glad to understand why what was succeeding, fails now. But I surely don't have the technical background to follow your proposal.

      I'd like to set up my gtk script on a few PCs and I'll probably install a portable strawberry perl with my scripts if I can't get the packaging working

      François

Re: On the road again with Gtk2 and PAR::Packer
by Anonymous Monk on Feb 16, 2019 at 02:12 UTC