Re: Which Perl versions Autoconf needs

Jacob Bachmeyer <[email protected]>
Newsgroups gmane.comp.sysutils.autoconf.general
Message-ID <[email protected]>
Gavin Smith wrote:
> On Wed, Mar 29, 2023 at 09:29:30PM -0500, Jacob Bachmeyer wrote:
>   
>> Do we need a direct configure test for "has Perl module"?
>> AC_PERL_MODULE([Digest::SHA]) would need to execute `$PERL -e "require
>> Digest::SHA"` and consider Digest::SHA available if that returns success.
>> Using Perl's -M option works for most modules, but a few (such as
>> Devel::Cover) produce effects beyond the perl process when import is called,
>> so simply evaluating "require" is less likely to cause weirdness.
>> (Theoretically, a module could do something when loaded with require, but
>> those kinds of side effects are strongly discouraged.  Devel::Cover creates
>> a coverage database in the current directory when import is called, but does
>> nothing when loaded with "require".)
>>     
>
> It would likely be possible to implement whatever tests were desired.
> For example, the Texinfo package has several occurences of checks for
> Perl modules.  Some of them occur at run-time, some at configure-time,
> and some are fatal and some are non-fatal.
>
> Here's an example of a configure check in configure.ac:
>
>     AC_MSG_CHECKING([Perl version for tests requiring unicode collation])
>     if $PERL -e "use 5.018_001; use Unicode::Collate" >/dev/null 2>&1; then
>       perl_unicode_collation_requirement='yes'
>     else
>       perl_unicode_collation_requirement='no'
>     fi
>     AC_MSG_RESULT($perl_unicode_collation_requirement)
>     PERL_UNICODE_COLLATE_OK=$perl_unicode_collation_requirement
>     AC_SUBST([PERL_UNICODE_COLLATE_OK])
>   

This is a fair example of a case where a Perl version could be a 
legitimate requirement, since Perl's Unicode support has often been 
incomplete or buggy and is deeply intertwined into the Perl core.  
However, while that is relevant for Texinfo, which must actually process 
text in many alphabets (and in this case, I am guessing, perform proper 
collation for building indexes), Automake and Autoconf deal primarily in 
ASCII and secondarily in octet strings, such that the details of Unicode 
support are irrelevant, and even the Perl 5.6 Unicode support is adequate.

This is also a fair start for an expansion for an AC_PERL_MODULE macro.  
To continue with the example I used earlier:

    AC_MSG_CHECKING([for Perl module Digest::SHA])
    if $PERL -e 'require Digest::SHA' >/dev/null 2>&1; then
      perl_module_Digest_SHA='yes'
    else
      perl_module_Digest_SHA='no'
    fi
    AC_MSG_RESULT($perl_module_Digest_SHA)
    PERL_MODULE_DIGEST_SHA=$perl_module_Digest_SHA
    AC_SUBST([PERL_MODULE_DIGEST_SHA])

The perl_* and PERL_* shell variable names can be obtained using the 
patsubst ([::] -> [_]) and translit ([a-z] -> [A-Z]) GNU m4 builtins.  
We probably should use the cache, so the expansion becomes:  (I think)

    AC_CACHE_CHECK([for Perl module Digest::SHA], 
[ac_cv_perl_module_Digest_SHA],
        [if $PERL -e 'require Digest::SHA' >/dev/null 2>&1; then
          ac_cv_perl_module_Digest_SHA='yes'
        else
          ac_cv_perl_module_Digest_SHA='no'
        fi])
    PERL_MODULE_DIGEST_SHA=$ac_cv_perl_module_Digest_SHA
    AC_SUBST([PERL_MODULE_DIGEST_SHA])

> An example of a run-time check (for the Archive::Zip module, in the
> EPUB output code):
>
>     eval { require Archive::Zip; };
>      
>     my $archive_zip_loading_error = $@;
>   

This discussion got started with a compile-time check (note that perl 
compiles the program to an in-memory intermediate form immediately 
before running it) that I wrote for Automake:

    BEGIN { eval { require Time::HiRes; import Time::HiRes qw(stat) } }

This is a bit of an odd duck, because the semantics of importing 
Time::HiRes::stat are to effectively replace the builtin stat operator 
with an XSUB that returns timestamps with fractional seconds included.  
As a consequence, while the result must be established before the rest 
of the module is compiled, failing to import Time::HiRes::stat leaves an 
obvious fallback:  the original stat builtin that only gives integer 
timestamps, which Automake now uses instead of failing if Time::HiRes is 
not available.

Note that the run-time check you cite is (as I understand) subtly wrong 
under most versions of perl, where edge cases exist that can allow an 
exception to be caught, yet $@ remains undefined.  I have never actually 
seen this happen and I do not remember exactly what the supposed edge 
cases are off the top of my head or if the edge cases were ever entirely 
eliminated, but seem to recall that the only way to be certain is to set 
a variable after the operation that can throw, like this:

    my $archive_zip_loaded = 0;
    eval { require Archive::Zip; $archive_zip_loaded = 1 };
    my $archive_zip_loading_error = $@;

Later code then looks for more details in $archive_zip_loading_error iff 
$archive_zip_loaded has remained false.  The issues with $@ may have 
been fixed at some point, but I typically use this "flag variable" 
method as a defensive programming practice, since it works under all 
versions of perl and is obviously correct upon inspection.  This was not 
an issue for importing Time::HiRes::stat in Automake, since the goal 
there was simply to get the high-resolution timestamps if available.


-- Jacob
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.