Discussion:
AC_CHECK_HEADER question
Dijk, J. van
2013-03-17 16:07:44 UTC
Permalink
Dear all,

I can't imagine that I am the first to have this problem, but did
not manage to find a solution in the manual or on the Internet:
if I missed it, I apologize for that.

In our project, we are using the superlu code. On some systems, the headers are
present in <prefix>/include, on others in <prefix>/include/superlu. We therefore
#include the files without the superlu/ part, as in "#include "slu_util.h" and append
the directory <prefix>/superlu/ to the CPPFLAGS variable in our project.

How can I achieve this with autoconf? I mean: I know how to write a test like

AC_CHECK_HEADER(superlu/slu_util.h, foo, bar),

but how do I obtain (in 'foo') the path relative to which the file superlu/slu_util.h
was found? I was hoping that a variable, let's say 'header_location' is set, so
I can implement 'foo' as something like:

SUPERLU_CPPFLAGS="-I$header_location/superlu"

Is there such variable? Or can this be accomplished in a different way?

Your help is appreciated.

With kind regards,

Jan van Dijk.
Rhys Ulerich
2013-03-17 19:39:25 UTC
Permalink
Post by Dijk, J. van
How can I achieve this with autoconf? I mean: I know how to write a test like
AC_CHECK_HEADER(superlu/slu_util.h, foo, bar),
but how do I obtain (in 'foo') the path relative to which the file superlu/slu_util.h
was found?
Use the optional third and forth arguments. Run the macro several times
checking for a different prefix each time. Keep track of which one
succeeds. Fail only if all checks fail.

- Rhys
Jan van Dijk
2013-03-17 21:35:03 UTC
Permalink
Post by Rhys Ulerich
Post by Dijk, J. van
How can I achieve this with autoconf? I mean: I know how to write a test like
AC_CHECK_HEADER(superlu/slu_util.h, foo, bar),
but how do I obtain (in 'foo') the path relative to which the file
superlu/slu_util.h was found?
Use the optional third and forth arguments. Run the macro several times
checking for a different prefix each time. Keep track of which one
succeeds. Fail only if all checks fail.
Dear Rhys,

Thanks a lot for your fast reply.

That is a bit disappointing, though: it generates a lot of extra work for the
configure.ac author, only to find out what autoconf already knows: where it
could find a particular header file. It will also make the scripts less
robust.

Am I overlooking something? Is there a technical reason why that information
cannot be.communicated to the user? If not, I suppose I could file a feature
request.

Thanks again, Jan.
Peter Johansson
2013-03-17 23:39:34 UTC
Permalink
Hi Jan,
Post by Jan van Dijk
It will also make the scripts less
robust.
Am I overlooking something? Is there a technical reason why that information
cannot be.communicated to the user?
It is not known where the header file is. The configure script tests if
code which contains "#include <header.h>" compiles. If it compiles it
proves that 'header.h' exist but not *where*.


I have a similar situation in one my projects in which we use a header
file "bam.h" which is either installed in '<prefix>/include/', in
'<prefix>/include/bam/' or in '<prefix>/include/samtools'. We solve it
by having

found_bam_header=no
AC_CHECK_HEADERS([bam/bam.h bam.h samtools/bam.h],
[found_bam_header=yes; break])

in configure.ac which will AC_DEFINE HAVE_BAM_BAM_H, HAVE_BAM_H,
HAVE_SAMTOOLS_BAM_H or neither. If header is not found shell variable
found_bam_header equals "no" and one can error out based on that.

Then in you can include appropriately with something like
#if HAVE_BAM_BAM_H
#include <bam/bam.h>
#elif HAVE_BAM_H
#include <bam.h>
#elif
#include <samtools/bam.h>
#endif

or you can create a convenience header that use similar logic to #define
a macro BAM_HEADER and then have

#include "convenience.h"
#include BAM_HEADER

Hope that helps.

Peter
Post by Jan van Dijk
If not, I suppose I could file a feature
request.
Thanks again, Jan.
_______________________________________________
Autoconf mailing list
https://lists.gnu.org/mailman/listinfo/autoconf
Jan van Dijk
2013-03-18 08:20:19 UTC
Permalink
Post by Peter Johansson
Hi Jan,
Post by Jan van Dijk
It will also make the scripts less
robust.
Am I overlooking something? Is there a technical reason why that
information cannot be.communicated to the user?
It is not known where the header file is. The configure script tests if
code which contains "#include <header.h>" compiles. If it compiles it
proves that 'header.h' exist but not *where*.
I have a similar situation in one my projects in which we use a header
file "bam.h" which is either installed in '<prefix>/include/', in
'<prefix>/include/bam/' or in '<prefix>/include/samtools'. We solve it
by having
Dear Peter,

Thank you for your comments and suggestions. The problem is that the header is
included indirectly (by a third-party header) not by ourselves. So
unfortunately, this patterns does not work (without changing that third-party
code)

With kind regards,

Jan van Dijk
Zack Weinberg
2013-03-18 00:05:59 UTC
Permalink
Post by Jan van Dijk
That is a bit disappointing, though: it generates a lot of extra work for the
configure.ac author, only to find out what autoconf already knows: where it
could find a particular header file. It will also make the scripts less
robust.
Thing is, Autoconf *doesn't* know where the header is. When you do

AC_CHECK_HEADER([superlu/slu_util.h])

that gets translated to something along the lines of

printf '#include <%s>\n' 'superlu/slu_util.h' > conftest.c
if $CC $CFLAGS $CPPFLAGS -c -o conftest.o conftest.c >>config.log 2>&1
then
action-if-found
else
action-if-not-found
fi

So it's the *C compiler* that searches for the header file, and it
doesn't tell the configure script where it found it.

You could do something like this instead:

superlu_found=no
for sludir in '' 'superlu/' #...
do
AC_CHECK_HEADER([${sludir}slu_util.h],
[AC_DEFINE_UNQUOTED([SLU_SLU_UTIL_H], ["\"${sludir}slu_util.h\""],
[Define to the proper way to include slu_util.h])
AC_DEFINE_UNQUOTED([SLU_SLU_OTHER_H], ["\"${sludir}slu_other.h\""],
[Define to the proper way to include slu_other.h])
# ... all other slu headers that may be required ...
superlu_found=yes
break])
done
if test $superlu_found = no; then
AC_MSG_FAILURE([unable to find superlu headers])
fi

You then write things like

#include SLU_SLU_UTIL_H

in your code. Unfortunately, you need to define one of these macros
for _every_ SLU header you need. You might think it was possible to
write a macro that would let you do

#include SLUHDR(slu_util.h)

but it isn't (because you cannot token-paste a letter with a /).


zw
Jan van Dijk
2013-03-18 08:50:18 UTC
Permalink
Post by Zack Weinberg
Post by Jan van Dijk
That is a bit disappointing, though: it generates a lot of extra work for
where it could find a particular header file. It will also make the
scripts less robust.
Thing is, Autoconf *doesn't* know where the header is. When you do
AC_CHECK_HEADER([superlu/slu_util.h])
that gets translated to something along the lines of
printf '#include <%s>\n' 'superlu/slu_util.h' > conftest.c
if $CC $CFLAGS $CPPFLAGS -c -o conftest.o conftest.c >>config.log 2>&1
then
action-if-found
else
action-if-not-found
fi
So it's the *C compiler* that searches for the header file, and it
doesn't tell the configure script where it found it.
Dear Zack,

I guess my confusion stems from the fact that autoconf claims to check for
presence and usability separately. Indeed, I just found out that 'presence'
rather means that the file can be preprocessed. I did:

AC_CHECK_HEADER([foo.h])

where foo.h contains:

#error I do not exist

To my surprise, configure tells me that foo.h does not exist, before pointing
out that it is usable neither. Is that a documentation glitch?

Would it be possible to provide a new macro AC_WHICH_HEADER, say, which
informs it user what header has been/will be picked up by the preprocessor?
Perhaps it could use the compiler's dependency tracking system, as in:

echo "#include <math.h>" | gcc -E -M - | head -n1 | cut -f 3 -d ' '

I have no idea if this can be expressed in a sufficiently portable way that
would allow its inclusion in autoconf.
...

Thank you very much for that insightful suggestion.

With kind regards,

jan van Dijk.
Eric Blake
2013-03-18 19:05:14 UTC
Permalink
Post by Jan van Dijk
Would it be possible to provide a new macro AC_WHICH_HEADER, say, which
informs it user what header has been/will be picked up by the preprocessor?
I'm not sure that it is a common enough action to need to know where a
header lives. Knowing that a particular spelling for an include name
compiled should generally be enough.

That said, check out gnulib's m4/absolute-header.m4, which is about as
portable as you can get across multiple compilers at determining the
absolute name for any header's location, provided that header had some
non-trivial content after pre-processing (so headers like <assert.h>
cannot always be found, but headers like <stdio.h> are fair game).

http://git.sv.gnu.org/cgit/gnulib.git/tree/m4/absolute-header.m4
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
Loading...