autoconf/automake: conditional compilation based on presence of library? - autoconf

I need to conditionally compile some code based on the presence of a library. Seems like this should be easy with autoconf/automake but I can't figure it out.
For example, if there is a PNG library present, I want to include code to use it. My configure.ac has:
AC_CHECK_LIB([png], [png_create_write_struct_2])
and my Makefile.am has:
if USE_LIBPNG
libdev_la_SOURCES += png.c
endif
(which adds png.c to the list of sources for libdev so it gets compiled).
An automake conditional like USE_LIBPNG requires the conditional be defined in configure.ac, so i need:
AM_CONDITIONAL([USE_LIBPNG], [test SOMETHINGOROTHER])
The question is, what can test SOMETHINGOROTHER be? What does AC_CHECK_LIB define that I can test for?
AC_CHECK_LIB's default behavior is to define a symbol (in config.h) which can be used in source code, but that doesn't help the Makefile since the AM_CONDITIONAL needs a shell test
I tried overriding the default AC_CHECK_LIB behavior like so:
AC_CHECK_LIB([png], [png_create_write_struct_2], [HAS_LIBPNG=1])
after which I could test for it:
AM_CONDITIONAL([USE_LIBPNG], [test "x$HAS_LIBPNG" = "x1"])
This is ugly, but works for the Makefile... but creates a new problem: since it discards the original AC_CHECK_LIB behavior, and I no longer get a symbol added to config.h, which I need.
I must be missing something basic, or possible Doing It Wrong. Have been digging around for hours and found no answer.
Anyone?

If the library you're checking for supplies a .pc file for use with pkg-config, then you're much better off using PKG_CHECK_MODULES to get the correct flags. libpng does:
(in configure.ac)
PKG_CHECK_MODULES([libpng], [libpng12])
This gives you access to the variables $(libpng_CFLAGS) and $(libpng_LIBS) which you will want to add to Makefile.am (probably in AM_CFLAGS/AM_CXXFLAGS and LDADD, or target-specific versions thereof).
It will also cause configure to fail with an error if libpng12.pc isn't found. If you want configure to continue, you'll need to supply the third and fourth arguments to PKG_CHECK_MODULES, which are ACTION-IF-FOUND and ACTION-IF-NOT-FOUND:
(in configure.ac)
PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])
Now, if you need an automake conditional, you can do something like:
(in configure.ac)
AM_CONDITIONAL([USE_LIBPNG], [test "$HAVE_LIBPNG" -eq 1])
If you also need the preprocessor definition, you could use AC_DEFINE like so:
(in configure.ac)
AS_IF([test "$USE_LIBPNG" -eq 1], [AC_DEFINE([USE_LIBPNG], [1], [Define if using libpng.])])
Possibly nicer is to set the definition in Makefile.am:
(in Makefile.am)
AM_CPPFLAGS =
if USE_LIBPNG
AM_CPPFLAGS += -DUSE_LIBPNG
endif
This will clutter your command line, though, whereas AC_DEFINE can put the definition in a header if you use AC_CONFIG_HEADERS. I guess this doesn't really matter if you use AM_SILENT_RULES([yes]) or don't care about your command line being neat (and let's be honest, automake generates some pretty gnarly command lines anyway).
A note on good autoconf style
It is considered poor form to build optional support based on whether or not a check succeeded (see this gentoo doc for details). Here's how I'd code optional support for libpng:
(in configure.ac)
# This is because the first PKG_CHECK_MODULES call is inside a conditional.
PKG_PROG_PKG_CONFIG
AC_ARG_WITH([libpng],
[AS_HELP_STRING([--with-libpng],
[support handling png files #<:#default=check#:>#])],
[],
[with_libpng=check])
AS_CASE(["$with_libpng"],
[yes], [PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1])],
[no], [],
[PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])])
AM_CONDITIONAL([USE_LIBPNG], [test "$with_libpng" != no -a "$HAVE_LIBPNG" -eq 1])
(in Makefile.am)
if USE_LIBPNG
AM_CPPFLAGS += -DUSE_LIBPNG
AM_CFLAGS += $(libpng_CFLAGS)
LDADD += $(libpng_LIBS)
libdev_la_SOURCES += png.c
endif
If your library doesn't have a .pc file
For completeness, here's how I'd check for a library that didn't have a .pc file. I'll skip over the details of following good autoconf style. AC_CHECK_LIB sets a cache variable, so you can test that instead of replacing the ACTION-IF-FOUND of AC_CHECK_LIB:
(in configure.ac)
AC_CHECK_LIB([png], [png_create_write_struct_2])
# Then test:
AS_IF([test "$ac_cv_lib_png_png_create_write_struct_2" = yes], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])
# Or set conditional:
AM_CONDITIONAL([USE_LIBPNG], [test "$ac_cv_lib_png_png_create_write_struct_2" = yes])
IMHO, you should only do it this way if you have no other option.

I will disagree mildly with Jack on his recommendation to use PKG_CHECK_MODULES. It is probably best to avoid using that. But I will agree with Jack on avoiding assigning to LIBS in the 3rd argument to AC_CHECK_LIB. Life is easier if you let AC_CHECK_LIB use the default settings.
Although AC_CHECK_LIB does not define a shell variable indicating whether or not the library was found, you can do this in configure.ac:
AM_CONDITIONAL([USE_LIBPNG],[grep HAVE_LIBPNG confdefs.h > /dev/null])
Arguably, this is relying on internal autoconf details, but in practice will work reliably.

Thanks for the replies.
Jack: I'm trying for maximum portability, so can't assume the libraries were installed as part of a package (they're not on my own box!), which means the no-other-option solution you suggested is what I already tried-- setting a shell variable manually-- but also manually performs the extra steps that would have been done by AC_CHECK_LIB: prepending the library to LIBS and defining HAVE_LIBxxx.
There was a catch though: autoheader complains about the bare AC_DEFINE:
autoheader: warning: missing template: HAVE_LIBPNG
autoheader: Use AC_DEFINE([HAVE_LIBPNG], [], [Description])
I'd be nice if autoheader worked in the future, so I had to change AC_DEFINE to the full monty:
AC_CHECK_LIB([png], [png_create_write_struct_2],
[HAS_LIBPNG=1
LIBS="-lpng $LIBS"
AC_DEFINE([HAVE_LIBPNG], 1, [Define to 1 if you have the `png' library (-lpng)])])
This works, but I don't much like having to duplicate the default behavior of AC_CHECK_LIB.
William: Yes I could grep for the symbol definition in confdefs.h, that also works.
Both solutions have their pros and cons (what doesn't?). Not sure which way I'll go, but it's nice to have options.
Thanks again.

Related

How to check for the existence of a header of a package?

In Autoconf, when you want to check for the existence of some header, you do:
AC_CHECK_HEADERS([foo.h])
Now, let's suppose that I have some package, sponge, of which pkg-config knows, and I want to find out if it has a header named spongefoo.h.
I can do the following:
PKG_CHECK_MODULES([SPONGE])
CPPFLAGS="$CPPFLAGS $SPONGE_CFLAGS"
AC_CHECK_HEADERS([spongefoo.h])
This would work, but the Autoconf/Automake documentation says (my additions in brackets):
"Sometimes package developers are tempted to set user variables such as 'CFLAGS' [and, I add, 'CPPFLAGS'] because it appears to make their job easier. However, the package itself should never set a user variable, [...] To get around this problem, Automake introduces an automake-specific shadow variable [named AM_CPPFLAGS]"
However, AC_CHECK_HEADERS() and other test macros don't know about Automake's shadow variables.
So how do I properly check that a package has some header?
(BTW, AC_CHECK_HEADER() gets a 4'th argument, "INCLUDES", but this is a verbatim '"#include"' text, not a '"-I..."' switch, so it doesn't help me much.)
The requirement to temporarily set a user variable like CPPFLAGS to some value and run a compilation test while preserving the original value is actually done quite often. This is usually accomplished in Autoconf using a pattern similar to the following:
ac_save_CPPFLAGS=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $SPONGE_CFLAGS"
AC_CHECK_HEADERS([spongefoo.h])
CPPFLAGS=$ac_save_CPPFLAGS
Note that the ac_ shell variable prefix is informally reserved for Autoconf itself, you might want to use your own variable name like proj_save_CPPFLAGS.

AC_CHECK_LIB does not find library but compilation runs anyway

I am adding autotool support to a library project. It relies on another self-written library which is not necessarily in a default library path. So I will set LDFLAGS when configuring.
Nevertheless, I want to check for the library in order to warn the user to set LDFLAGS correctly. Therefore I put in this line:
AC_CHECK_LIB([foo], [foo_func],
[AC_DEFINE([HAVE_FOO, [1],
[Define if you have libfoo])],
[AC_MSG_WARN([libfoo not found.])])
Now, if I do not set LDFLAGS, the check fails as expected and the warning is printed. BUT: When I run make, the code compiles nevertheless, because I have the library path set in the environment variable LD_LIBRARY_PATH. I find this confusing... I would want either the check to fail and the code not to compile or the check does not fail and the code compiles.
Am I misunderstanding what AC_CHECK_LIB means or what am I doing wrong?
AC_CHECK_LIB does not care what conclusions you attach to the presence or absence of the library. It just determines whether the library is there and executes its third argument if so, and its fourth argument if not.
So getting the logic you want is up to you. If you replace AC_MSG_WARN by AC_MSG_ERROR in the fourth argument, as ldav1s suggests in the comment, then the configure script will abort if the check fails, and the code will not compile.

Automake flex output naming

If if use, for example
foo_SOURCES = bar.l
then, automake generates via flex file bar.c. But, if I provide prefix AM_LFLAGS=-Psome_prefix, it generates lex.some_prefix.c, which is not known by other
compilation rules, so it fails with bar.c: No such file or directory. Where is my mistake and how can I work around it? I really need prefix.
I think the only way around this is to write your own rule for the .l->.c translation. Something like:
x_SOURCES = lex.some_prefix.c
lex.some_prefix.c: lex.l
... rule here
You may also need a tweak to ensure you distribute the .l file.

can an RPM spec file "include" other files?

Is there a kind of "include" directive in RPM spec? I couldn't find an answer by googling.
Motivation: I have a RPM spec template which the build process modifies with the version, revision and other build-specific data. This is done by sed currently. I think it would be cleaner if the spec would #include a build-specific definitions file, which would be generated by the build process, so I don't need to search and replace in the spec.
If there is no include, is there an idiomatic way to do this (quite common, I believe) task?
Sufficiently recent versions of rpmbuild certainly do support %include:
%include common.inc
Unfortunately, they aren't very smart about it -- there is no known set of directories, in which it will look for the requested files, for example. But it is there and variables are expanded, for example:
%include %{_topdir}/Common/common.inc
RPM does not support includes.
I have solved similar problems with either m4 macro processor or by just concatenating parts of spec (when the "include" was at the beginning).
If you only need to pass a few variables at build time, and not include several lines from another file, you can run
rpmbuild --define 'myvar SOMEVALUE' -bb myspec.spec
and you can use %myvar in the spec.
I faced this same issue recently. I wanted to define multiple sub-packages that were similar, but each varied just slightly (they were language-specific RPMs). I didn't want to repeat the same boiler-plate stuff for each sub-package.
Here's a generic version of what I did:
%define foo_spec() %{expand:%(cat '%{myloc}/main-foo.spec')}
%{foo_spec bar}
%{foo_spec baz}
%{foo_spec qux}
The use of %{expand} ensures that %(cat) is only executed a single time, when the macro is defined. The content of the main-foo.spec file is then three times, and each time %1 in the main-foo.spec file expands to each of bar, baz and qux, in turn, allowing me to treat it as a template. You could easily expand this to more than one parameter, if you have the need (I did not).
For the underlying issue, there maybe two additional solutions that are present in all rpm versions that I am aware of.
Subpackages
macro and rpmrc files.
Subpackages
Another alternative (and perhaps the "RPM way") is to use sub-packages. Maximum RPM also has information and examples of subpackages.
I think the question is trying to structure something like,
two spec files; say rpm_debug.spec and rpm_production.spec
both use %include common.spec
debug and production could also be client and server, etc. For the examples of redefining a variable, each subpackage can have it's own list of variables.
Limitations
The main advantage of subpackages is that only one build takes place; This may also be a disadvantage. The debug and production example may highlight this. That can be worked around using strip to create variants or compiling twice with different output; perhaps using VPATH with Gnu Make). Having to compile large packages and then only have simple variations, like with/without developer info, like headers, static libraries, etc. can make you appreciate this approach.
Macros and Rpmrc
Subpackages don't solve the problem of structural defines that you wish for an entire rootfs hierarchy, or larger collection of RPMs. We have rpmbuild --showrc for this. You can have a large amount of variables and macros defined by altering rpmrc and macros when you run rpm and rpmbuild. From the man page,
rpmrc Configuration
/usr/lib/rpm/rpmrc
/usr/lib/rpm/redhat/rpmrc
/etc/rpmrc
~/.rpmrc
Macro Configuration
/usr/lib/rpm/macros
/usr/lib/rpm/redhat/macros
/etc/rpm/macros
~/.rpmmacros
I think these two features can solve all the problems that %include can. However, %include is a familiar concept and was probably added to make rpm more full-featured and developer friendly.
Which version are you talking about? I currently have %include filename.txt in my spec file and it seems to work just like the C #include directive.
> rpmbuild --version
RPM version 4.8.1
You can include the *.inc files from the SOURCES directory (%_sourcedir):
Source1: common.inc
%include %{SOURCE1}
In this way they will go automatically into SRPMS.
I've used scripts (name your favorite) to take a template and create the spec file from that. Also, the %files tag can import a file that is created by another process, e.g. Python's bdist-rpm.

autoconf: AC_PROG_CC checks for object and executable suffix, but how to get this?

I'm a newbie to autoconf, and found out that a call of the macro AC_PROG_CC checks for the suffixes of executables and object files. Now I want to use the results of these checks and replace them in my Makefile.in, but there is no adequate documentation or mentioning in the autoconf docs on how to use this.
I'm also having the general problem: Which macro gives me which variables, and where is a reference to get know about?
Thanks for any help.
The variables you are looking for are #EXEEXT# and #OBJEXT#.
This link takes you to the index of all the output variables from the Autoconf manual.
Unfortunately there's no easy table of which ones are defined by which macros, you just have to read the descriptions.

Resources