Более надежный AC компилирует тестирование функций IFELSE?

autoconf для Х AC_COMPILE_IFELSE неправильно определяет функции для нас в разных компиляторах, таких как компилятор Sun C++ и компилятор xlC IBM. AC_COMPILE_IFELSE, похоже, проверяет возвращаемые значения, но некоторые компиляторы не утруждают себя установкой или установкой неожиданных значений. Позже мы используем опции, которые недоступны.

в моих сценариях сборки без Autoconf я использую "fatal|error|illegal|unrecognized|not found|not exist" для обнаружения жалобы компилятора или компоновщика. Он более надежен, чем просто проверка $?. Тест выглядит например:

# infile and outfile are temp files that allow testing a feature
SH_ERROR=$($CXX -Wl,--enable-new-dtags -o "$outfile" "$infile" 2>&1 | $EGREP -i -c -E 'fatal|error|illegal|unrecognized|not found|not exist')
if [[ "$SH_ERROR" -eq "0" ]]; then
    CXXFLAGS+="-Wl,--enable-new-dtags"
fi

документация Autoconf для AC_COMPILE_IFELSE на 6.4 запуск компилятора, но это не Обсуждение предмета. Фактически, документ даже не определяет, что он означает для AC_COMPILE_IFELSE быть " успех[ful]".

мой первый вопрос: Являются ли возвращаемые значения компилятора стандартизированными где-то?

мой второй вопрос: что Autoconf использует для определения "успеха"?

мой третий вопрос, как мы это делаем то же самое в Autoconf? Есть ли что-то еще, кроме AC_COMPILE_IFELSE?

связанный вопрос (основанный на ответе Стефана), как мы получаем Autoconf для использования улучшенного AC_COMPILE_IFELSE? Можно ли undef текущий AC_COMPILE_IFELSE и определить его для более надежной версии?

спасибо заранее.

1 ответов


мой первый вопрос: где-то стандартизированы возвращаемые значения компилятора?

я уверен, что нет стандарта, определяющего, какие компиляторы для любого языка должны возвращаться, кроме очевидного стандарта для всех программ, которые выходят из кода 0 означает успех и все остальное провал, см. posix на exit:

значение нуля (или EXIT_SUCCESS, который должен быть равен нулю) для аргумента статус условно означает успешное завершение. Это соответствует спецификации exit() в стандарте ISO C. За соглашением следуют утилиты, такие как make и различные оболочки, которые интерпретируют нулевой статус дочернего процесса как успех. По этой причине, приложения не должны вызывать exit(0) или _exit(0) когда они заканчиваются неудачно; например, в функциях улавливания сигналов.


мой второй вопрос, что делает Использование Autoconf для определения "успеха"?

последний выпуск autoconf-2.69 (с 2012 года), и хотя некоторые вещи могли измениться, я собираюсь основывать свой ответ на нем.

AC_COMPILE_IFELSE успешно, если компилятор имеет успешный код выхода (т. е. 0) и объектный файл не является пустым (test -s conftest.$ac_objext; он удаляется перед запуском компилятора). Если AC_LANG_WERROR используется для текущего языка, он также гарантирует, что the stderr вывод компилятора пуст (кроме строки журнала трассировки оболочки).


мой третий вопрос: как мы делаем то же самое в Autoconf? Есть ли что-то еще, кроме AC_COMPILE_IFELSE?

имейте в виду, что хотя источники autoconf выглядят как магия, они не являются - Вы можете создавать свои собственные макросы, пока вы знаете, что вы хотите, чтобы они делали :) но, возможно,AC_LANG_WERROR - это вариант, кроме того, чтобы сказать поставщику сосать его и исправить свое дерьмо.

я не фанат AC_LANG_WERROR: мне пришлось использовать /etc/ld.so.preload в мультиархивной системе, чтобы исправить проблемы с flashplayer несколько лет назад, и запуск двоичных файлов из другой арки всегда печатал ошибку, она не могла загрузить ее, хотя с ней не было ничего плохого - AC_LANG_WERROR ломает ужасно в такой среде

в качестве примера пользовательского макроса проверки компиляции взгляните на это:

# MY_COMPILE_CLEAN_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
# ---------------------------------------------------------------
# Try to compile PROGRAM.
AC_DEFUN([MY_COMPILE_CLEAN_IFELSE],
[AC_REQUIRE([AC_PROG_EGREP])
AC_COMPILE_IFELSE([],[retval=0
if $EGREP -i -c -E 'fatal|error|unrecognized|not found|not exist' conftest.err >/dev/null; then retval=1; fi
],[retval=1])
AS_IF([test $retval = 0],[],[])])

conftest.err удаляется после AC_COMPILE_IFELSE сделано, поэтому вам нужно проверить его во внутренних действиях.