Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Need help using Inline::Module with JavaScript::Embedded

by cavac (Parson)
on Jul 13, 2022 at 10:47 UTC ( [id://11145473]=perlquestion: print w/replies, xml ) Need Help??

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

I want to compile the C library in JavaScript::Embedded at install time, not every time it is used.

I've been trying for a few days now to get JavaScript::Embedded to work with Inline::Module, but i never could get it to work. Frankly, this is one area of Perl that i feel like stumbling through the woods with a blindfold on.

Any XS/Inline::C experts on PM that volunteer to have a go at this and become part of the project?

Update: Thank you everyone! I've released a new version on CPAN that should now work as expected and only compile once at install time.

PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP
  • Comment on Need help using Inline::Module with JavaScript::Embedded

Replies are listed 'Best First'.
Re: Need help using Inline::Module with JavaScript::Embedded
by syphilis (Archbishop) on Jul 14, 2022 at 02:57 UTC
    I want to compile the C library in JavaScript::Embedded at install time, not every time it is used.

    Ok ... apply this patch (or make the specified changes by hand) to Embedded.pm.
    Update: Patch corrected to remove errant whitespace. (Thanks LanX.)
    --- Embedded.pm_orig 2022-07-14 21:12:05 +1000 +++ Embedded.pm 2022-07-14 12:01:26 +1000 @@ -4,6 +4,14 @@ use Carp; use Data::Dumper; use Scalar::Util qw( weaken ); + +use Config; +BEGIN { + # Create Inline's build directory: + mkdir "$Config{installsitelib}/_Inline" + unless -d "$Config{installsitelib}/_Inline"; +}; + our $VERSION = '2.7.1'; my $GlobalRef = {}; @@ -315,6 +323,9 @@ } use Inline C => config => + build_noisy => 1, + clean_after_build => 0, + directory => "$Config{installsitelib}/_Inline", typemaps => _get_path('typemap'), INC => '-I' . _get_path('../C') . ' -I' . _get_path('../C/l +ib'); # myextlib => $Duklib,
    I've assumed that $Config{installsitelib} always exists, and is writable.
    I think those are fairly safe assumptions.
    The thing is that, in order to avoid the re-compilation issue, you need to assign a specific directory as Inline's build directory.

    Setting of the "build_noisy" and unsetting of the "clean_after_build" config options is not really needed - they just make things a little clearer. (IMO, "build_noisy" should be set by default.)
    Unsetting the "clean_after_build" option allows us to go into the build directory and view the XS and C files that Inline::C generated. Otherwise, those files are deleted when the build has been completed.

    If, having built the module, you go into the $Config{installsitelib}/_Inline/build/JavaScript/Embedded directory and locate the XS file (in the "Vm_a662" subdirectory on my build) generated from duk_perl.c you'll see that the standard perl headers (EXTERN.h, perl.h and XSUB.h) have been included twice.
    Also, Inline::C does not handle PERL_NO_GET_CONTEXT and might also not handle NO_XSLOCKS (I don't know).
    Both PERL_NO_GET_CONTEXT and NO_XSLOCKS need to be declared before the standard perl headers - and that clearly is not happening.
    None of this is causing any breakage, but I recommend that you apply the following changes to duk_perl.c for clarity:
    --- duk_perl.c_orig 2022-07-14 12:38:44 +1000 +++ duk_perl.c 2022-07-14 12:40:08 +1000 @@ -1,9 +1,4 @@ -#define NO_XSLOCKS -#define PERL_NO_GET_CONTEXT -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" #include "ppport.h" #include <time.h> #include <stdlib.h>
    If you really want to effectively define PERL_NO_GET_CONTEXT, then we'll need to say goodbye to Inline::C and switch to XS.
    For that, I would be using my own InlineX::C2XS (which uses Inline::C) to generate the XS file(s).

    Are you happy enough with just those changes to Embedded.pm and duk_perl.c ? ... or do we need to go further ?

    Cheers,
    Rob

      So that is how to do it! Very, very nice!

      I've done limited testing so far, but it seems to work exactly the way i wanted it to be. Outstanding job, very much appreciated!

      I've released a new version on CPAN, should be available on mirrors in a few hours.

      PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP
        So that is how to do it!

        Well, it's one way to do it ... but it's a different way to the way it's done in the demo module that ships with the Inline::C source.
        That demo module is Math-Simple-1.23, and you'll find it in the examples/modules folder in the Inline-C source distro.

        When you build and install that module (which is safe and fine to do), you'll find that compilation of the C code is done only once (ie during 'make test'), yet nothing is done to control the location of the Inline build directory.
        I don't know why JavaScript::Embedded is requiring special treatment wrt the location of the _Inline build directory. I think the difference probably lies in some magic provided by Inline::MakeMaker - which the Math::Simple Makefile.PL uses in place of ExtUtils::MakeMaker.
        But I can't remember and I don't really feel like digging into it.
        Have a play with Math::Simple if you're interested and you'll quickly see that there's no re-compiling being done.

        BTW, the problem I had building JavaScript::Embedded on perl-5.36.0 is my fault. The mingw-w64 compiler that built that perl defines _WIN32_WINNT to 0x0602 0x0a00, which implies that I'm running Windows 8 10 (and therefore that GetSystemTimePreciseAsFileTime() is available).
        But I'm actually on Windows 7, and GetSystemTimePreciseAsFileTime() is therefore unavailable does not become available until Windows 8.
        The mingw-w64 compiler that built my perl-5.34.0 defines _WIN32_WINNT to 0x0502 (which implies pre-Windows7) and therefore avoids the issue.

        I've released a new version on CPAN, should be available on mirrors in a few hours

        JavaScript-Embedded-2.7.2 built, tested, and installed fine for me on perl-5.34.0.

        Cheers,
        Rob
Re: Need help using Inline::Module with JavaScript::Embedded
by syphilis (Archbishop) on Jul 13, 2022 at 13:27 UTC
    I've been trying for a few days now to get JavaScript::Embedded to work with Inline::Module, but i never could get it to work.

    I've downloaded JavaScript-Embedded-2.7.1, and had a go at building it on Windows 7, perl-5.36.0, but during 'make test', I continually hit the fatal perl.exe error "The procedure entry point GetSystemTimePreciseAsFileTime could not be located in the dynamic link library KERNEL32.dll".
    This happens at the beginning of each of the 56 test scripts.
    KERNEL32.dll is, of course a Windows system dll.

    If I switch to perl-5.34.0 on the same machine, the module builds and tests fine - so I guess I'll work with that perl for the moment.

    What is it that you want to fix ?
    When the test suite is run for the first time, Inline::C performs its required compilation before the tests run.
    When the test suite is run for the second time, no compilation is done and the existing compiled binaries are used.
    That all looks correct. If I can get a better idea of what you want to alter then I might be able to help.

    UPDATE: I think I can now see the issues that need to be addressed. I'll upload a separate post (in this thread) with some fixes, later today.

    Cheers,
    Rob
      When the test suite is run for the first time, Inline::C performs its required compilation before the tests run. When the test suite is run for the second time, no compilation is done and the existing compiled binaries are used.

      Sorry for the slightly off-topic questions ahead, but I am still a beginner, learning Perl.

      So, I want to understand this a little bit better. So, when inline C is used, the compiler saves the binaries. How does Perl know not to compile it again? And where does the compiler save the binaries when done? Is it in /tmp/ramdisk or is there a specific directory for Perl inline C binaries? How are these binaries named? Are they given random names?

        In brief:

        How does Perl know not to compile it again?

        Any change to the C code (including changes affecting only whitespace) will be detected as a change to the MD5 fingerprint, and the code will only then be recompiled.
        Changes to Inline configuration options will not alone trigger a rebuild - unless it's the FORCE_BUILD option that is being changed to a TRUE value.

        And where does the compiler save the binaries when done?

        Generally the building is done in ./_Inline/build and the binaries saved in ./_Inline/lib, but the name of the parent directory is configurable.

        How are these binaries named?

        A combination of the filename of the script, and the leading hex digits of the MD5 fingerprint of the code section.

        Cheers,
        Rob
Re: Need help using Inline::Module with JavaScript::Embedded
by bliako (Monsignor) on Jul 13, 2022 at 21:35 UTC

    ExtUtils::MakeMaker's Makefile.PL has a postamble sub where you can specify things to be injected into the produced Makefile. In theory you can add Makefile code to compile and install your binaries as your module is make'ed. That would be permanent. But as anonymous monk said, quickest way would be to find the XS produced and just include it in your distribution (somehow! I am a novice of XS, I can not tell you how).

    BTW, when I even do whichpm JavaScript::Embedded it takes ages (18sec) to complete! 100x more than other modules.

    BTW2, my compiler complains that croak(msg) (in fatal_handler of produced XS) needs a format and this croak("%s", msg) keeps it happy. Is that an Inline::C issue I wonder (perl 5.32/linux almost latest) hint-hint syphilis.

    bw, bliako

      BTW, when I even do whichpm JavaScript::Embedded it takes ages (18sec) to complete! 100x more than other modules.

      Yes - I think it's just silently compiling the Inline::C code first.
      IMO, the Inline config should specify build_noisy => 1, so that we can see what's happening (or, at least, that *something* is happening).
      It also needs to specify a build directory something like directory => "$Config{installsitelib}/_Inline", in order to avoid the re-compilation issue cavac mentioned.
      There's a bit to work through.

      BTW2, my compiler complains that croak(msg)....

      I haven't noticed that ... something else to check.

      Cheers,
      Rob
Re: Need help using Inline::Module with JavaScript::Embedded
by Anonymous Monk on Jul 13, 2022 at 11:14 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11145473]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (2)
As of 2024-04-20 06:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found