mirror of
git://git.sv.gnu.org/autoconf
synced 2025-01-30 11:01:45 +08:00
416 lines
12 KiB
Perl
416 lines
12 KiB
Perl
#! /usr/bin/perl
|
|
|
|
# Build some of the Autoconf test files.
|
|
|
|
# Copyright (C) 2000-2017, 2020-2021 Free Software Foundation, Inc.
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
use 5.006;
|
|
use strict;
|
|
use warnings FATAL => 'all';
|
|
|
|
# ac_exclude_list
|
|
# ---------------
|
|
# Check all AC_DEFUN'ed macros with AT_CHECK_MACRO, except these.
|
|
# Not every macro can be run without arguments, and some are already
|
|
# tested elsewhere.
|
|
my @ac_exclude_list = (
|
|
# Internal macros should not be invoked directly from a configure.ac.
|
|
qr/^_?_AC_/,
|
|
|
|
# Used in many places.
|
|
qr/^AC_.*_IFELSE$/,
|
|
qr/^AC_LANG/,
|
|
qr/^AC_RUN_LOG$/,
|
|
qr/^AC_TRY/,
|
|
|
|
# Need an argument.
|
|
qr/^AC_(CANONICALIZE|PREFIX_PROGRAM|PREREQ)$/,
|
|
qr/^AC_(SEARCH_LIBS|REPLACE_FUNCS)$/,
|
|
qr/^AC_(CACHE_CHECK|COMPUTE)_INT$/,
|
|
qr/^AC_ARG_VAR$/,
|
|
qr/^AC_REQUIRE_SHELL_FN$/,
|
|
|
|
# Performed in the semantics tests.
|
|
qr/^AC_CHECK_(
|
|
ALIGNOF|DECL|FILE|FUNC|HEADER|LIB|MEMBER
|
|
|PROG|SIZEOF|(TARGET_)?TOOL|TYPE
|
|
)S?$/x,
|
|
qr/^AC_PATH_PROGS_FEATURE_CHECK$/,
|
|
|
|
# Fail when the source does not exist.
|
|
qr/^AC_CONFIG/,
|
|
|
|
# AU defined to nothing.
|
|
qr/^AC_(CYGWIN|CYGWIN32|EMXOS2|MING32|EXEEXT|OBJEXT)$/,
|
|
|
|
# Produce "= val" because $1, the variable used to store the result,
|
|
# is empty.
|
|
qr/^AC_(F77|FC)_FUNC$/,
|
|
qr/^AC_FC_(PP_)?SRCEXT$/,
|
|
qr/^AC_PATH_((TARGET_)?TOOL|PROG)S?$/,
|
|
|
|
# Is a number.
|
|
qr/^AC_FD_CC$/,
|
|
|
|
# Obsolete, but needs to be AC_DEFUNed and cannot safely be called
|
|
# without arguments. Tested in tools.at.
|
|
qr/^AC_(DIAGNOSE|FATAL|FOREACH|OBSOLETE|WARNING)$/,
|
|
|
|
# Require a file that is not shipped with Autoconf. But it should.
|
|
qr/^AC_FUNC_(GETLOADAVG|FNMATCH_GNU)$/,
|
|
qr/^AC_REPLACE_FNMATCH$/,
|
|
|
|
# Obsolete, checked in semantics.
|
|
qr/^AC_FUNC_WAIT3$/,
|
|
qr/^AC_FUNC_SETVBUF_REVERSED$/,
|
|
qr/^AC_SYS_RESTARTABLE_SYSCALLS$/,
|
|
|
|
# Not intended to be invoked at the top level.
|
|
qr/^AC_INCLUDES_DEFAULT$/,
|
|
|
|
# AC_INIT includes all the AC_INIT macros.
|
|
# There is an infinite m4 recursion if AC_INIT is used twice.
|
|
qr/^AC_INIT/,
|
|
|
|
# Checked in semantics.
|
|
qr/^AC_(PROG_CC|C_CONST|C_VOLATILE)$/,
|
|
qr/^AC_PATH_XTRA$/,
|
|
|
|
# Use without an argument is obsolete.
|
|
# Checked in semantics.
|
|
qr/^AC_PROG_LEX$/,
|
|
|
|
# Requires a working C++ compiler, which is not a given.
|
|
qr/^AC_PROG_CXX_C_O$/,
|
|
|
|
# Already tested by AT_CHECK_MACRO.
|
|
qr/^AC_OUTPUT$/,
|
|
|
|
# Tested alongside m4_divert_text.
|
|
qr/^AC_PRESERVE_HELP_ORDER$/,
|
|
|
|
# Tested in erlang.at.
|
|
qr/^AC_ERLANG_SUBST_(INSTALL_LIB_SUBDIR|ROOT_DIR)$/,
|
|
qr/^AC_ERLANG_CHECK_LIB$/,
|
|
);
|
|
|
|
# au_exclude_list
|
|
# ---------------
|
|
# Check all AU_DEFUN'ed macros with AT_CHECK_AU_MACRO, except these.
|
|
my @au_exclude_list = (
|
|
# Empty.
|
|
qr/^AC_(C_CROSS|PROG_CC_(C[89]9|STDC))$/,
|
|
|
|
# Use AC_REQUIRE.
|
|
qr/^AC_(CYGWIN|MINGW32|EMXOS2)$/,
|
|
|
|
# Already in configure.ac.
|
|
qr/^AC_(INIT|OUTPUT)$/,
|
|
|
|
# AC_LANG_SAVE needs user interaction to be removed.
|
|
# AC_LANG_RESTORE cannot be used alone.
|
|
qr/^AC_LANG_(SAVE|RESTORE)$/,
|
|
|
|
# Need arguments. Tested in tools.at.
|
|
qr/^AC_(DIAGNOSE|FATAL|OBSOLETE|WARNING)$/,
|
|
qr/^AC_(FOREACH|LINK_FILES|PREREQ)$/,
|
|
|
|
# Need arguments. Tested in semantics.at.
|
|
qr/^AC_HAVE_LIBRARY$/,
|
|
qr/^AC_COMPILE_CHECK$/,
|
|
qr/^AC_TRY_(COMPILE|CPP|LINK|RUN)$/,
|
|
|
|
# Not macros, just mapping from old variable name to a new one.
|
|
qr/^ac_cv_prog_(gcc|gxx|g77)$/,
|
|
);
|
|
|
|
|
|
# test_parameters
|
|
# ---------------
|
|
# Extra arguments to pass to the test macro for particular macros.
|
|
# Keys are macro names, values are records containing one or more
|
|
# of the possible optional arguments to AT_CHECK_(AU_)MACRO:
|
|
# macro_use, additional_commands, autoconf_flags, test_parameters => '...'.
|
|
# Entries in this hash are grouped by common situations, and sorted
|
|
# alphabetically within each group.
|
|
# Note that you must provide M4 quotation; emit_test will not quote
|
|
# the arguments for you. (This is so you can _not_ quote the arguments
|
|
# when that's useful.)
|
|
|
|
my %test_parameters = (
|
|
# Uses AC_RUN_IFELSE, cross-compilation test fails.
|
|
AC_FC_CHECK_BOUNDS => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_CHOWN => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_FNMATCH => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_FORK => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_GETGROUPS => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_LSTAT => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_MALLOC => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_MEMCMP => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_MKTIME => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_MMAP => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_REALLOC => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_STAT => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_STRCOLL => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_STRNLEN => { test_parameters => '[no-cross]' },
|
|
AC_FUNC_STRTOD => { test_parameters => '[no-cross]' },
|
|
|
|
# Different result with a C++ compiler than a C compiler:
|
|
# C++ compilers may or may not support these features from C1999 and later.
|
|
AC_C_RESTRICT => {
|
|
test_parameters => ('[cxx_define_varies:restrict' .
|
|
' cxx_cv_varies:cxx_restrict]')
|
|
},
|
|
AC_C_TYPEOF => {
|
|
test_parameters => ('[cxx_define_varies:typeof' .
|
|
' cxx_define_varies:HAVE_TYPEOF' .
|
|
' cxx_cv_varies:cxx_typeof]')
|
|
},
|
|
AC_C__GENERIC => {
|
|
test_parameters => ('[cxx_define_varies:HAVE_C__GENERIC' .
|
|
' cxx_cv_varies:cxx__Generic]')
|
|
},
|
|
AC_C_VARARRAYS => {
|
|
test_parameters => ('[cxx_define_varies:HAVE_C_VARARRAYS' .
|
|
' cxx_define_varies:__STDC_NO_VLA__' .
|
|
' cxx_cv_varies:cxx_vararrays]')
|
|
},
|
|
|
|
# stdbool.h is supposed to be includeable from C++, per C++2011
|
|
# [support.runtime], but the type _Bool was not added to the C++
|
|
# standard, so it may or may not be present depending on how much
|
|
# the C++ compiler cares about C source compatibility.
|
|
AC_CHECK_HEADER_STDBOOL => {
|
|
test_parameters => ('[cxx_define_varies:HAVE__BOOL' .
|
|
' cxx_cv_varies:type__Bool]')
|
|
},
|
|
AC_HEADER_STDBOOL => {
|
|
test_parameters => ('[cxx_define_varies:HAVE__BOOL' .
|
|
' cxx_cv_varies:type__Bool]')
|
|
},
|
|
|
|
# G++ forces -D_GNU_SOURCE which, with some versions of GNU libc,
|
|
# changes the declaration of strerror_r. Blech.
|
|
AC_FUNC_STRERROR_R => {
|
|
test_parameters => ('[cxx_define_varies:STRERROR_R_CHAR_P' .
|
|
' cxx_cv_varies:func_strerror_r_char_p]')
|
|
},
|
|
);
|
|
|
|
# skip_macro MACRO, EXCLUDE-LIST
|
|
# ------------------------------
|
|
# Returns truthy if any of the regexes in EXCLUDE-LIST match MACRO.
|
|
sub skip_macro
|
|
{
|
|
my $macro = shift;
|
|
for my $pat (@_)
|
|
{
|
|
return 1 if $macro =~ $pat;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
# emit_test FH, TEST-MACRO, MACRO
|
|
# --------------------------------
|
|
# Emit code to FH to test MACRO using TEST-MACRO.
|
|
# TEST-MACRO is expected to be either AT_CHECK_MACRO or AT_CHECK_AU_MACRO;
|
|
# see local.at.
|
|
sub emit_test
|
|
{
|
|
my ($fh, $test_macro, $macro) = @_;
|
|
my $params = $test_parameters{$macro} || {};
|
|
my $macro_use = ${$params}{macro_use} || '';
|
|
my $additional_commands = ${$params}{additional_commands} || '';
|
|
my $autoconf_flags = ${$params}{autoconf_flags} || '';
|
|
my $test_parameters = ${$params}{test_parameters} || '';
|
|
|
|
$autoconf_flags = '[]'
|
|
if $autoconf_flags eq '' && $test_parameters ne '';
|
|
$additional_commands = '[]'
|
|
if $additional_commands eq '' && $autoconf_flags ne '';
|
|
$macro_use = '[]'
|
|
if $macro_use eq '' && $additional_commands ne '';
|
|
|
|
print $fh "$test_macro([$macro]";
|
|
print $fh ", $autoconf_flags" if $autoconf_flags ne '';
|
|
print $fh ", $additional_commands" if $additional_commands ne '';
|
|
print $fh ", $autoconf_flags" if $autoconf_flags ne '';
|
|
print $fh ", $test_parameters" if $test_parameters ne '';
|
|
print $fh ")\n";
|
|
}
|
|
|
|
# scan_m4_files
|
|
# -------------
|
|
# Scan all of the Autoconf source files and produce lists of macros
|
|
# to be tested
|
|
sub scan_m4_files
|
|
{
|
|
my @macros_to_test;
|
|
my %required_macros;
|
|
|
|
for my $file (@_)
|
|
{
|
|
open my $fh, "<", $file
|
|
or die "$file: $!\n";
|
|
|
|
my (@ac_macros, @au_macros);
|
|
while (<$fh>)
|
|
{
|
|
chomp;
|
|
s/\bdnl\b.*$//;
|
|
if (/\bAC_REQUIRE\(\[*([a-zA-Z0-9_]+)/)
|
|
{
|
|
$required_macros{$1} = 1;
|
|
}
|
|
elsif (/^AC_DEFUN(?:_ONCE)?\(\[*([a-zA-Z0-9_]+)/)
|
|
{
|
|
push @ac_macros, $1
|
|
unless skip_macro $1, @ac_exclude_list;
|
|
}
|
|
elsif (/^AU_DEFUN?\(\[*([a-zA-Z0-9_]+)/)
|
|
{
|
|
push @au_macros, $1
|
|
unless skip_macro $1, @au_exclude_list;
|
|
}
|
|
}
|
|
push @macros_to_test, [ $file, \@ac_macros, \@au_macros ];
|
|
}
|
|
|
|
# Filter out macros that are AC_REQUIREd by some other macro;
|
|
# it's not necessary to test them directly.
|
|
my @pruned_macros_to_test;
|
|
for my $elt (@macros_to_test)
|
|
{
|
|
my ($file, $ac_macros, $au_macros) = @$elt;
|
|
my (@pruned_ac_macros, @pruned_au_macros);
|
|
|
|
for my $macro (@$ac_macros)
|
|
{
|
|
push @pruned_ac_macros, $macro
|
|
unless defined $required_macros{$macro};
|
|
}
|
|
for my $macro (@$au_macros)
|
|
{
|
|
push @pruned_au_macros, $macro
|
|
unless defined $required_macros{$macro};
|
|
}
|
|
|
|
push @pruned_macros_to_test, [
|
|
$file, \@pruned_ac_macros, \@pruned_au_macros
|
|
];
|
|
}
|
|
|
|
return @pruned_macros_to_test;
|
|
}
|
|
|
|
|
|
# make_read_only FILE
|
|
# -------------------
|
|
# Make FILE read-only on disk. Also clears the execute and special bits.
|
|
sub make_read_only
|
|
{
|
|
my $f = shift;
|
|
my $mode = (stat $f)[2];
|
|
die "stat($f): $!\n" unless defined $mode;
|
|
# clear all the bits in $mode except r--r--r--
|
|
$mode &= 00444;
|
|
chmod $mode, $f or die "making $f read-only: $!\n";
|
|
}
|
|
|
|
|
|
# create_test_files OUTDIR, M4-FILES...
|
|
# -----------------
|
|
# Main loop: for each file listed in M4-FILES, generate an .at file
|
|
# named "ac${file}.at" that does cursory tests on each of the macros
|
|
# defined in $file.
|
|
sub create_test_files
|
|
{
|
|
my $outdir = shift;
|
|
if (@_ == 0)
|
|
{
|
|
print STDERR "usage: $0 outdir m4-files...\n";
|
|
exit 1;
|
|
}
|
|
|
|
for my $elt (scan_m4_files @_)
|
|
{
|
|
my ($file, $ac_macros, $au_macros) = @$elt;
|
|
|
|
my $base = $file;
|
|
$base =~ s|^.*/([^/.]+)(?:.[^/]*)?$|$1|;
|
|
|
|
my $tmpout = "${outdir}/ac${base}.tat";
|
|
my $out = "${outdir}/ac${base}.at";
|
|
|
|
open my $fh, ">", $tmpout
|
|
or die "$tmpout: $!\n";
|
|
|
|
print $fh <<"EOF";
|
|
# -*- autotest -*-
|
|
# Generated by $0 from $file.
|
|
# Do not edit this file by hand.
|
|
|
|
EOF
|
|
|
|
if (@$ac_macros || @$au_macros)
|
|
{
|
|
print $fh "AT_BANNER([Testing autoconf/$base macros.])\n";
|
|
|
|
if (@$ac_macros)
|
|
{
|
|
print $fh "\n# Modern macros.\n";
|
|
emit_test ($fh, 'AT_CHECK_MACRO', $_)
|
|
for sort @$ac_macros;
|
|
}
|
|
if (@$au_macros)
|
|
{
|
|
print $fh "\n# Obsolete macros.\n";
|
|
emit_test ($fh, 'AT_CHECK_AU_MACRO', $_)
|
|
for sort @$au_macros;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
print $fh "# Nothing to test.\n";
|
|
}
|
|
|
|
close $fh or die "writing to $tmpout: $!\n";
|
|
make_read_only $tmpout;
|
|
rename $tmpout, $out or die "updating $out: $!\n";
|
|
}
|
|
}
|
|
|
|
create_test_files @ARGV;
|
|
exit 0;
|
|
|
|
### Setup "GNU" style for perl-mode and cperl-mode.
|
|
## Local Variables:
|
|
## perl-indent-level: 2
|
|
## perl-continued-statement-offset: 2
|
|
## perl-continued-brace-offset: 0
|
|
## perl-brace-offset: 0
|
|
## perl-brace-imaginary-offset: 0
|
|
## perl-label-offset: -2
|
|
## cperl-indent-level: 2
|
|
## cperl-brace-offset: 0
|
|
## cperl-continued-brace-offset: 0
|
|
## cperl-label-offset: -2
|
|
## cperl-extra-newline-before-brace: t
|
|
## cperl-merge-trailing-else: nil
|
|
## cperl-continued-statement-offset: 2
|
|
## End:
|