This is a step-by-step description howto turn your own configure
check into an autoconf macro - this text tells about the ways to
polish the script into a shiny piece that you will really feel
like showing them on the Autoconf Macro Archive.
We suppose you have written a small check already used in your "configure"
script - which is actually a bourne shell script that calls other
tools and possibly sets an AC_SUBST variable to be replaced in your
Makefile.in. It may look like the following check for a "gnu make" in
the build environment:
make_command=""
for a in "$MAKE" make gmake gnumake
do test -z "$a" && continue
if ( sh -c "$a --version" 2>/dev/null | grep GNU >/dev/null )
then make_command=$a ; break;
fi
done
if test -z $make_command
then ifGNUmake=""
else ifGNUmake="#"
fi
AC_SUBST(ifGNUmake)
In the first step, one would extract that part from the "configure"
script and put it into its own file. For a first test, please use
the "acinclude.m4" file. The next call of `aclocal && autoconf`
will copy the new macro to "aclocal.m4" and from there to "configure".
So, now you have an extra file "acinclude.m4" reading:
AC_DEFUN(CHECK_GNU,[
make_command=""
for a in "$MAKE" make gmake gnumake
do test -z "$a" && continue
if ( sh -c "$a --version" 2>/dev/null | grep GNU >/dev/null )
then make_command=$a ; break;
fi
done
if test -n $make_command
then ifGNUmake=""
else ifGNUmake="#"
fi
AC_SUBST(ifGNUmake)
])
and in its place in the original "configure.in" you write that
name as:
....
CHECK_GNU
...
Now you are already done with having your own autoconf macro. And you
can be quite sure that it will work in your project - and probably
you have tested it on the platforms you do usually build for. Believe
it or not, this is a rather "controlled" environment - if you push the
macro to the Autoconf Macro Archive then your macro might make it into
other projects where they will meet lots of other macros, lots of other
shell code, lots of different platforms. And possibly, it will fail
over there - however there are some steps that can be checked before.
- add m4-quotings - AC_DEFUN([CHECK_GNU])
-
In the wild, your "CHECK_GNU" might have been already defined elsewhere.
It is perfectly possible to redefine a macro but only if AC_DEFUN
will see the name. Without the m4-quotes "[...]" however, the
predefined macro CHECK_GNU will be expandend before. In many
many cases it results in "syntax errors" occuring near your usage of
CHECK_GNU and they are not telling about a redefine problem at all.
It is really hard to get after that one.
-
- add m4-quotings - AC_SUBST([ifGNUmake])
-
For the same reason, you should put m4-quotes in any other places
where actually an m4-macro is being created - or possibly you are
going to use a symbol that might be a complex macro. As a rule of
thumb, all uppercase-symbols might be defined as a macro somewhere
else. Please put all of them into m4-quotes "[...]". By the way, if
you need a pair of "[..]" to be output to the "configure" script,
just double (or triple) them as "[[...]]".
-
- var-settings need doublequotes - make_command="$a"
-
Most people forget about a problem here - if there is a single space
between the "=" and anything to follow then the righthand side will be
executed as a command and the return value of that command gets assigned.
In other words, 'a="echo foo" ; var= $a' will not set "$var" to
"foo" but instead print "foo" to the user screen. Putting
doublequotes around the righthand side will ensure it gets never ever
executed errornously. If you really want to get the execution value,
then use backticks to express just that: 'a=`echo foo`'.
-
- test emptyness as : test "x$var" = "x"
-
The "test" command happens to be implemented very very differently on
the various platforms, in fact it is mostly a builtin to the shell you
happen to have your configure script get executed with. While "-z" is
seen often, even "-n" is rarely implemented. Even more, there are some
buggy shells which remove an empty "" string completely instead of
providing an empty argument to the "test" command, so that "test" would
see a 'test "$var" = ""' as a real 'test =' - and ask for a syntax error.
-
- use cache variables - _cv_make_command
-
Your macro might be used by other macros which get each expanded into
the final "configure" script. That will make your check code to be
executed multiple times. Not necessary, and for a compile-and-run
test it would be very time consuming. Also, the cache-variables allow
a packager guru to pre-set the check-result, yielding faster "configure"
and allows to handle problems with cross-compile setups. The configure
script will automatically save-to-cache all shell variables containing
a "_cv_" in the name.
-
- use AC_MSG_RESULT - after AC_MSG_CHECKING / AC_CACHE_CHECK
-
Inform the user when the "configure" script enters your macro and
when it leaves your macro. If there are problems, they can be identified
faster - remember that an extra autoconf macro file is in a distant
place perhaps and the original "configure.ac" has only a macro name,
and possibly not even your macro name but a different one that
happens to use your macro in its definition. At best, inform
the user of the result - and try to avoid terminology that is not
helpful to a non-coder.
-
- don't be afraid of long names - use AS_VAR_PUSHDEF / POPDEF
-
You should avoid to destroy shell variable values possibly used
somewhere else - or the ones of the other macro calling your macro.
As for short-lived variables that do not span over other macros,
just use very short names - for the other ones use a long prefix
that resembles the name of your macro check.
-
- use a specific prefix - do not use AC_ or AM_
-
Many macro names might be defined under the same name elsewhere.
Usually, you would use a project prefix to avoid double defines,
i.e. MYPROJECT_CHECK_GNU. Do never use AC_CHECK_GNU since all AC_
names are reserved - even if you know there is no such macro in
the "autoconf" package then it might still be added later. If you
intend to submit your macro the Autoconf Macro Archive then you
can use the AX_ prefix - we take all macros and we will ensure
all macros in the archive are unique. Always and forever.
After applying all these guideline, the macro might now look like
this:
AC_DEFUN([AX_CHECK_GNU_MAKE],[
AC_CACHE_CHECK([for GNU make],ax_cv_gnu_make_command,[
AS_VAR_PUSHEDEF([_make_command],ax_cv_gnu_make_command)dnl
_make_command=""
for a in "$MAKE" make gmake gnumake
do test "x$a" = "x" && continue
if ( sh -c "$a --version" 2>/dev/null | grep GNU >/dev/null )
then _make_command="$a" ; break;
fi
done
if test "x$_make_command" != "x"
then ifGNUmake=""
AC_MSG_RESULT([$_make_command])
else ifGNUmake="#"
AC_MSG_RESULT([nothing found])
fi
AC_SUBST([ifGNUmake])
AS_VAR_POPDEF([_make_command])dnl
]])
Now the macro is clean - just add a description block as required in
the contribution format and send it to
ac-archive-maintainers@gnu.org
However, we can even get to the next level of autoconf macro coding.
- add ACTION-IF-TRUE / ACTION-IF-FALSE
-
If you have a look around then you will notice that most "CHECK"
macros have additional and optional arguments. Those may contain
shell-code (or other autoconf macros) that should be executed
when the autodection fails (or additionally when it succeeds).
Autoconf macros are numbered, and the first argument is generally
reserved for sub-specifications - e.g. additional "make" program
names to check for
dnl AX_CHECK_GNU_MAKE([make names],[ACTION-IF-FOUND],[ACTION-IF-NOT])
AC_DEFUN([AX_CHECK_GNU_MAKE],[
AC_CACHE_CHECK([for GNU make],ax_cv_gnu_make_command,[
AS_VAR_PUSHEDEF([_make_command],ax_cv_gnu_make_command)dnl
_make_command=""
for a in "$MAKE" $1 make gmake gnumake
do test "x$a" = "x" && continue
if ( sh -c "$a --version" 2>/dev/null | grep GNU >/dev/null )
then _make_command="$a" ; break;
fi
done
if test "x$_make_command" != "x"
then ifGNUmake=""
AC_MSG_RESULT([$_make_command])
$2
else ifGNUmake="#"
AC_MSG_RESULT([nothing found])
$3
fi
AC_SUBST([ifGNUmake])
AS_VAR_POPDEF([_make_command])
]])
- use sugar - either m4sugar or m4sh sugar
-
The m4 macro processor has lots of ways to avoid that parts get
pushed into the final "configure" script unessarily or in way
being unportable. Have a look at
/usr/share/autoconf/m4sugar/m4sugar.m4 and
/usr/share/autoconf/m4sugar/m4sh.m4
Among the possible usages - one can avoid the extra space in
the example if there are no optional $2 or $3 argument. We use
the m4sugar m4_ifvaln for that, i.e.
then ifGNUmake=""
AC_MSG_RESULT([$_make_command])
m4_ifvaln([$2],[$2])dnl
else ifGNUmake="#"
AC_MSG_RESULT([nothing found])
m4_ifvaln([$3],[$3])dnl
fi
In this example it would only be one line saved - but one can save a
lot more in other places. Let's consider the case that the check-value
is only used to execute an ACTION whereas both action-defs
are optional as arguments. The shell does have a default "no-operation"
statement named ":", so the first attempt might read as
if test "x$testvalue" = "xyes"
then $2
:
else $3
:
fi
That one is simply needed since the shell might call for a "syntax
error" if there is nothing after "then" and before "else". And in
fact, the $2 and $3 ACTION might be empty. A more interesting
approach would be to use some m4sugar as
if test "x$testvalue" = "xyes" ; then
m4_ifvaln([$2],[$2],[:])dnl
m4_ifvaln([$3],[else $3])dnl
fi
| |