5

I'm using link-time optimisation (LTO) in a project that compiles under both GCC and Clang and builds a static library. It's working with GCC 4.8, but GCC 5.4 makes thin LTO objects and when automake tries to build the static library with ar it fails, because it needs the wrapper script gcc-ar.

Is there a good example I can look at for how to make automake use gcc-ar instead of ar (and similarly for gcc-ranlib)? I can probably hack something in, but ideally it should:

  • Use the appropriate tools for the compiler (Clang has its own instructions).
  • Work even if the user overrides the compiler to one that isn't the system default.
  • Work when cross compiling
Bruce Merry
  • 751
  • 3
  • 11

2 Answers2

2

You can override the default tools used by calling

./configure AR=gcc-ar RANLIB=gcc-ranlib

I'm afraid for ./configure to pick them up by default, autoconf/automake will have to be fixed to know about those in the default set of checks.

Diego Elio Pettenò
  • 3,152
  • 12
  • 15
  • One can write a custom set of checks to do this (autoconf is fully extensible). My question is whether any project has already done this so that I can follow their example, rather than figure out how to handle all the compilers on my own. – Bruce Merry Dec 04 '16 at 06:49
0

Use this:

AC_ARG_VAR([AR], [AR command (default is gcc-ar)])
AC_CHECK_TOOL([AR], [gcc-ar])

AC_ARG_VAR([RANLIB], [RANLIB command (default is gcc-ranlib)])
AC_CHECK_TOOL([RANLIB], [gcc-ranlib])
  • AC_ARG_VAR is there just to document it, when invoking ./configure --help.

  • AC_CHECK_TOOL is used for these tools, instead of AC_CHECK_PROGS, so the right version is used when cross-compiling.

  • You can still override AR, RANLIB when invoking ./configure.

  • To fallback to regular ar and regular ranlib, you can use AC_CHECK_TOOLS instead:

    AC_CHECK_TOOLS([AR], [gcc-ar ar])
    
  • An optional third argument can be set to something like : so you can test if none of the tools were found:

    AC_CHECK_TOOLS([AR], [gcc-ar ar], [:])
    AS_VAR_IF([AR], [:], AC_MSG_ERROR([could not find AR tool.]))
    

For Clang, they follow a different naming convention: llvm-ar, llvm-ranlib, llvm-objcopy, etc. I'll be using two helper macros.

First, we define MY_CHECK_TOOL_PREFIX, using AX_COMPILER_VENDOR, this will try to guess what tool prefix to use; it can be overridden with the TOOL_PREFIX variable. It will test the compiler for the current language (defaults to C); make sure to call AC_LANG(C++) beforehand if needed. It's used by the next macro, you don't need to call it manually.

AC_DEFUN([MY_CHECK_TOOL_PREFIX],
[
    AC_REQUIRE([AX_COMPILER_VENDOR])
    AC_ARG_VAR([TOOL_PREFIX], [tool prefix (gcc, llvm)])
    AC_MSG_CHECKING([toolchain prefix])
    # only convert vendor to prefix if not already set
    AS_VAR_SET_IF([TOOL_PREFIX],
        [],
        [
            AS_CASE([${ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor}],
                [gnu], [TOOL_PREFIX="gcc"],
                [clang], [TOOL_PREFIX="llvm"],
                [TOOL_PREFIX="unknown"])
        ])
    AC_MSG_RESULT([$TOOL_PREFIX])
])

Then comes the macro you'll be using: MY_CHECK_TOOL. The default action, if not variant of the tool is found, is to abort.

dnl MY_CHECK_TOOL(TOOL, PROGRAM-TO-CHECK, [ACTION-IF-NOT-FOUND])
AC_DEFUN([MY_CHECK_TOOL],
[
    AC_REQUIRE([MY_CHECK_TOOL_PREFIX])
    AC_ARG_VAR($1, [$1 command (default is TOOL_PREFIX-$2, $2)])
    AC_CHECK_TOOLS($1, [${TOOL_PREFIX}-$2 $2], [:])
    AS_VAR_IF($1, [:],
        [m4_ifblank($3,
            [AC_MSG_ERROR([could not find $1])],
            $3)])
])

You can save both in a my_prefix_tools.m4 file in your M4 dir, if you don't want to clutter your configure.ac.

And here's how you'd use it in configure.ac:

AC_PROG_CXX
AC_LANG(C++)
MY_CHECK_TOOL([AR], [ar])
MY_CHECK_TOOL([RANLIB], [ranlib])
MY_CHECK_TOOL([OBJCOPY], [objcopy])
MY_CHECK_TOOL([NM], [nm])

When running ./configure where g++ is the default C++ compiler, this is the output:

checking for C++ compiler vendor... gnu
checking toolchain prefix... gcc
checking for gcc-ar... gcc-ar
checking for gcc-ranlib... gcc-ranlib
checking for gcc-objcopy... no
checking for objcopy... objcopy
checking for gcc-nm... gcc-nm

And when running ./configure CXX=clang++, this is the output:

checking for C++ compiler vendor... clang
checking toolchain prefix... llvm
checking for llvm-ar... llvm-ar
checking for llvm-ranlib... llvm-ranlib
checking for llvm-objcopy... llvm-objcopy
checking for llvm-nm... llvm-nm
DanielKO
  • 4,422
  • 19
  • 29