in reply to How to author a module with optional XS

Math::Prime::Util has pure-perl and XS implementations of everything, with options to override which to use via the environment variable MPU_NO_XS, and specific documentation on some methods to warn that they will be unusually slow in pure perl. It's a pretty mature and successful distribution, so one worth looking at (though it hasn't had a new release for a while now - I remain hopeful that there will be one soon).

I don't believe it attempts to automate the choice however: as far as I recall, the user decides whether to build the XS, and whether to use it in any given instance. That feels to me like a better approach than having the build process decide for itself - I wouldn't want a module to silently install the pure-perl code and claim success just because it tripped over some trivial, easily-fixed problem building the XS code.

Replies are listed 'Best First'.
Re^2: How to author a module with optional XS
by NERDVANA (Priest) on Aug 30, 2023 at 23:30 UTC
    I wouldn't want a module to silently install the pure-perl code and claim success just because it tripped over some trivial, easily-fixed problem building the XS code

    Well, that's a good point. Trying to automatically make it fast could just as easily fail and make it silently not-fast.

    What about trying to detect presence of a functioning C compiler during Makefile.PL and then spitting out a dependency on the ::XS variant? Something like:

    1. If an environment variable says not to try XS, proceed with normal make
    2. Else, look for a C compiler and relevant tooling. If found, end the Makefile.PL with a dependency on MyModule::XS
    3. cpanm switches to installing MyModule::XS
    4. cpanm comes back and finishes installing MyModule.

    Are there official methods to detect whether XS is supported by a Perl environment? I thought maybe I could find out whether Devel::CheckLib finds a compiler, but it appears that Devel::CheckLib probably can't be installed unless it does find a compiler. So I can't list Devel::CheckLib as a dependency for a module that I want to be installable on compiler-less perls.

    Maybe I shouldn't worry about compiler-less perl environments? (are there any where a compiler *can't* be installed?) and just focus on making sure my module can work properly with fat-packing, since I think that is the main reason that people try to avoid XS dependencies?

      I don't know what capabilities there are to detect whether C compilation is available.

      Generally, however, the user will know - and might want to skip the C compilation even when a compiler is available, for whatever reason. So my inclination would be to let the user choose, and to concentrate on providing good error messages if you can't do what they ask you to (and at most a warning if you think what they've asked for isn't the best option for them).

      For what it's worth, one of my recent maths projects (written in C) is being run by a number of people on Windows, but despite several of them being programmers only one of them was prepared to actually compile the code (who then provided a binary I could distribute to the others) - even while some of them were asking for features that were already available as compile-time options. I do not pretend to understand this, but I think I can reasonably conclude that some people have a complicated relationship with the concept of a compiler.

        I don't know what capabilities there are to detect whether C compilation is available.

        Neither do I, but one should be obvious: Just try to compile something. On a sane system (for some definition of sane), creating foo.c followed by invoking make foo in the directory containing foo.c should result in a binary named foo and an exit code of 0. If anything went wrong, the exit code will be non-zero and/or foo does not exist. To see if you did not accidentally invoke a cross-compiler, you would simply try to start foo. To detect if foo.c behaves as expected, make it exit with an exit code that is unlikely to happen and/or write out a text that you test for when invoking foo.

        Something like this:

        /tmp>cat foo.c int main(void) { return 42; } /tmp>make foo cc foo.c -o foo /tmp>echo $? 0 /tmp>./foo /tmp>echo $? 42 /tmp>

        Of course, getting that to work on non-Unix systems needs a little bit more work, starting with the fact that the compiled binary will very likely be named foo.exe, not just foo, on Windows. I also completely ignored all problems of having the right libraries and headers available. And, of course, I did not write any Perl code to write foo.c and to compile it, but that's just a little bit of perlipc.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      Re "are there any where a compiler *can't* be installed?" - answer - Production systems usually ban compilers for security.

        Production systems usually ban compilers for security.

        yet programs still get installed on production systems -- its not rocket brain surgery