Hi, sorry for being annoying about this -- sending this here now since I never got any response on autoconf-patches. I'd greatly appreciate if someone could have a look at my patch and tell me whether it's acceptable. I already completed the copyright assignment process. Perhaps I should provide some more detail about the use case for this change. In a nutshell: Autoconf already allows for more than one config header. This feature is useful e.g. for libraries which need to install a machine-specific configuration header that is included by the library's public header files. Apart from system configuration, this is also useful for version number defines. I've been using this scheme successfully for many years in a number of C and C++ libraries I've worked on. However, only the first configuration header passed as argument to AC_CONFIG_HEADERS() has its template generated by Autoheader. Secondary configuration headers have to use hand-written template files. This is just fine for the library use case, where it is important to tightly control the symbols put into the installed config header, since user code will be indirectly exposed to it. So all would be just fine if it weren't for the problem that Autoheader doesn't really handle the situation correctly. In order to appease Autoheader's sanity checking (which cannot be disabled), it is currently necessary to use the three-argument version of AC_DEFINE() even for defines which already appear in a manually written header template file. Using the three-argument AC_DEFINE() of course also means that the define is duplicated into the first config header, too. Even so it is still usable, and I've lived with that problem for years. However, I've recently run into a situation which prompted me to create this patch to fix Autoheader. The issue is with auto-generated version defines, which may include a git revision hash and thus change with every commit. Due to the duplication of all defines into the first configuration header, which is included by every source file in the project, this causes the entire project to be rebuild on every change. If the version defines could be limited to the secondary config header, the dependencies could be contained and the need to rebuild minimized. Incidentally, the goal to reduce rebuilds is also the reason why a proper configuration header is preferable over using AC_SUBST for this, since the latter mechanism does not have the update-avoiding check for changed content. Long story short, my patch makes Autoheader behave like it probably should have from the beginning. That is, the hand-written template files of secondary config headers are considered during the sanity check whether all defines have a corresponding template. This makes it possible to use the two-argument version of AC_DEFINE() for defines with a hand-written template, thereby avoiding the spill into the first config header. This change should have no effect on existing code. Is this acceptable? I'd be delighted if it could be part of the next release. Cheers, --Daniel * bin/autoheader.in: When checking for missing templates, take all config headers into account, not just the one generated by autoheader. This makes it possible to use AC_DEFINE() for secondary headers without duplicating the template into the first header. * tests/tools.at: Add a check for autoheader with multiple config headers. * NEWS: Document the new behavior. --- NEWS | 5 +++++ bin/autoheader.in | 37 ++++++++++++++++++++++++++----------- tests/tools.at | 25 +++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index f691179..ceda4a0 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,11 @@ GNU Autoconf NEWS - User visible changes. is now deprecated. If you really need that behavior use AC_PREPROC_IFELSE. +** When checking for missing templates, autoheader now takes any + templates defined in the inputs of secondary config headers into + account. This makes it possible to use AC_DEFINE for secondary + headers without duplicating the template in the main config header. + ** Macros - New macro AC_C__GENERIC. diff --git a/bin/autoheader.in b/bin/autoheader.in index 8c70663..fe06774 100644 --- a/bin/autoheader.in +++ b/bin/autoheader.in @@ -191,11 +191,21 @@ unless ($config_h) exit 1; } -# We template only the first CONFIG_HEADER. -$config_h =~ s/ .*//; # Support "outfile[:infile]", defaulting infile="outfile.in". -($config_h, $config_h_in) = split (':', $config_h, 2); -$config_h_in ||= "$config_h.in"; +sub templates_for_header ($) +{ + my ($spec) = @_; + my ($header, @templates) = split(':', $spec); + + return @templates if (@templates); + return $header . '.in'; +} + +my @config_templates = map(templates_for_header($_), split(' ', $config_h)); + +# We template only the first CONFIG_HEADER. +$config_h_in = shift(@config_templates); +$config_h =~ s/[ :].*//; # %SYMBOL might contain things like 'F77_FUNC(name,NAME)', but we keep # only the name of the macro. @@ -261,14 +271,20 @@ $out->close; # Check that all the symbols have a template. { - my $in = new Autom4te::XFile ("< " . open_quote ("$tmp/config.hin")); - my $suggest_ac_define = 1; - while ($_ = $in->getline) + foreach my $template ("$tmp/config.hin", @config_templates) { - my ($symbol) = /^\#\s*\w+\s+(\w+)/ - or next; - delete $symbol{$symbol}; + my $in = new Autom4te::XFile ("< " . open_quote ($template)); + + while ($_ = $in->getline) + { + my ($sym) = /^\#\s*\w+\s+(\w+)/ + or next; + delete $symbol{$sym}; + } } + + my $suggest_ac_define = 1; + foreach (sort keys %symbol) { msg 'syntax', "warning: missing template: $_"; @@ -277,7 +293,6 @@ $out->close; msg 'syntax', "Use AC_DEFINE([$_], [], [Description])"; $suggest_ac_define = 0; } - } exit 1 if keys %symbol; diff --git a/tests/tools.at b/tests/tools.at index 24173c9..d5a919c 100644 --- a/tests/tools.at +++ b/tests/tools.at @@ -860,6 +860,31 @@ config.h.in:0 AT_CLEANUP +# autoheader should take all config header inputs into account when +# checking for missing templates. +AT_SETUP([autoheader with multiple headers]) + +AT_DATA([config-extra.h.in], +[[/* Define this to whatever you want. */ +#undef HANNA +]]) +AT_DATA([configure.ac], +[[AC_INIT +AC_CONFIG_HEADERS([config.h config-extra.h]) +AC_DEFINE([HANNA], ["Hanna"]) +AC_DEFINE([SEAN], ["Sean"], [Sean's name]) +AC_OUTPUT +]]) + +AT_CHECK_AUTOCONF +AT_CHECK_AUTOHEADER +AT_CHECK([grep HANNA configure], [0], [ignore], [ignore]) +AT_CHECK([grep HANNA config.h.in], [1], [ignore], [ignore]) +AT_CHECK([grep SEAN configure], [0], [ignore], [ignore]) +AT_CHECK([grep SEAN config.h.in], [0], [ignore], [ignore]) + +AT_CLEANUP + ## ------------ ## _______________________________________________ Autoconf mailing list Autoconf@xxxxxxx https://lists.gnu.org/mailman/listinfo/autoconf