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

Dearest Monks, I'm trying to create a small C program that uses Perl to work with some YAML (XS).

Everything works, except that I really need this to be statically linked so that I only have a single executable that packs the Perl libraries + the LibYAML XS libs. I need it that way for distribution purposes where no Perl or LibYAML can be installed (but other dependencies may be ok, like LibC, etc.).

Like a Golang freak colleague says, this would be "just like Go". He urges me to use Go instead, but I just can't believe a C-Perl compiled interpreter could not do the job just as well :)

Searching around in the we takes me to staticperl, which is a quite complicated beast, based on Perl 5.12 and not really what I'm looking for.

Here's a proof-of-concept program and the compilation line.

#include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { PERL_SYS_INIT3(&argc,&argv,&env); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; char *embedding[] = { "", "-e", "0" }; my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); perl_run(my_perl); eval_pv( "use YAML::XS;", TRUE ); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

cc myprog.c -o myprog `perl -MExtUtils::Embed -e ccopts -e ldopts`

Note I'm not using the Dynaloader in this example as I assume, if correctly linked as a static binary, my binary would not need Perl's Dynaloader... right?

Replies are listed 'Best First'.
Re: Compiling C program with a Static Perl
by Corion (Patriarch) on Sep 03, 2017 at 10:12 UTC

    I think that App::Staticperl should still work with most recent versions of Perl and basically give you what you want.

    The approach is basically your approach, compiling a single-executable statically linked Perl with the script embedded.

    I think you could look as an alternative at B::C, which tries to compile Perl to a static? executable.

    There also is PAR, which bundles a dynamically linked Perl and a Perl script into a single file. That one needs a work directory to unpack though.

Re: Compiling C program with a Static Perl
by zakame (Pilgrim) on Sep 03, 2017 at 15:11 UTC

    There's also the recently-announced stew from vti which might be up your alley, though if I read this right, something like the suggestions at perlembed might suit you more since you intend to use Perl from within your C program.

Re: Compiling C program with a Static Perl
by RonW (Parson) on Sep 06, 2017 at 23:13 UTC
    I need it that way for distribution purposes where no Perl or LibYAML can be installed

    Is this a policy or technical limit?

    If this a technical limit, then maybe a ZIP file could be used for distribution. The ZIP would contain your program, Perl and all the dependencies needed.

    (If your situation requires an installer, there are ways to convert a ZIP file into an installer.)

    (Although my primary PC runs Linux, I've only ever setup self-contained ZIP distributions for MS Windows, but this is possible with Linux, MacOS and others.)

    For MS Windows, I have started with the portable edition of Strawberry Perl. After downloading and unzipping to a folder, go to that folder and run portableshell.bat

    Then you can use the cpan command to install any dependencies from CPAN. You can copy any libraries your C program needs to the lib folder under the c folder.

    Once you have your program running in this environment, make a copy of portableshell.bat to yourprogram.bat and customize yourprogram.bat to run your program. If you have several programs, you can make customized copies of portableshell.bat for each.

    Test that your yourprogram.bat file(s) launch your program(s) correctly and everything is still running correctly.

    Zip the folder containing yourprogram.bat and the dependencies. On a PC with without Perl or your program, unzip the zip file and test your program(s). If everything still works correctly, you now have a ZIP file to distribute.

      If this a technical limit, then maybe a ZIP file could be used for distribution. The ZIP would contain your program, Perl and all the dependencies needed.

      (If your situation requires an installer, there are ways to convert a ZIP file into an installer.)

      See also Re: How do you distribute your Perl application to your customers?

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: Compiling C program with a Static Perl
by Anonymous Monk on Sep 03, 2017 at 11:55 UTC
    A true C++ library (or whatever binary language you are using ...) to work with YAML just might be easier . . . Perl is a great language but not necessarily in =this= use-case.

      This is a perfectly reasonable answer and I need to explain why I think it's completely awful.

      A true Foo for whatever Bar to work with Baz just might be easier. It becomes more sinister than the platitude it is without giving a specific example

      Perl is not a bad language or a language fated to lose to Ruby, Python, Go, Dart, PHP, or any other. Its major disadvantage today is lack of applications and code libraries matching currently relevant, growing problem domains.

      In this SoPW we have a user willing to sink time into attempting to relieve some tiny corner of that problem. The problem, above all others, which is withering the language and its adoption.

      The best solution to the user's problem may well be, forget about Perl, use this instead. The best solution for Perl, especially in cases like this where there is a clear interest in hearing it is, get after that with Perl and good luck!

      Update: fixed embarrassing typo.

        I agree that there's a tool for every job. In my case Perl would be the right tool. The code with LibYAML is just the tip of the iceberg (a proof of concept). Behind my example there is actually a good codebase that I'm not willing to rewrite and that make a single static Perl executable the right choice my use case... But unfortunately I can't find good simple examples on how to get it done. App::staticperl, like I said, is a huge mess that packs over 100 libs in one big Perl based on 5.12. But I guess there's no other way of doing it but by going over that code and see if I can figure it out.