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

Hi Monks,

This weekend I've been studying perlxstut for play. since I've already had some experience of XS, I thought it would be a cozy research. But reality hurt me deeply, I took 5 more hours to study example 4, but there are still some questions make me headache (mainly about ExtUtils::MM):
And finally create a file Makefile.PL that looks like this: use ExtUtils::MakeMaker; $Verbose = 1; WriteMakefile( NAME => 'Mytest2::mylib', SKIP => [qw(all static static_lib dynamic dynamic_lib)], clean => {'FILES' => 'libmylib$(LIB_EXT)'}, ); sub MY::top_targets { ' all :: static pure_all :: static static :: libmylib$(LIB_EXT) libmylib$(LIB_EXT): $(O_FILES) $(AR) cr libmylib$(LIB_EXT) $(O_FILES) $(RANLIB) libmylib$(LIB_EXT) '; }
Above contents are makefile.PL in Mytest2/mylib subdir, my questions are
  1. As I understand, this makefile.PL just told make how to build static lib. so if libmylib is shared, can I just
    WriteMakefile( NAME => 'Mytest2::mylib', ); #no MY
  2. can I just write a makefile on Mystest/mylib or a Makefile.PL? too many parameters on EU::MM.
sub MY::postamble { ' $(MYEXTLIB): mylib/Makefile cd mylib && $(MAKE) $(PASSTHRU) '; }
Obove are some contents of Makefile.PL on Mytest2, my question are
  1. What is $(PASSTHRU)? I neither find it on EU::MM pod nor on make manpage, but I find a PASTHRU on makefile in mylib directory, is the same?
  2. Why when I run perl Makefile.PL on Mytest2 level, there also build a makefile on Mytest2/mylib directory? I don't see any command about this on Makefile.PL on Mytest2.
  3. Is there a standard way to write xs of access to a library? I lookup on cpan, like gtk2, EV and Tk, It seems there are own way to do.
  4. Is there a xs cookbook on internet? I think I now fully understand the underlying knowledge of xs and corresponding directives, but I hope there is a cookbook to lookup so I could avoid the pitfalls in the futures
TIA.

Replies are listed 'Best First'.
Re: some questions about example 4 of perlxstut
by bliako (Abbot) on Jun 30, 2019 at 11:09 UTC

    This is what I can answer:

    1. What is $(PASSTHRU)? I neither find it on EU::MM pod nor on make manpage, but I find a PASTHRU on makefile in mylib directory, is the same?
    
    sub MY::postamble { ' $(MYEXTLIB): mylib/Makefile cd mylib && $(MAKE) $(PASSTHRU) '; }

    In the above code, what's in single quotes(*) is to be added verbatim to Makefile. It says that the requirement mylib.a depends on the Makefile in mylib dir. And in order to produce the requirement, make should enter mylib dir and run make command with the PASSTHRU argument which will be empty if it has not been defined at all.

    Essentially it looks to me an attempt to pass current make's parameters to the make spawn inside the mylib dir. Which, in my case, does not work - it's always empty. So, when I say make dynamic, it makes dynamic in Mytest2 dir but just make which defaults to make static in mylib and it creates a mess. The GNU-make variable $(MAKECMDGOALS) contains the target initially make was called with, e.g. "all" or "dynamic" for make all or make dynamic. See also https://www.gnu.org/software/make/manual/html_node/Recursion.html

    2. Why when I run perl Makefile.PL on Mytest2 level, there also build a makefile on Mytest2/mylib directory? I don't see any command about this on Makefile.PL on Mytest2. 
    

    As I said, the line $(MYEXTLIB): mylib/Makefile means that the requirement MYEXTLIB depends on "mylib/Makefile" which in itself can be a requirement with its own rules on how to be satisfied and therefore somehow create "mylib/Makefile". Maybe I am running this tutorial wrong but for me, "mylib/Makefile" is not created automatically whenever I run perl Makefile.PL && make in Mytest2 dir. There is no rule on how to make it in Makefile. However, if I add this to the postamble section of Makefile.PL, a Makefile in mylib is created automatically when needed:

    sub MY::postamble { <<'EXA'; mylib/Makefile: mylib/Makefile.PL echo "ZZZZZZZZ" cd mylib && perl Makefile.PL $(MYEXTLIB): mylib/Makefile echo "XXXXXXXXXXXXX pass is '$(PASSTHRU)' for GNU make, this tells + me the target to pass thru '$(MAKECMDGOALS)'" cd mylib && $(MAKE) $(PASSTHRU) EXA

    Note (*): better use the here-doc method rather than single quotes which will fail if you use single quotes in your Makefile stamble (e.g. "echo pass is ...")

    Note to anyone trying this tutorial: I seriously got bitten by copy-pasting code from perlxstut via firefox 60+. For me, each line of the code within the code-tags at https://perldoc.perl.org is pre-fixed with 4 spaces followed by a tab which renders the space-sensitive Makefile stabs useless. They were simply ignored.

    bw, bliako

      As I said, the line $(MYEXTLIB): mylib/Makefile means that the requirement MYEXTLIB depends on "mylib/Makefile" which in itself can be a requirement with its own rules on how to be satisfied and therefore somehow create "mylib/Makefile".

      I'm fairly confident that the creation of "mylib/Makefile" depends solely upon the existence of mylib/Makefile.PL. (But "confidence" != "expertise".)
      I think the line $(MYEXTLIB): mylib/Makefile comes into play when "libmylib.a" is created during the "make" stage.

      Maybe I am running this tutorial wrong but for me, "mylib/Makefile" is not created automatically whenever I run perl Makefile.PL && make in Mytest2 dir

      This is also something that I'm not seeing.
      For me "mylib/Makefile" is being created by the perl Makefile.PL step. Did you first create mylib/Makefile.PL ?

      Cheers,
      Rob

        You are right, I see Writing Makefile for Mytest2::mylib after running perl Makefile.PL in Mytest2 dir. I don't know why I did not see it before and had to add the extra rule.

Re: some questions about example 4 of perlxstut
by syphilis (Archbishop) on Jun 30, 2019 at 14:11 UTC
    Why when I run perl Makefile.PL on Mytest2 level, there also build a makefile on Mytest2/mylib directory?

    I think that's something that's done by EU::MM. When perl Makefile.PL is run, it seems that perl searches recursively through the directories below the current one, and executes all Makefile.PL files that it finds.
    If I create a Mytest2/bogus/Makefile.PL that contains simply warn "\nHello World\n"; then I see Hello World appear in the output when I run perl Makefile.PL in the Mytest2 directory.
    Also, if I remove Mytest2/mylib/Makefile.PL then its absence is not detected during the initial "perl Makefile.PL" step.

    I lookup on cpan, like gtk2, EV and Tk, It seems there are own way to do

    The gtk2 modules are faced with a challenge quite different to that of Example 4.
    With Example 4, the challenge is to access functionality that has been included with the Mylib2 source, whereas the gtk2 modules have to access functionality in the gtk2 libraries - which are 3rd party libraries not provided by the module's source distribution.
    The XS files provided by the gtk2 modules simply provide the glue that enables access to those external libraries, though they also rely on linking to those external libraries and on including their headers.
    Not sure about Tk or EV.

    For mine, the links provided by Anonymous Monk are more worthy of attention than this rather pathetic perlxstut that specifies ad-hoc code (not all of which can be copy'n'pasted), and reliance upon h2xs.
    I should add that I've never used (and likely never will use) h2xs, and am therefore perhaps not fully appreciative of what it has to offer.

    Cheers,
    Rob

      Thanks Rob, I usually use Inine::C to call some C functions from a library or create a skeleton of XS module, it's very handy, and I haven't touched h2xs for long time also. But as you said, example 4 is aim to access to functions in source, in this scenario, Inline C is not very suitable I think, although what h2xs shows in example 4 in perlxstut is not good either.

      So what's the good way to generate XS (automatically) for access to a large source distribution? I'll look up ExtUtils::XSpp, hope it's a right way to go.

        So what's the good way to generate XS (automatically) for access to a large source distribution?

        I don't know - it's not something I've done, and Example 4 would indicate that a large amount of hand-editing of the XS file that's generated by h2xs would be required.
        However, you might find something useful in perldoc Inline::C::Cookbook.
        For example there's a small section headed "Replacing h2xs" that seems to discuss this very issue, though it's thin on detail and I don't understand it.

        FAIRK, maybe that fiddly "Example 4" is, in fact, as good a way as any ?

        Cheers,
        Rob
Re: some questions about example 4 of perlxstut
by Anonymous Monk on Jun 30, 2019 at 04:02 UTC