Hello everybody out there using GNU autoconf,
What is the best practice to look for libftdi
and including it with autoconf
for compiling a C program using it?
The following snippet from a configure.ac
file works, but I'm not sure, whether it is best practice:
PKG_CHECK_MODULES([LIBFTDI], [libftdi])
#AC_CHECK_LIB([ftdi],[ftdi],[ftdi]) # Why doesn't this work?
#AC_SEARCH_LIBS([ftdi],[ftdi],[ftdi]) # Why doesn't this work?
#AC_CHECK_HEADERS([ftdi.h],[],[echo "error: missing libftdi header files" && exit 1])
LIBS="-lftdi $LIBS $LDFLAGS" # works, but is this the best way?
I'm building the program with autoconf (GNU Autoconf) 2.69
and compiling it with gcc version 7.5.0
on Ubuntu 18.04.
Your commented-out AC_CHECK_LIB
and AC_SEARCH_LIBS
examples do not demonstrate correct usage. Usage details are presented in the manual, but to sum up:
the arguments to AC_CHECK_LIB
are
ftdi
configure
to execute in the event that the library is found. Default is to prepend a link option to $LIBS
and define a HAVE_LIB*
preprocessor macro.configure
to execute in the event that the library is not found$LIBS
) that are needed to link a program that uses the library being checkedthe arguments to AC_SEARCH_LIBS
are
configure
to execute in the event that the library is found, in addition to prepending a link option to $LIBS
(but not defining any preprocessor macro)configure
to execute in the event that the library is not found$LIBS
that are needed to link a program that uses the library being checkedNeither your AC_CHECK_LIB
example nor your AC_SEARCH_LIBS
example properly designates an existing libftdi function to check for. Moreover, the third argument in each case is unlikely to be valid shell / Autoconf code, so in the event that the library were found, configure
would probably crash. Better might be:
AC_CHECK_LIB([ftdi], [ftdi_init])
or
AC_SEARCH_LIBS([ftdi_init], [ftdi])
Depending on what exactly you want to do, on details of libftdi, and on the configure.ac
context, you might need to provide appropriate values for some or all of the optional arguments.
The main reasons for a library check to fail despite the library in fact being installed are
The former is analogous to header installation location considerations discussed in the next section. The latter can be addressed by adding explicit extra link flags via the fifth argument to AC_CHECK_LIB
or AC_SEARCH_LIBS
, but is more often addressed semi-automatically by performing AC_CHECK_LIB
or AC_SEARCH_LIBS
tests in reverse prerequisite order, so that the value of LIBS
is built up with an appropriately-ordered list of link flags, ready at each point to support the next check, and ultimately appropriate for supporting the overall compilation.
Note also that libftdi provides both C and C++ interfaces. In ftdi_init
, I have been careful to choose a function that has C linkage, so as to avoid C++ name-mangling issues (see How to test a C++ library usability in configure.in?). You may also need to ensure that the tests are run with the C compiler (see Language Choice in the Autoconf manual).
Your AC_CHECK_HEADERS
usage, on the other hand, does not appear to be inherently wrong. If the resulting configure
script does not detect ftdi.h
, then that implies that the header isn't in the compiler's default header search path. That might happen, for example, if it is installed in a subdirectory, such as /usr/include/ftdi
. This would be a matter of both ftdi and system installation convention.
If it is ftdi convention for the headers to be installed in a subdirectory, then your source files should specify that in their #include
directives:
#include <ftdi/ftdi.h>
If your source files in fact do that, then that should also be what you tell Autoconf to look for:
AC_CHECK_HEADERS([ftdi/ftdi.h])
Regardless of whether a subdirectory prefix is expected or used, it is good practice to accommodate the possibility of headers and / or libraries being installed in a non-standard location. Although one can always do that by specifying appropriate flags in the CPPFLAGS
variable in configure
's environment, I prefer and recommend using AC_ARG_WITH
to designate a --with
argument or AC_ARG_VAR
to designate an environment variable that configure
will consult for the purpose. For example,
AC_ARG_WITH([ftdi-includedir],
[AS_HELP_STRING([--with-ftdiincludedir=dir],
[specifies a custom directory for the libftdi header files])],
[CPPFLAGS="$CPPFLAGS -I$withval"]
)
Exposing an argument or environment variable for the specific purpose highlights (in the output of ./configure --help
) the fact that this is a knob that the user might need to adjust. Additionally, receiving the include directory via a for-purpose vector is sometimes useful for limiting in which compilations the designated include directory is made available.
PKG_CHECK_MODULES
The Autotools objective and philosophy is to support the widest possible array of build machines and environments by minimizing external dependencies and writing the most portable configuration and build code possible. To this end, the Autotools are designed so that they themselves are not required to build projects on supported systems. Rather, Autoconf produces configure
as a stand-alone, highly portable shell script, and Automake produces configurable templates for highly portable makefiles. These are intended to be included in source packages, to be used as-is on each build system. Making your configure
script dependent on pkg-config
being installed on every system where your project is to be built, as using PKG_CHECK_MODULES
does, conflicts with those objectives.
How significant an issue that may be is a subject of some dispute. Where it is available, pkg-config
can be very useful, especially for components that require complex build flags. PKG_CHECK_MODULES
is thus very convenient for both package maintainer and package builder on those systems where it is present or readily available, for those components that provide pkg-config metadata.
But pkg-config
is not necessarily available for every system targeted by your software. It cannot reasonably be assumed present or obtainable even on systems for which it is nominally available. And even on systems that have it, pkg-config metadata for the libraries of interest are not necessarily installed with the libraries.
As such, I urge you to avoid using PKG_CHECK_MODULES
in your Autoconf projects. You need to know how to do without it in any case, because it is not an option for some libraries. Where appropriate, provide hooks by which the builder can supply appropriate flags, and let them choose whether to use pkg-config
in conjunction with those. Decoupling configure
from pkg-config
in this way makes a bit more work for you, and in some cases for builders, but it is more flexible.
PKG_CHECK_MODULES
exampleYour example invocation appears ok in itself, supposing that "libftdi" is the appropriate pkg-config module name (you have to know the appropriate name):
PKG_CHECK_MODULES([LIBFTDI], [libftdi])
But although that may yield a configure
script that runs successfully, it does not, in itself, do much for you. In particular, it verifies that pkg-config
metadata for the named module is present, but
pkg-config
, then you should use the link flags it reports to you instead of hardcoding -lftdi
, and that alone.Furthermore, it is more typical to use the output variables created by PKG_CHECK_MODULES
in your makefile than to use them to update $LIBS
or other general variables inside configure
. If you do use them in configure
, however, then it is essential to understand that LIBS
and LDFLAGS
have different roles with little overlap. It is generally inappropriate, not to mention unnecessary, to include the LDFLAGS
in LIBS
. If you want to update LIBS
inside configure
, then this would be the way to do it:
LIBS="$LIBFTDI_LIBS $LIBS"
And if you're going to do that, then you probably should do the same with the compiler flags reported by pkg-config, if any:
CFLAGS="$CFLAGS $LIBFTDI_CFLAGS"