diff options
author | Zack Weinberg <zackw@panix.com> | 2020-10-07 15:45:57 -0400 |
---|---|---|
committer | Zack Weinberg <zackw@panix.com> | 2020-11-30 11:45:27 -0500 |
commit | 8bf19fe82e08a98babbbfa5d7b8a42b6ee6b594f (patch) | |
tree | 53c58d159e48369ffc48a4d69706e020c11051a6 | |
parent | 7ee946312e227a07cc20dcb5d3c5645caa1684a0 (diff) | |
download | autoconf-8bf19fe82e08a98babbbfa5d7b8a42b6ee6b594f.tar.gz |
Overhaul Erlang support.
Erlang is similar to Java in that it doesn’t compile to standalone
machine code; the output of ‘erlc’ is byte-code files that are then
interpreted by ‘erl’. We handle this poorly in a whole bunch of ways,
particularly when cross-compiling. This patch fixes up the more
serious problems:
- AC_COMPILE_IFELSE now actually works when AC_LANG([Erlang]) is in
effect.
- ‘conftest.beam’ is now deleted in several more places where it
could be created.
- The various AC_ERLANG_* macros that interrogate the runtime
environment do so by invoking ‘$ERL’ directly, rather than using
AC_RUN_IFELSE, and thus do not crash the configure script when
we think we’re cross-compiling. (It is not clear to me whether
they get the correct answer when cross-compiling, but this should
still be strictly an improvement.)
- The Erlang-related tests have been streamlined.
Further improvements are definitely possible, but we’d have to teach
the infrastructure to make $ac_objext language-specific first, which
seems like too big of a change for 2.70.
(This patch is all fallout from a logically unrelated testsuite change
which is coming up next. Gotta love the fundamental interconnectedness
of things.)
* lib/autoconf/general.m4 (_AC_COMPILE_IFELSE_BODY)
(_AC_LINK_IFELSE_BODY): Delete conftest.beam as well as conftest.$ac_objext.
* lib/autoconf/erlang.m4 (AC_ERLANG_PATH_ERLC, AC_ERLANG_PATH_ERL):
Don’t repeat work done by AC_PATH_TOOL.
(Erlang $ac_compile): Fake an .o file so AC_TRY_COMPILE will be happy.
(AC_LANG_COMPILER(Erlang)): AC_REQUIRE AC_ERLANG_NEED_ERLC, not
AC_ERLANG_PATH_ERLC. Also AC_REQUIRE AC_ERLANG_NEED_ERL so
AC_RUN_IFELSE works reliably.
(AC_ERLANG_CHECK_LIB, AC_ERLANG_SUBST_ROOT_DIR)
(AC_ERLANG_SUBST_LIB_DIR, AC_ERLANG_SUBST_ERTS_VER):
Use $ERL -eval, not AC_RUN_IFELSE.
No need to AC_REQUIRE AC_ERLANG_NEED_ERLC.
* tests/erlang.at: Don’t test anything here that’s tested adequately
by acerlang.at; document which macros those are expected to be.
Remove unnecessary AC_ERLANG_PATH_ERL/ERLC invocations throughout.
(AT_CHECK_MACRO([Erlang])): Rename test to ‘Erlang basic compilation’;
expect both AC_COMPILE_IFELSE and AC_RUN_IFELSE to work;
handle cross compilation mode properly.
* tests/mktests.sh: Exclude from acerlang.at all macros completely
covered by erlang.at.
-rw-r--r-- | lib/autoconf/erlang.m4 | 119 | ||||
-rw-r--r-- | lib/autoconf/general.m4 | 8 | ||||
-rw-r--r-- | tests/erlang.at | 101 | ||||
-rwxr-xr-x | tests/mktests.sh | 4 |
4 files changed, 84 insertions, 148 deletions
diff --git a/lib/autoconf/erlang.m4 b/lib/autoconf/erlang.m4 index ad423b16..b1d3ab1f 100644 --- a/lib/autoconf/erlang.m4 +++ b/lib/autoconf/erlang.m4 @@ -48,13 +48,8 @@ # ------------------------------------------------- AC_DEFUN([AC_ERLANG_PATH_ERLC], [AC_ARG_VAR([ERLC], [Erlang/OTP compiler command [autodetected]])dnl -if test -n "$ERLC"; then - AC_MSG_CHECKING([for erlc]) - AC_MSG_RESULT([$ERLC]) -else - AC_PATH_TOOL(ERLC, erlc, [$1], [$2]) -fi AC_ARG_VAR([ERLCFLAGS], [Erlang/OTP compiler flags [none]])dnl +AC_PATH_TOOL(ERLC, erlc, [$1], [$2]) ]) @@ -72,12 +67,7 @@ fi # ------------------------------------------------ AC_DEFUN([AC_ERLANG_PATH_ERL], [AC_ARG_VAR([ERL], [Erlang/OTP interpreter command [autodetected]])dnl -if test -n "$ERL"; then - AC_MSG_CHECKING([for erl]) - AC_MSG_RESULT([$ERL]) -else - AC_PATH_TOOL(ERL, erl, [$1], [$2])[]dnl -fi +AC_PATH_TOOL(ERL, erl, [$1], [$2]) ]) @@ -101,7 +91,8 @@ fi # --------------- AC_LANG_DEFINE([Erlang], [erl], [ERL], [ERLC], [], [ac_ext=erl -ac_compile='$ERLC $ERLCFLAGS -b beam conftest.$ac_ext >&AS_MESSAGE_LOG_FD' +: ${ac_objext=o} +ac_compile='$ERLC $ERLCFLAGS -b beam conftest.$ac_ext >&AS_MESSAGE_LOG_FD && ln -sf conftest.beam conftest.$ac_objext' ac_link='$ERLC $ERLCFLAGS -b beam conftest.$ac_ext >&AS_MESSAGE_LOG_FD && echo "[#]!/bin/sh" > conftest$ac_exeext && AS_ECHO(["\"$ERL\" -run conftest start -run init stop -noshell"]) >> conftest$ac_exeext && chmod +x conftest$ac_exeext' ]) @@ -164,8 +155,11 @@ AC_DEFUN([AC_LANG_PREPROC(Erlang)], # AC_LANG_COMPILER(Erlang) # ------------------------ # Find the Erlang compiler. Must be AC_DEFUN'd to be AC_REQUIRE'able. +# Technically we only need erlc to compile, but there's no AC_LANG_DISPATCH +# hook specifically for AC_RUN_IFELSE, so we need to find erl here too. AC_DEFUN([AC_LANG_COMPILER(Erlang)], -[AC_REQUIRE([AC_ERLANG_PATH_ERLC])]) +[AC_REQUIRE([AC_ERLANG_NEED_ERLC]) +AC_REQUIRE([AC_ERLANG_NEED_ERL])]) # AC_ERLANG_CHECK_LIB(LIBRARY, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) @@ -173,37 +167,22 @@ AC_DEFUN([AC_LANG_COMPILER(Erlang)], # Macro for checking if an Erlang library is installed, and to # determine its version. AC_DEFUN([AC_ERLANG_CHECK_LIB], -[AC_REQUIRE([AC_ERLANG_NEED_ERLC])[]dnl -AC_REQUIRE([AC_ERLANG_NEED_ERL])[]dnl +[AC_REQUIRE([AC_ERLANG_NEED_ERL])[]dnl AC_CACHE_CHECK([for Erlang/OTP '$1' library subdirectory], [ac_cv_erlang_lib_dir_$1], - [AC_LANG_PUSH(Erlang)[]dnl - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([], [dnl - ReturnValue = case code:lib_dir("[$1]") of - {error, bad_name} -> - file:write_file("conftest.out", "not found\n"), - 1; - LibDir -> - file:write_file("conftest.out", LibDir), - 0 - end, - halt(ReturnValue)])], - [ac_cv_erlang_lib_dir_$1=`cat conftest.out` - rm -f conftest.out], - [if test ! -f conftest.out; then - AC_MSG_FAILURE([test Erlang program execution failed]) - else - ac_cv_erlang_lib_dir_$1="not found" - rm -f conftest.out - fi]) - AC_LANG_POP(Erlang)[]dnl - ]) + [ac_cv_erlang_lib_dir_$1=`$ERL -noshell -eval ' + case code:lib_dir("$1") of + {error, bad_name} -> io:format("not found~n"); + LibDir -> io:format("~s~n", @<:@LibDir@:>@) + end, + halt(0) + '`]) AC_CACHE_CHECK([for Erlang/OTP '$1' library version], [ac_cv_erlang_lib_ver_$1], [AS_IF([test "$ac_cv_erlang_lib_dir_$1" = "not found"], - [ac_cv_erlang_lib_ver_$1="not found"], - [ac_cv_erlang_lib_ver_$1=`AS_ECHO(["$ac_cv_erlang_lib_dir_$1"]) | sed -n -e 's,^.*-\([[^/-]]*\)$,\1,p'`])[]dnl + [ac_cv_erlang_lib_ver_$1="not found"], + [ac_cv_erlang_lib_ver_$1=`AS_ECHO(["$ac_cv_erlang_lib_dir_$1"]) | + sed -n -e 's,^.*-\([[^/-]]*\)$,\1,p'`])[]dnl ]) AC_SUBST([ERLANG_LIB_DIR_$1], [$ac_cv_erlang_lib_dir_$1]) AC_SUBST([ERLANG_LIB_VER_$1], [$ac_cv_erlang_lib_ver_$1]) @@ -215,23 +194,13 @@ AS_IF([test "$ac_cv_erlang_lib_dir_$1" = "not found"], [$3], [$2]) # ------------------------ # Determines the Erlang/OTP root directory. AC_DEFUN([AC_ERLANG_SUBST_ROOT_DIR], -[AC_REQUIRE([AC_ERLANG_NEED_ERLC])[]dnl -AC_REQUIRE([AC_ERLANG_NEED_ERL])[]dnl +[AC_REQUIRE([AC_ERLANG_NEED_ERL])[]dnl AC_CACHE_CHECK([for Erlang/OTP root directory], [ac_cv_erlang_root_dir], - [AC_LANG_PUSH(Erlang)[]dnl - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([], [dnl - RootDir = code:root_dir(), - file:write_file("conftest.out", RootDir), - ReturnValue = 0, - halt(ReturnValue)])], - [ac_cv_erlang_root_dir=`cat conftest.out` - rm -f conftest.out], - [rm -f conftest.out - AC_MSG_FAILURE([test Erlang program execution failed])]) - AC_LANG_POP(Erlang)[]dnl - ]) + [ac_cv_erlang_root_dir=`$ERL -noshell -eval ' + io:format("~s~n", @<:@code:root_dir()@:>@), + halt(0) + '`]) AC_SUBST([ERLANG_ROOT_DIR], [$ac_cv_erlang_root_dir]) ])# AC_ERLANG_SUBST_ROOT_DIR @@ -239,23 +208,13 @@ AC_SUBST([ERLANG_ROOT_DIR], [$ac_cv_erlang_root_dir]) # AC_ERLANG_SUBST_LIB_DIR # ----------------------- AC_DEFUN([AC_ERLANG_SUBST_LIB_DIR], -[AC_REQUIRE([AC_ERLANG_NEED_ERLC])[]dnl -AC_REQUIRE([AC_ERLANG_NEED_ERL])[]dnl +[AC_REQUIRE([AC_ERLANG_NEED_ERL])[]dnl AC_CACHE_CHECK([for Erlang/OTP library base directory], [ac_cv_erlang_lib_dir], - [AC_LANG_PUSH(Erlang)[]dnl - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([], [dnl - LibDir = code:lib_dir(), - file:write_file("conftest.out", LibDir), - ReturnValue = 0, - halt(ReturnValue)])], - [ac_cv_erlang_lib_dir=`cat conftest.out` - rm -f conftest.out], - [rm -f conftest.out - AC_MSG_FAILURE([test Erlang program execution failed])]) - AC_LANG_POP(Erlang)[]dnl - ]) + [ac_cv_erlang_lib_dir=`$ERL -noshell -eval ' + io:format("~s~n", @<:@code:lib_dir()@:>@), + halt(0) + '`]) AC_SUBST([ERLANG_LIB_DIR], [$ac_cv_erlang_lib_dir]) ])# AC_ERLANG_SUBST_LIB_DIR @@ -299,22 +258,12 @@ fi # ------------------------ # Determines the Erlang runtime system version. AC_DEFUN([AC_ERLANG_SUBST_ERTS_VER], -[AC_REQUIRE([AC_ERLANG_NEED_ERLC])[]dnl -AC_REQUIRE([AC_ERLANG_NEED_ERL])[]dnl +[AC_REQUIRE([AC_ERLANG_NEED_ERL])[]dnl AC_CACHE_CHECK([for Erlang/OTP ERTS version], [ac_cv_erlang_erts_ver], - [AC_LANG_PUSH([Erlang])[]dnl - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([], [dnl - Version = erlang:system_info(version), - file:write_file("conftest.out", Version), - ReturnValue = 0, - halt(ReturnValue)])], - [ac_cv_erlang_erts_ver=`cat conftest.out` - rm -f conftest.out], - [rm -f conftest.out - AC_MSG_FAILURE([test Erlang program execution failed])]) - AC_LANG_POP([Erlang])[]dnl - ]) + [ac_cv_erlang_erts_ver=`$ERL -noshell -eval ' + io:format("~s~n", @<:@erlang:system_info(version)@:>@), + halt(0) + '`]) AC_SUBST([ERLANG_ERTS_VER], [$ac_cv_erlang_erts_ver]) ])# AC_ERLANG_SUBST_ERTS_VER diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4 index f75b2dbb..16f0d074 100644 --- a/lib/autoconf/general.m4 +++ b/lib/autoconf/general.m4 @@ -2802,7 +2802,7 @@ AC_DEFUN([AC_EGREP_HEADER], # Shell function body for _AC_COMPILE_IFELSE. m4_define([_AC_COMPILE_IFELSE_BODY], [ AS_LINENO_PUSH([$[]1]) - rm -f conftest.$ac_objext + rm -f conftest.$ac_objext conftest.beam AS_IF([_AC_DO_STDERR($ac_compile) && { test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || test ! -s conftest.err @@ -2826,7 +2826,7 @@ AC_DEFUN([_AC_COMPILE_IFELSE], [$0_BODY])]dnl [m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])]dnl [AS_IF([ac_fn_[]_AC_LANG_ABBREV[]_try_compile "$LINENO"], [$2], [$3]) -rm -f core conftest.err conftest.$ac_objext[]m4_ifval([$1], [ conftest.$ac_ext])[]dnl +rm -f core conftest.err conftest.$ac_objext conftest.beam[]m4_ifval([$1], [ conftest.$ac_ext])[]dnl ])# _AC_COMPILE_IFELSE @@ -2858,7 +2858,7 @@ AU_DEFUN([AC_TRY_COMPILE], # Shell function body for _AC_LINK_IFELSE. m4_define([_AC_LINK_IFELSE_BODY], [ AS_LINENO_PUSH([$[]1]) - rm -f conftest.$ac_objext conftest$ac_exeext + rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext AS_IF([_AC_DO_STDERR($ac_link) && { test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || test ! -s conftest.err @@ -2897,7 +2897,7 @@ AC_DEFUN([_AC_LINK_IFELSE], [$0_BODY])]dnl [m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])]dnl [AS_IF([ac_fn_[]_AC_LANG_ABBREV[]_try_link "$LINENO"], [$2], [$3]) -rm -f core conftest.err conftest.$ac_objext \ +rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext[]m4_ifval([$1], [ conftest.$ac_ext])[]dnl ])# _AC_LINK_IFELSE diff --git a/tests/erlang.at b/tests/erlang.at index c149f776..93a0e478 100644 --- a/tests/erlang.at +++ b/tests/erlang.at @@ -1,5 +1,11 @@ # -*- Autotest -*- +# Macros tested in acerlang.at: +# AC_ERLANG_PATH_ERL +# AC_ERLANG_PATH_ERLC +# AC_ERLANG_SUBST_ERTS_VER +# AU::AC_LANG_ERLANG + AT_BANNER([Erlang low level compiling and utility macros.]) # Copyright (C) 2009-2017, 2020 Free Software Foundation, Inc. @@ -27,22 +33,30 @@ AT_BANNER([Erlang low level compiling and utility macros.]) ## Erlang Compiler. ## ## ----------------- ## -AT_CHECK_MACRO([Erlang], -[[AC_ERLANG_PATH_ERL([no]) -AC_ERLANG_PATH_ERLC([no]) -if test "$ERL" = "no" || test "$ERLC" = "no"; then AS_EXIT([77]); fi -AC_LANG([Erlang]) -## Can't compile, but can run an Erlang module: -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [halt(0)])], - [AC_MSG_RESULT([ok]) - AC_MSG_ERROR([compiling Erlang program should fail])], - [AC_MSG_RESULT([failed])]) -AC_RUN_IFELSE([AC_LANG_PROGRAM([], [halt(0)])], - [AC_MSG_RESULT([ok])], - [AC_MSG_RESULT([failed]) - AC_MSG_ERROR([could not run test program])]) -]], -[AT_KEYWORDS([Erlang])]) +AT_CHECK_MACRO([Erlang basic compilation], +[[AC_LANG([Erlang]) + +AC_CACHE_CHECK([whether erlc works], [ac_cv_erlang_erlc_works], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [halt(0)])], + [ac_cv_erlang_erlc_works=yes], + [ac_cv_erlang_erlc_works=no])]) + +if test $ac_cv_erlang_erlc_works = no; then + AC_MSG_ERROR([could not compile a test Erlang module]) +fi + +# To keep AT_CHECK_MACRO happy, we lie and say that erl does work +# when cross compiling. +AC_CACHE_CHECK([whether erl works], [ac_cv_erlang_erl_works], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([], [halt(0)])], + [ac_cv_erlang_erl_works=yes], + [ac_cv_erlang_erl_works=no], + [ac_cv_erlang_erl_works=yes])]) + +if test $ac_cv_erlang_erl_works = no; then + AC_MSG_ERROR([could not run a test Erlang module]) +fi +]]) ## ---------------------- ## @@ -50,19 +64,15 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM([], [halt(0)])], ## ---------------------- ## AT_CHECK_MACRO([AC_ERLANG_CHECK_LIB], -[[AC_ERLANG_PATH_ERL([no]) -AC_ERLANG_PATH_ERLC([no]) -if test "$ERL" = "no" || test "$ERLC" = "no"; then AS_EXIT([77]); fi -AC_ERLANG_CHECK_LIB([stdlib], - [AC_MSG_RESULT([ok])], - [AC_MSG_RESULT([failed])]) +[[AC_ERLANG_CHECK_LIB([stdlib]) +if test "$ERLANG_LIB_DIR_stdlib" = "not found"; then + AC_MSG_ERROR([failed to find the Erlang stdlib]) +fi ## Test that the lib path detection really detected a directory: -if test "$ERLANG_LIB_DIR_stdlib" != "not found" \ - && test ! -d "$ERLANG_LIB_DIR_stdlib"; then - AC_MSG_ERROR([incorrect ERLANG_LIB_DIR_stdlib variable]) +if test ! -d "$ERLANG_LIB_DIR_stdlib"; then + AC_MSG_ERROR([incorrect ERLANG_LIB_DIR_stdlib variable]) fi -]], -[AT_KEYWORDS([Erlang])]) +]]) ## --------------------------- ## @@ -70,16 +80,12 @@ fi ## --------------------------- ## AT_CHECK_MACRO([AC_ERLANG_SUBST_ROOT_DIR], -[[AC_ERLANG_PATH_ERL([no]) -AC_ERLANG_PATH_ERLC([no]) -if test "$ERL" = "no" || test "$ERLC" = "no"; then AS_EXIT([77]); fi -AC_ERLANG_SUBST_ROOT_DIR +[[AC_ERLANG_SUBST_ROOT_DIR ## Test that the root path detection really detected a directory: if test ! -d "$ERLANG_ROOT_DIR"; then AC_MSG_ERROR([incorrect ERLANG_ROOT_DIR variable]) fi -]], -[AT_KEYWORDS([Erlang])]) +]]) ## -------------------------- ## @@ -87,10 +93,7 @@ fi ## -------------------------- ## AT_CHECK_MACRO([AC_ERLANG_SUBST_LIB_DIR], -[[AC_ERLANG_PATH_ERL([no]) -AC_ERLANG_PATH_ERLC([no]) -if test "$ERL" = "no" || test "$ERLC" = "no"; then AS_EXIT([77]); fi -AC_ERLANG_SUBST_LIB_DIR +[[AC_ERLANG_SUBST_LIB_DIR ## Test that the lib path detection really detected a directory: if test ! -d "$ERLANG_LIB_DIR"; then AC_MSG_ERROR([incorrect ERLANG_LIB_DIR variable]) @@ -99,14 +102,6 @@ fi [AT_KEYWORDS([Erlang])]) -## ----------------------------------- ## -## Erlang install base dir detection. ## -## ----------------------------------- ## - -AT_CHECK_MACRO([AC_ERLANG_SUBST_INSTALL_LIB_DIR], - [AT_KEYWORDS([Erlang])]) - - ## ---------------------------------- ## ## Erlang install lib dir detection. ## ## ---------------------------------- ## @@ -114,21 +109,9 @@ AT_CHECK_MACRO([AC_ERLANG_SUBST_INSTALL_LIB_DIR], AT_CHECK_MACRO([AC_ERLANG_SUBST_INSTALL_LIB_SUBDIR], [[AC_ERLANG_SUBST_INSTALL_LIB_SUBDIR([test_blah], [1.24-b]) ## Test that the generated directory name is well-formed: -if test `echo "$ERLANG_INSTALL_LIB_DIR_test_blah" | sed -e 's/^.*\///'` != "test_blah-1.24-b"; then +if test `echo "$ERLANG_INSTALL_LIB_DIR_test_blah" | sed -e 's/^.*\///'` \ + != "test_blah-1.24-b"; then AC_MSG_ERROR([incorrect ERLANG_INSTALL_LIB_DIR_test_blah variable]) fi ]], [AT_KEYWORDS([Erlang])]) - - -## -------------------------- ## -## Erlang version detection. ## -## -------------------------- ## - -AT_CHECK_MACRO([AC_ERLANG_SUBST_ERTS_VER], -[[AC_ERLANG_PATH_ERL([no]) -AC_ERLANG_PATH_ERLC([no]) -if test "$ERL" = "no" || test "$ERLC" = "no"; then AS_EXIT([77]); fi -AC_ERLANG_SUBST_ERTS_VER -]], -[AT_KEYWORDS([Erlang])]) diff --git a/tests/mktests.sh b/tests/mktests.sh index 3ce0c2b4..34458a27 100755 --- a/tests/mktests.sh +++ b/tests/mktests.sh @@ -146,6 +146,10 @@ ac_exclude_list=' # Tested alongside m4_divert_text. /^AC_PRESERVE_HELP_ORDER$/ {next} + + # Tested in erlang.at. + /^AC_ERLANG_SUBST_(INSTALL_LIB_SUBDIR|ROOT_DIR)$/ {next} + /^AC_ERLANG_CHECK_LIB$/ {next} ' |