Discussion:
How to write directly to config.h from configure?
Jeffrey Walton
2018-07-26 15:36:47 UTC
Permalink
Hi Everyone,

I have a bad interaction with a project and Autotools. The project is
not an Autotools project but we are trying to [cleanly] support
Autotools. The project provides its own config.h since the mid-1990's.
We want to supply roughly the same file though Autotools.

The problem is, the project's config.h has some stuff that does not
seem to fit in the Autotools model like typedefs and declarations of
namespaces. I think the solution is to write directly to config.h but
I can't figure out how to do it. Testing code like below is lost
(i.e., it is not in the resulting config.h):

## Some real autoconf tests...

cat << EOT >> config.h
typedef unsigned char byte;
typedef unsigned short word16;
typedef unsigned int word32;
EOT

## Back to real autoconf tests...

Is it possible to write directly to config.h? If yes, then how do I do it?

Jeff
Zack Weinberg
2018-07-26 15:53:40 UTC
Permalink
On Thu, Jul 26, 2018 at 11:36 AM, Jeffrey Walton <***@gmail.com> wrote:
...
Post by Jeffrey Walton
The problem is, the project's config.h has some stuff that does not
seem to fit in the Autotools model like typedefs and declarations of
namespaces. I think the solution is to write directly to config.h but
I can't figure out how to do it. Testing code like below is lost
## Some real autoconf tests...
cat << EOT >> config.h
typedef unsigned char byte;
typedef unsigned short word16;
typedef unsigned int word32;
EOT
## Back to real autoconf tests...
Is it possible to write directly to config.h? If yes, then how do I do it?
I don't think there's any way to _conditionally_ include a block of
code in the generated config.h. If the test can be restructured into
an appropriate form, you could do something like this:

if test $ac_cv_whatever = yes; then
AC_DEFINE([TYPESIZES_C8_S16_I32]
fi
AH_VERBATIM([TYPESIZES_B8_S16_I32_COND],
[#ifdef TYPESIZES_C8_S16_I32_COND
typedef unsigned char byte;
typedef unsigned short word16;
typedef unsigned int word32;
#endif
])

Also, AC_DEFINE_UNQUOTED may be useful.
Nick Bowler
2018-07-26 15:55:32 UTC
Permalink
Post by Jeffrey Walton
I have a bad interaction with a project and Autotools. The project is
not an Autotools project but we are trying to [cleanly] support
Autotools. The project provides its own config.h since the mid-1990's.
We want to supply roughly the same file though Autotools.
The problem is, the project's config.h has some stuff that does not
seem to fit in the Autotools model like typedefs and declarations of
namespaces. I think the solution is to write directly to config.h but
I can't figure out how to do it. Testing code like below is lost
The only thing configure (actually, config.status) does is replace
#undef lines in the package-provided config.h.in with either a #define
or a comment, based on configure results controlled by the AC_DEFINE
macro.

You can essentially to place any code you'd like in config.h.in, with
some limitations, see "Configuration Header Templates" in the Autoconf
manual[1].
Post by Jeffrey Walton
Is it possible to write directly to config.h? If yes, then how do I do it?
Configure just copies anything it doesn't recognize (i.e. anything other
than recognized #undef lines) from config.h.in to config.h.

If you are generating config.h.in using autoheader, then the AH_TOP and
AH_BOTTOM macros might be of interest.

[1] https://www.gnu.org/software/autoconf/manual/autoconf.html#Header-Templates

Hope that helps,
Nick
Jeffrey Walton
2018-07-29 00:36:51 UTC
Permalink
Post by Nick Bowler
Post by Jeffrey Walton
I have a bad interaction with a project and Autotools. The project is
not an Autotools project but we are trying to [cleanly] support
Autotools. The project provides its own config.h since the mid-1990's.
We want to supply roughly the same file though Autotools.
The problem is, the project's config.h has some stuff that does not
seem to fit in the Autotools model like typedefs and declarations of
namespaces. I think the solution is to write directly to config.h but
I can't figure out how to do it. Testing code like below is lost
The only thing configure (actually, config.status) does is replace
#undef lines in the package-provided config.h.in with either a #define
or a comment, based on configure results controlled by the AC_DEFINE
macro.
You can essentially to place any code you'd like in config.h.in, with
some limitations, see "Configuration Header Templates" in the Autoconf
manual[1].
Thanks everyone.

I believe config.h.in is a dead-end for us. I tried it in the past.
Also see https://stackoverflow.com/q/48436715/608639 .

Jeff

Eric Blake
2018-07-26 16:00:26 UTC
Permalink
Post by Jeffrey Walton
Hi Everyone,
I have a bad interaction with a project and Autotools. The project is
not an Autotools project but we are trying to [cleanly] support
Autotools. The project provides its own config.h since the mid-1990's.
We want to supply roughly the same file though Autotools.
The problem is, the project's config.h has some stuff that does not
seem to fit in the Autotools model like typedefs and declarations of
namespaces. I think the solution is to write directly to config.h but
I can't figure out how to do it. Testing code like below is lost
## Some real autoconf tests...
cat << EOT >> config.h
typedef unsigned char byte;
typedef unsigned short word16;
typedef unsigned int word32;
EOT
## Back to real autoconf tests...
Is it possible to write directly to config.h? If yes, then how do I do it?
Sort of. It's possible to use AH_VERBATIM() to put almost-arbitrary text
into the config.h file, with the caveat that '#undef' within that text
is still a magic sequence that gets turned into a comment or #define as
needed. For example, from autoconf itself:

AC_DEFUN([AC_C_BIGENDIAN],
[AH_VERBATIM([WORDS_BIGENDIAN],
[/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif])dnl
AC_CACHE_CHECK([whether byte ordering is bigendian], [ac_cv_c_bigendian],
...

which results in a verbatim chunk of code in config.h where only one
line (third from the bottom) is later rewritten by AC_DEFINE, but where
the logic flow of the preprocessor doesn't care about the rewritten line
on Apple universal builds.

In your case, it looks like you'd do:

AH_VERBATIM([MY_TYPEDEFS], [[
typedef unsigned char byte;
typedef unsigned short word16;
typedef unsigned int word32;
]])

(where MY_TYPEDEFS is replaced by whatever name you desire, although it
should be prefixed to your project to avoid collisions)
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
Warren Young
2018-07-26 17:20:06 UTC
Permalink
Post by Jeffrey Walton
cat << EOT >> config.h
typedef unsigned char byte;
typedef unsigned short word16;
typedef unsigned int word32;
EOT
You’re reinventing C99’s stdint.h here. Unless you still must build on C89 or older compilers, you should just switch.

I get supporting old compilers — I often need to support C++ compilers 10 years old or more — but C89 should be safe to drop in most projects by now.
Jeffrey Walton
2018-07-26 17:26:50 UTC
Permalink
Post by Warren Young
Post by Jeffrey Walton
cat << EOT >> config.h
typedef unsigned char byte;
typedef unsigned short word16;
typedef unsigned int word32;
EOT
You’re reinventing C99’s stdint.h here. Unless you still must build on C89 or older compilers, you should just switch.
I get supporting old compilers — I often need to support C++ compilers 10 years old or more — but C89 should be safe to drop in most projects by now.
Yeah, we changed minimum requirements to C++03 recently (from C++98).
The problem is we risk breaking user code, especially on Windows
platforms where <stdint.h> or <cstdint> did not arrive until about
2010.

Breaking user code means mailing list questions and bug reports. I
prefer a silent and dark cockpits so I think its best to leave the
cruft.

Jeff
Paul Eggert
2018-07-26 17:42:20 UTC
Permalink
Post by Jeffrey Walton
The problem is we risk breaking user code, especially on Windows
platforms where <stdint.h> or <cstdint> did not arrive until about
2010.
Gnulib's stdint.h module solves this. Use it, and the rest of your code
can just use "#include <stdint.h>".

https://www.gnu.org/software/gnulib/manual/html_node/stdint_002eh.html
Bob Friesenhahn
2018-07-26 19:32:49 UTC
Permalink
Post by Jeffrey Walton
Yeah, we changed minimum requirements to C++03 recently (from C++98).
The problem is we risk breaking user code, especially on Windows
platforms where <stdint.h> or <cstdint> did not arrive until about
2010.
Using <inttypes.h> is more portable than <stdint.h> since it was
defined earlier.

It is easy to conflate the compiler with the system header files. On
Unix type systems, often inttypes.h or stdint.h comes from system
header files rather than the compiler. For Microsoft Windows, the
header likely comes from the SDK, which is mostly independent of the
OS version.

It all comes down to if you choose to abandon a portion of potential
users (typically non GNU-Linux) for the sake of convenience. I have
not decided to do that yet since it has not proven difficult to
support old compilers and systems even dating from the late '90s.

Bob
--
Bob Friesenhahn
***@simple.dallas.tx.us, http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer, http://www.GraphicsMagick.org/
Loading...