Hi,
AC_CHECK_SIZEOF currently does not know how to determine the value when
crosscompiling. Here is a patch which enable this. It is based on the
fact that all C and C++ compilers reject declarations of arrays with
negative size.
What the patch does, essentially, is to compile
int _array_ [1 - 2 * !(expr)];
for various boolean expressions 'expr'. Each compilation success or
failure is 1 bit of informations. To determine the sizeof(foo) == 6,
the test will try the following expressions:
sizeof(foo) >= 0 -> true
sizeof(foo) <= 0 -> false
sizeof(foo) <= 1 -> false
sizeof(foo) <= 3 -> false
sizeof(foo) <= 7 -> true
sizeof(foo) <= 5 -> false
sizeof(foo) <= 6 -> true
The sample configure.in contains three macros that would be interesting
additions for autoconf.
- AC_CHECK_EVAL_BOOL(INCLUDES, BOOLEAN-CONSTANT-EXPRESSION
[, ACTION-IF-TRUE [, ACTION-IF-FALSE]])
Evaluates a boolean constant expression.
- AC_CHECK_EVAL_INT(INCLUDES, INT-CONSTANT-EXPRESSION, VARIABLE)
Evaluates an integer constant expression, and assigns the value (in decimal)
to the shell variable VARIABLE.
- AC_CHECK_SIZEOF(TYPE)
Evaluates the sizof of a builtin type. (Sizeof of types defined in header
files can be dealt with using AC_CHECK_EVAL_INT.)
I apologize for the horrific use of 'patsubst'. It serves the purpose of
determining a reasonable cache variable for an arbitrary C expression.
The macros AC_CHECK_EVAL_BOOL_UNCACHED and AC_CHECK_EVAL_INT_UNCACHED are
auxiliary macros. Their existence permits to use the same technique with
different arguments or different AC_MSG_* messages.
Bruno
================================== sample configure.in ====================
AC_INIT(rebox-utf8.gif)
AC_CONFIG_HEADER(config.h)
AC_PROG_CC
AC_PROG_CPP
dnl AC_CHECK_EVAL_BOOL_UNCACHED(INCLUDES, BOOLEAN-CONSTANT-EXPRESSION)
define(AC_CHECK_EVAL_BOOL_UNCACHED,
[AC_TRY_COMPILE([$1
#define _expr_ $2
int _array_ [1 - 2 * !(_expr_)];
], , AC_CV_NAME=true, AC_CV_NAME=false)])
dnl AC_CHECK_EVAL_BOOL(INCLUDES, BOOLEAN-CONSTANT-EXPRESSION
dnl [, ACTION-IF-TRUE [, ACTION-IF-FALSE]])
AC_DEFUN(AC_CHECK_EVAL_BOOL,
[dnl All C/C++ compilers reject arrays with negative size.
changequote(<<, >>)dnl
dnl The cache variable name.
define(<<AC_CV_NAME>>,
<<ac_cv_eval_bool_>>dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
translit(<<$2>>,<<(),^ >>,<<{}`$>>),
<<[!]>>,<<X21>>),
<<["]>>,<<X22>>),
<<[%]>>,<<X25>>),
<<[&]>>,<<X26>>),
<<[']>>,<<X27>>),
<<[{]>>,<<X28>>),
<<[}]>>,<<X29>>),
<<[*]>>,<<X2A>>),
<<[+]>>,<<X2B>>),
<<[`]>>,<<X2C>>),
<<[-]>>,<<X2D>>),
<<[.]>>,<<X2E>>),
<<[/]>>,<<X2F>>),
<<[:]>>,<<X3A>>),
<<[<]>>,<<X3C>>),
<<[=]>>,<<X3D>>),
<<[>]>>,<<X3E>>),
<<[?]>>,<<X3F>>),
<<[$]>>,<<X5E>>),
<<[|]>>,<<X7C>>),
<<[~]>>,<<X7E>>))dnl
changequote([, ])dnl
AC_MSG_CHECKING(value of $2)
AC_CACHE_VAL(AC_CV_NAME, [AC_CHECK_EVAL_BOOL_UNCACHED([$1],[$2])])dnl
AC_MSG_RESULT($AC_CV_NAME)
if test $AC_CV_NAME = true; then
ifelse([$3], , :, [$3])
ifelse([$4], , , [else
$4
])dnl
fi
undefine([AC_CV_NAME])dnl
])
dnl AC_CHECK_EVAL_INT_UNCACHED(INCLUDES, INT-CONSTANT-EXPRESSION)
define(AC_CHECK_EVAL_INT_UNCACHED,
[if test "$cross_compiling" = yes; then
# First determine the sign, then a bound, then perform a binary search.
AC_TRY_COMPILE([$1
#define _expr_ $2
int _array_ [1 - 2 * !((_expr_) >= 0)];
], , ac_result=true, ac_result=false)
if test $ac_result = true; then
ac_lo="0"
ac_try="0"
while true; do
AC_TRY_COMPILE([$1
#define _expr_ $2
int _array_ [1 - 2 * !((_expr_) <= $ac_try)];
], , ac_result=true, ac_result=false)
if test $ac_result = true; then
ac_hi=$ac_try
break
else
ac_lo=`expr $ac_try + 1`
ac_try=`expr 2 '*' $ac_try + 1`
fi
done
else
ac_hi="-1"
ac_try="-1"
while true; do
AC_TRY_COMPILE([$1
#define _expr_ $2
int _array_ [1 - 2 * !((_expr_) >= $ac_try)];
], , ac_result=true, ac_result=false)
if test $ac_result = true; then
ac_lo=$ac_try
break
else
ac_hi=`expr $ac_try - 1`
ac_try=`expr 2 '*' $ac_try`
fi
done
fi
while test "x$ac_lo" != "x$ac_hi"; do
ac_try=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
AC_TRY_COMPILE([$1
#define _expr_ $2
int _array_ [1 - 2 * !((_expr_) <= $ac_try)];
], , ac_result=true, ac_result=false)
if test $ac_result = true; then
ac_hi=$ac_try
else
ac_lo=`expr $ac_try + 1`
fi
done
AC_CV_NAME=$ac_lo
else
AC_TRY_RUN_NATIVE([$1
int _expr_ = ($2);
#include <stdio.h>
int main ()
{
FILE *f = fopen("conftestval", "w");
if (!f) exit(1);
fprintf(f, "%d\n", _expr_);
return 0;
}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=unknown)
fi
])
dnl AC_CHECK_EVAL_INT(INCLUDES, INT-CONSTANT-EXPRESSION, VARIABLE)
AC_DEFUN(AC_CHECK_EVAL_INT,
[changequote(<<, >>)dnl
dnl The cache variable name.
define(<<AC_CV_NAME>>,
<<ac_cv_eval_int_>>dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
translit(<<$2>>,<<(),^ >>,<<{}`$>>),
<<[!]>>,<<X21>>),
<<["]>>,<<X22>>),
<<[%]>>,<<X25>>),
<<[&]>>,<<X26>>),
<<[']>>,<<X27>>),
<<[{]>>,<<X28>>),
<<[}]>>,<<X29>>),
<<[*]>>,<<X2A>>),
<<[+]>>,<<X2B>>),
<<[`]>>,<<X2C>>),
<<[-]>>,<<X2D>>),
<<[.]>>,<<X2E>>),
<<[/]>>,<<X2F>>),
<<[:]>>,<<X3A>>),
<<[<]>>,<<X3C>>),
<<[=]>>,<<X3D>>),
<<[>]>>,<<X3E>>),
<<[?]>>,<<X3F>>),
<<[$]>>,<<X5E>>),
<<[|]>>,<<X7C>>),
<<[~]>>,<<X7E>>))dnl
changequote([, ])dnl
AC_MSG_CHECKING(value of $2)
AC_CACHE_VAL(AC_CV_NAME, [AC_CHECK_EVAL_INT_UNCACHED([$1],[$2])])
AC_MSG_RESULT($AC_CV_NAME)
$3=$AC_CV_NAME
undefine([AC_CV_NAME])dnl
])
dnl AC_CHECK_SIZEOF(TYPE)
AC_DEFUN(AC_CHECK_SIZEOF,
[changequote(<<, >>)dnl
dnl The name to #define.
define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
dnl The cache variable name.
define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
changequote([, ])dnl
AC_MSG_CHECKING(size of $1)
AC_CACHE_VAL(AC_CV_NAME, [AC_CHECK_EVAL_INT_UNCACHED([], [sizeof($1)])])
AC_MSG_RESULT($AC_CV_NAME)
AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME)
undefine([AC_TYPE_NAME])dnl
undefine([AC_CV_NAME])dnl
])
dnl Examples
AC_CHECK_EVAL_BOOL([#include <stdlib.h>], [sizeof (int) < 3])
AC_CHECK_EVAL_INT([], 5 * 3, foo)
AC_CHECK_EVAL_INT([], ~17, bar)
AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(int)
AC_OUTPUT(Makefile)