6. Verificação de Padrões de Linguagem
Vamos testar suporte a diferentes padrões de C e C++.
Até o momento, utilizamos macros definidas por padrão pelo Autoconf, porém, a partir de agora precisaremos definir nossos próprios macros, pois não há uma forma padrão de testar padrões de linguagem.
Por uma questão de boa prática e organização, vamos separar o arquivo principal
configure.ac
dos nossos macros definidos futuramente. Crie um diretório
chamado m4
e crie um arquivo checks.m4
dentro desse diretório.
6.1. Código do m4/checks.m4
AC_DEFUN([CHECK_C_STANDARD], [
AC_MSG_CHECKING([for C$1 support])
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE([
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < $2
#error "C$1 not supported"
#endif
int main(void) { return 0; }
])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]
)
])
AC_DEFUN([CHECK_CXX_STANDARD], [
AC_MSG_CHECKING([for C++$1 support])
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE([
#if !defined(__cplusplus) || __cplusplus < $2
#error "C++$1 not supported"
#endif
int main() { return 0; }
])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]
)
])
6.2. Macros Utilizados
Este código define duas macros para verificar suporte a padrões C e C++. Vamos analisar cada parte:
CHECK_C_STANDARD
: Verifica se o compilador C suporta uma versão específica do padrão C.CHECK_CXX_STANDARD
: Verifica se o compilador C++ suporta uma versão específica do padrão C++.
Ambos os macros seguem o mesmo padrão:
AC_MSG_CHECKING(msg)
: Exibe uma mensagem de verificação (ex: "checking for C11 support"). A palavra "checking" é automaticamente posta no inicio da mensagemAC_COMPILE_IFELSE([program], [success], [failure])
: Tenta compilar um programa teste, em caso de sucesso, executará o que está emsuccess
, em caso de falha, executará o que está emfailure
AC_LANG_SOURCE([program])
: Define o código fonte a ser compilado. Caso não seja dado um programa, será utilizado um programa padrão simples definido pelo AutoconfAC_MSG_RESULT
: Exibe o resultado (yes/no)
6.2.1. Detalhes da Implementação para C (CHECK_C_STANDARD
)
- Verifica
__STDC_VERSION__
(macro que indica a versão do padrão C) - Compara com o valor numérico fornecido no segundo argumento (
$2
) - Valores típicos:
- C99:
199901L
- C11:
201112L
- C17:
201710L
- C99:
6.2.2. Detalhes da Implementação para C++ (CHECK_CXX_STANDARD
)
- Verifica
__cplusplus
(macro que indica a versão do padrão C++) - Compara com o valor numérico fornecido no segundo argumento (
$2
) - Valores típicos:
- C++11:
201103L
- C++14:
201402L
- C++17:
201703L
- C++20:
202002L
- C++11:
6.3. Fluxo de execução da função
- O Autoconf expande as macros durante a geração do script
configure
- Os argumentos são passados no estilo bash, o primeiro argumento é
$1
, o segundo,$2
, etc. - Quando
./configure
é executado:- Compila o programa teste
- Se compilar com sucesso: padrão suportado ("yes")
- Se falhar (devido ao
#error
): padrão não suportado ("no")
6.4. Código do configure.ac
AC_INIT([epp], [1.0])
m4_include([m4/checks.m4])
AC_PROG_CC
AC_PROG_CXX
AC_LANG_PUSH([C])
CHECK_C_STANDARD([11], [201112L]) # C11
CHECK_C_STANDARD([17], [201710L]) # C17
CHECK_C_STANDARD([23], [202311L]) # C23
AC_LANG_POP([C])
AC_LANG_PUSH([C++])
CHECK_CXX_STANDARD([11], [201103L]) # C++11
CHECK_CXX_STANDARD([14], [201402L]) # C++14
CHECK_CXX_STANDARD([17], [201703L]) # C++17
CHECK_CXX_STANDARD([20], [202002L]) # C++20
CHECK_CXX_STANDARD([23], [202302L]) # C++23
AC_LANG_POP([C++])
AC_OUTPUT
AC_LANG_PUSH([lang])
eAC_LANG_POP([lang])
: indicam qual linguagem o Autoconf está lidando na hora de compilar o programa passado
6.4. Saída Esperada
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether the compiler supports GNU C... yes
checking whether gcc accepts -g... yes
checking for gcc option to enable C11 features... none needed
checking for g++... g++
checking whether the compiler supports GNU C++... yes
checking whether g++ accepts -g... yes
checking for g++ option to enable C++11 features... none needed
checking for C11 support... yes
checking for C17 support... yes
checking for C23 support... no
checking for C++11 support... yes
checking for C++14 support... yes
checking for C++17 support... yes
checking for C++20 support... no
checking for C++23 support... no
configure: creating ./config.status