Como definir o nível de aviso no CMake?


116

Como definir o nível de aviso para um projeto (não toda a solução) usando CMake ? Deve funcionar em Visual Studio e GCC .

Encontrei várias opções, mas a maioria parece não funcionar ou não é consistente com a documentação.

Respostas:


96

ATUALIZAÇÃO: Esta resposta é anterior à era Modern CMake. Todo usuário sensato do CMake deve evitar mexer com o CMAKE_CXX_FLAGSdiretamente e chamar o target_compile_optionscomando. Verifique a resposta dos mrts que apresenta as melhores práticas recomendadas.

Você pode fazer algo semelhante a isto:

if(MSVC)
  # Force to always compile with W4
  if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
  else()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
  endif()
elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
  # Update if necessary
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic")
endif()

Observe que as novas versões do Visual Studio (pelo menos 2013) suportam /Wallsinalizador (que é nomeado EnableAllWarnings). Produz ainda mais avisos do que /W4. No entanto, pela minha experiência, produz muitos avisos.
Adam Badura

12
/Wallpode ser usado se você quiser seguir uma estratégia 'subtrativa' para avisos, assim como a do clang -Weverything. Em vez de selecionar avisos para ativar, você ativa tudo e, em seguida, seleciona avisos específicos para desativar.
bames53

86

No CMake moderno, o seguinte funciona bem:

if(MSVC)
  target_compile_options(${TARGET_NAME} PRIVATE /W4 /WX)
else()
  target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic -Werror)
endif()

Meu colega sugeriu uma versão alternativa:

target_compile_options(${TARGET_NAME} PRIVATE
  $<$<CXX_COMPILER_ID:MSVC>:/W4 /WX>
  $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -pedantic -Werror>
)

Substitua ${TARGET_NAME}pelo nome real do alvo. -Werroré opcional, transforma todos os avisos em erros.

Ou use add_compile_options(...)se quiser aplicá-lo a todos os destinos, conforme sugerido por @aldo nos comentários.

Além disso, certifique-se de entender a diferença entre PRIVATEe PUBLIC(as opções públicas serão herdadas por destinos que dependem do destino fornecido).


19
Ou simplesmente add_compile_options(...)se você deseja aplicá-lo a todos os alvos.
aldo,

1
FYI moderno CMake não requer a repetição da condição em else()ou endif().
Timmmm de

1
@Timmmm Obrigado pelo aviso! É apenas uma nota ou prefere que eu remova as condições?
março

1
@helmesjo Não, Timmmm estava se referindo ao código CMake como existia antes da edição de 9 de abril. Você pode dar uma olhada no histórico de edição para ver os bits que foram removidos, que são as mesmas coisas que Timmmm estava apontando.
FeRD

2
@aldo, o problema add_compile_options()é que os avisos se propagam para os alvos adicionados via add_subdirectory(). Se você incluir bibliotecas externas dessa forma, poderá obter muitos avisos se essa biblioteca tiver sido projetada com níveis de aviso diferentes.
trozen

24

Alguns módulos do CMake que escrevi incluem supressão experimental de aviso de plataforma cruzada :

sugar_generate_warning_flags(
    target_compile_options
    target_properties
    ENABLE conversion
    TREAT_AS_ERRORS ALL
)

set_target_properties(
    foo
    PROPERTIES
    ${target_properties}
    COMPILE_OPTIONS
    "${target_compile_options}"
)

Resultado para Xcode:

  • Defina o CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSIONatributo Xcode (também conhecido como configurações de construção -> avisos -> conversões implícitas suspeitas -> SIM )
  • Adicionar sinalizador do compilador: -Werror

Makefile gcc e clang:

  • Adicionar opções de compilação: -Wconversion,-Werror

Estúdio visual:

  • Adicionar opções de compilação: /WX,/w14244

Links


1
é uma pena que o cmake não fornece esta funcionalidade
Slava

3
Boas notícias. Desculpe postá-lo aqui e não na lista de discussão do cmake, mas sem o nível isso será inútil. Existem muitos avisos para listá-los todos explicitamente. Se você deseja unificá-lo, uma forma de fazer isso é dois cmake_level separados - conjunto unificado de avisos, baseado por exemplo em clang e native_level com o significado específico para um compilador. Um deles provavelmente pode ser reduzido para nível. Desculpe se eu realmente não segui a conversa e entendi algo errado
Slava

1
@ void.pointer levanta um ponto válido. Sua proposta de resposta é: " Estou planejando adicionar este recurso" . Não quer dizer que você fez uma pesquisa superficial e agora espera que outra pessoa faça o trabalho pesado para você. Se você não quiser ser atribuído com a implementação (e perguntas sobre seu progresso), você precisa editar sua resposta e se desassociar da tarefa na qual não progrediu em mais de um ano.
Inspecionável

"Mais de um ano depois, ainda nenhum progresso." - Esse é um ponto válido. Mais de um ano se passou, sem progresso. Essa é uma indicação muito forte de um projeto abandonado. Se você quiser provar que estamos errados, mostre-nos alguns progressos. Isso não aconteceu, mas sua resposta proposta ainda sugere que o recurso está prestes a ser adicionado ao CMake. Por que fazer tanto alarido sobre um recurso que não estará disponível em anos? Isso não ajuda em nada. Mostre algum progresso ou edite sua resposta para ser menos enganosa.
Inspecionável

5
Você não parece entender. Se você sugerir que implementará um recurso, será necessário implementá-lo no devido tempo. Caso contrário, você será solicitado a remover essa promessa de sua resposta proposta. Você demonstrou compromisso zero para implementar esse recurso, então não diga o contrário. Eu entendo que é grande. Eu também entendo que você não seja capaz de fazer isso. Estou simplesmente pedindo a você que faça sua resposta refletir isso.
Inspecionável

6

Aqui está a melhor solução que encontrei até agora (incluindo uma verificação do compilador):

if(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
    add_definitions(/W2)
endif()

Isso definirá o nível de aviso 2 no Visual Studio. Suponho que com um -W2funcionaria no GCC também (não testado).

Atualização de @Williams: Deve ser -Wallpara o GCC.


6
A sinalização de aviso para GCC seria -Walle talvez -Wextraconforme detalhado em gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Milliams

1
A lista que uso é -W -Wall -Wextra -pedantic. -WextraIIRC substituído -Wem uma versão posterior do GCC, mas deixo ambos por causa das compatibilidades.
Jimmio92

2
Esse não é o propósito pretendido de add_definitions ( "tem a intenção de adicionar definições de pré-processador" ). Não é apenas uma recomendação de melhores práticas. Os argumentos passados ​​para este comando aparecerão nos scripts de construção gerados, invocando ferramentas que não os esperam (por exemplo, o compilador de recursos).
Inspecionável

Isso não é uma "verificação do compilador", é uma verificação da ferramenta de compilação.
Thomas

3

De acordo com a documentação Cmake 3.17.1 :

if (MSVC)
    # warning level 4 and all warnings as errors
    add_compile_options(/W4 /WX)
else()
    # lots of warnings and all warnings as errors
    add_compile_options(-Wall -Wextra -pedantic -Werror)
endif()

O GCC e o Clang compartilham esses sinalizadores, portanto, isso deve abranger todos os 3.


Não use isso. Em vez disso, use target_compile_options (). Referir-se ao documento mais recente parece ser "correto", mas é uma entrada antiga apenas para compatibilidade com versões anteriores.
caoanan

1
@caoanan A documentação não menciona nada de compatibilidade com versões anteriores para isso. add_compile_optionsabrange todo o diretório, mas target_compile_optionsé apenas para um único destino.
TehWan

2
if(MSVC)
    string(REGEX REPLACE "/W[1-3]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()

Se você usar target_compile_options- cmake tentará usar double /W*flag, o que dará um aviso pelo compilador.


Obrigado por isso. Eu estava usando ingenuamente add_compile_optionsapenas para obter toneladas de avisos que /W3estão sendo anulados /W4. O fato de que o CMake não está abordando essa opção rudimentar (definir o nível de aviso) é inacreditável.
Ressurreição em
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.