Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Inline::C and Dist::Zilla

by basiliscos (Pilgrim)
on Nov 13, 2014 at 20:08 UTC ( [id://1107150]=perlquestion: print w/replies, xml ) Need Help??

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

Hello dear monks!

I am creating portable perl application, which should run under Windows. So, I use embedded perl features to create my binary, as kindly described here.

I use Inline::C to speed up data processing. (I have got x75! speedup, if your curious).

But everytime I launch my-binary.exe I see _Inline. This is not what I would like to see, because I cannon assume that gcc will be available on client PCs. OK, here is an excerpt from :

The Inline code only gets compiled the first time you run it (or whenever it is modified) so you only take the performance hit once. Code that is Inlined into distributed modules (like on the CPAN) will get compiled when the module is installed, so the end user will never notice the compilation time.

How to achieve that? I use Dist::Zilla to build my application/module; I have found Dist::Zilla::Plugin::InlineIncluder, and have had an hope, that

[InlineIncluder]

will magically do all required stuff. But, no, now dz fails on build:

dzil build [DZ] beginning to build Iston Inline and Inline-C repos missing or not in right state at /home/basil +iscos/perl5/perlbrew/perls/perl-5.20.1/lib/site_perl/5.20.1/Dist/Zill +a/Plugin/InlineIncluder.pm line 49.

I'm stuck here, and don't know what to do.

Thanks for any advice!

WBR, basiliscos

Replies are listed 'Best First'.
Re: Inline::C and Dist::Zilla
by ikegami (Patriarch) on Nov 13, 2014 at 20:36 UTC
    Once you have used Inline::C to create your .xs file, you don't need to use Inline::C anymore. You can just make it an XS module using the XS file Inline::C generated as your XS file.
Re: Inline::C and Dist::Zilla
by davido (Cardinal) on Nov 13, 2014 at 21:37 UTC

    What you are looking for is the new (infant, currently under rapid development) module, Inline::Module. Its purpose is to allow authors to write "Inline::C" code, and produce XS modules. The final product would be a module that, to the end user, is indistinguishable from plain old XS. See http://inline.ouistreet.com for the project's blog, and stop by #inline on irc.perl.org to discuss it.


    Dave

      Thanks, Dave

      I think I misunderstood the usage of Inline::C: it helps in creation XS-modules, but not in creation of distributions with XS-code.

      So, If I know XS, it would be less problems just to create old plain XS-distribution with XS-module, than using Inline::C

        I'm not sure I am interpreting your question correctly, but here goes:

        Inline::C gives the appearance of C code being included in-line with your Perl script. Internally this works by producing an XS module that the target codebase can bootstrap with Dynaloader and use. This happens quietly, behind the scenes. Someone else suggested that you could just take that auto-generated XS module and use it to create your own XS module via the time-honored tradition of copy/paste/fiddle. This has been how many people get started with their XS-based modules; prototype with Inline, then migrate to full XS.

        Inline::Module lets a distribution be created by using Inline to author the code, but then the end-user just gets the .so file installed where any other XS-generated .so (or .dll, etc) file would have been installed on any plain old XS based distribution.

        We're still working on it. Currently it works for ExtUtils::MakeMaker based distributions, and probably for Dist::Zilla by now as well. But documentation is sparse, and there are no guarantees that something won't change before we officially announce the release. Nevertheless, we would love for people to go ahead and give it a try, and to check in at #inline with questions. Issues can be posted to the module's GitHub repository issue tracker.


        Dave

Re: Inline::C and Dist::Zilla
by syphilis (Archbishop) on Nov 13, 2014 at 23:37 UTC
    But everytime I launch my-binary.exe I see _Inline. This is not what I would like to see, because I cannon assume that gcc will be available on client PCs.

    I don't understand the logic flow there.
    _Inline is just the directory that contains the compiled C code. If it is present, then it won't matter whether the client PC has gcc or not - because all of the required compilation has already been done.
    The client machine will, however, need Inline::C installed (or you'll need to package Inline::C with the app).

    The only thing that can bring you undone (AFAICT) is that, if you used gcc-4.x.x to compile the Inline::C code in your app, then it will have a runtime dependency on either libgcc_s_dw2-1.dll (mingw.org vendor) or libgcc_s_sjlj-1.dll (mingw-w64 vendor).
    If the client machine doesn't have a gcc-4 compiler from the same vendor as you (or their gcc-4 compiler is not in their path) then that dll will not be found.
    So you probably need to ship that dll with your app - in the _Inline/lib/auto/<whatever_it's called>/ directory.
    You'll find that dll in your compiler's bin directory.

    But if you used gcc-3.x.x then there are no such dll issues.

    Cheers,
    Rob

      When is the libgcc_s dependency even necessary? Gcc documents the -static-libgcc option, while saying:

      There are several situations in which an application should use the shared libgcc instead of the static version. The most common of these is when the application wishes to throw and catch exceptions across different shared libraries. ...

      Also, if a module depends on some small and obscure library, it might be preferable to static link with that. A la

      $ make foobar LDFLAGS='-lthis -lthat -Wl,-dn,-lobscure,-dy'
      (Mind you, this is all from the linux perspective.)

        When is the libgcc_s dependency even necessary?

        Good point.
        I wasn't sure if invoking -static-libgcc would work if perl had not been built with the same option - but I've just run a quick check (see below) and it seems that there's no problem in that regard.
        So if the OP wants to distribute binaries compiled with gcc-4, but doesn't want to distribute the dll, then that's the way to go.

        Actually, there's sometimes a dependency on a second dll (libstdc++-6.dll) so, to avoid having to distribute that dll, you'd also invoke -static-libstdc++.
        These are linker flags, so they need to be given to $Config{ld}, which is g++ on Mingw-built perls.
        As a quick test I ran:
        use Inline C => Config => BUILD_NOISY =>1, LD => 'g++ -static-libgcc', INC => '-IC:/MinGW/msys/1.0/local/include'; use Inline C => <<'EOC'; SV * foo(SV * x, SV * y) { return newSVnv(SvNV(x) * SvNV(y)); } EOC $x = foo(2.3, 1.1); print $x, "\n";
        Sure enough, the script ran fine and objdump revealed that the dll that was built had no dependency upon libgcc_s_dw2-1.dll:
        C:\_32\pscrpt\inline>objdump -x _Inline/lib/auto/try_pl_0a36/try_pl_0a +36.dll | grep "DLL Name" DLL Name: KERNEL32.dll DLL Name: msvcrt.dll DLL Name: perl516.dll
        Whereas, if I commented out the LD => 'g++ ... assignment I then got
        C:\_32\pscrpt\inline>objdump -x _Inline/lib/auto/try_pl_0a36/try_pl_0a +36.dll | grep "DLL Name" DLL Name: libgcc_s_dw2-1.dll DLL Name: KERNEL32.dll DLL Name: msvcrt.dll DLL Name: perl516.dll
        Cheers,
        Rob

      Thank you, Rob

      Indeed, you are right. I all need to have my portable application is:

      1. gather dependencies in lib sub-directory
      2. compile and link binary with libperl
      3. run my binary to get _Inline to be generated with needed dll-files

      I missed the 3rd step, because I assumed, that _Inline-stuff will be already somewhere, when I install my module

      With the possible problem you described, i.e. need of the 4th step to find-and-copy gcc dll, I think I should use plain XS instead of Inline::C to have only 2 steps

      WBR, basiliscos

        I think I should use plain XS instead of Inline::C to have only 2 steps

        If you're going to compile the XS module using gcc-4 before sending it to the various client PC's then you still leave yourself open to the very same dll-dependency problem.

        If you compile with gcc-3 it won't be a problem (though this is a poor reason for using gcc-3 instead of gcc-4 imo) ... or if you just distribute the source to the client PC's and leave the XS compilation to be done on those client machines then you also avoid the issue.

        Even if you were to compile the XS component using a post-MSVC++6 Microsoft compiler you would strike a similar problem in that the compiled code would depend upon a runtime library that might not be present on the client PC.

        However, I don't think you should worry too much about these issues. They are solvable and you'll soon work out what needs to be done if they jump up and bite you.
        The good news is that whenever a dll is not found, the error message (pop-up) gives you the name of that dll.

        Cheers,
        Rob

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (6)
As of 2024-04-19 09:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found