Search code examples
rautoconf

how to check the version of a program from inside autoconf script configure.ac


I spent half day trying to figure out whether my question is even feasible to ask or not. There is a MACRO for checking the availability of a program. For example R:

AC_PATH_PROG([R], [R], [nor])

Is there are standard way of checking the version of R found? For example, I am trying to base my project with R 3.6.x. This question could apply to any program of your liking. I could find out with a shell script:

R --version | grep "R version" | cut -d ' ' -f 3

The above snipit will return the version of R. Assume I can get this far somehow inside configure.ac, how do I make sure rversion > 3.5. Is ax_compare_version the way to go? The following is my test segment. Getting a little bit wrong. My general question: is my way of doing this acceptable practice?

AC_PATH_PROG([R], [R], [nor])
if test "$R" = nor; then
   AC_MSG_ERROR([No R installed in this system])
fi
RVERSION=`$R --version | grep "R version" | cut -d ' ' -f 3`
AX_COMPARE_VERSION([$RVERSION], [ge], [3.6.0], AC_MSG_NOTICE([R $RVERSION good]), AC_MSG_ERROR([R $RVERSION too low]))

 checking for R... /usr/local/bin/R
 configure: R 3.6.3 good

Note: to use the AX_COMPARE_VERSION you have to copy the m4 file to your project m4 directory or some system location.


Solution

  • Sure. The general idea is to turn it into expressions a shell script can evaluate / something you can run from `configure. Below are three different approaches.

    The first is some basic tests for g++ we had in the RQuantLib configure.ac package for many years (yes, that many years that we tested for g++-3.* ...). The main gist here is a wild card comparison.

    AC_PROG_CXX
    if test "${GXX}" = yes; then
        gxx_version=`${CXX} -v 2>&1 | grep "^.*g.. version" | \\
                   sed -e 's/^.*g.. version *//'`
        case ${gxx_version} in
            1.*|2.*)
             AC_MSG_WARN([Only g++ version 3.0 or greater can be used with RQuantib.])
             AC_MSG_ERROR([Please use a different compiler.])
            ;;
        4.6.*|4.7.*|4.8.*|4.9.*|5.*|6.*|7.*|8.*|9.*|10.*)
             gxx_newer_than_45="-fpermissive"
        ;;
        esac
    fi
    

    Here is another version from RProtoBuf where we compile something to have the version bubble up as a true/false expression:

    ## also check for minimum version
    AC_MSG_CHECKING([if ProtoBuf version >= 2.2.0])
    AC_RUN_IFELSE([AC_LANG_SOURCE([[
    #include <google/protobuf/stubs/common.h>
    int main() {
       if (GOOGLE_PROTOBUF_VERSION >= 2001000) {
            exit (0);
       } else {
            exit(1);
       }
    }
    ]])],
    [pb_version_ok=yes],
    [pb_version_ok=no],
    [pb_version_ok=yes])
    if test x"${pb_version_ok}" == x"no"; then
        AC_MSG_ERROR([Need ProtoBuf version >= 2.2.0])
    else
        AC_MSG_RESULT([yes])
    fi
    

    And I think I did something more recently where I made it an package_version object in R so that one can compare---here it is from RcppRedis -- this again comes back to configure as a true/false.

    ## look for (optional !!) MsgPack headers
    ## RcppMsgPack on CRAN fits the bill -- but is a soft dependency
    AC_MSG_CHECKING([for RcppMsgPack])
    ## Check if R has RcppMsgPack
    $("${R_HOME}/bin/Rscript" --vanilla -e 'hasPkg <- "RcppMsgPack" %in% rownames(installed.packages()); q(save="no", status=if (hasPkg) packageVersion("RcppMsgPack") >= "0.2.0" else FALSE)')
    if test x"$?" == x"1"; then
        AC_MSG_RESULT([yes])
        msgpackincdir=$("${R_HOME}/bin/Rscript" --vanilla -e 'cat(system.file("include", package="RcppMsgPack"))')
        msgpack_cxxflags="-I${msgpackincdir} -DHAVE_MSGPACK"
        AC_MSG_NOTICE([Found RcppMsgPack, using '${msgpack_cxxflags}'])
    else
        AC_MSG_RESULT([no])
        AC_MSG_NOTICE([Install (optional) RcppMsgPack (>= 0.2.0) from CRAN via 'install.packages("RcppMsgPack")'])
    fi  
    

    I hope this gives you some ideas.