¿Cómo establecer el nivel de advertencia en CMake?

116

¿Cómo establecer el nivel de advertencia para un proyecto (no la solución completa) usando CMake ? Debería funcionar en Visual Studio y GCC .

Encontré varias opciones, pero la mayoría parece no funcionar o no son consistentes con la documentación.

Wernight
fuente

Respuestas:

96

ACTUALIZACIÓN: Esta respuesta es anterior a la era de Modern CMake. Todo usuario cuerdo de CMake debe abstenerse de jugar CMAKE_CXX_FLAGSdirectamente y llamar al target_compile_optionscomando en su lugar. Verifique la respuesta de mrts que presenta las mejores prácticas recomendadas.

Puedes hacer algo similar a esto:

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()
Mloskot
fuente
Tenga en cuenta que las nuevas versiones de Visual Studio (al menos 2013) admiten el /Wallindicador (que se denomina EnableAllWarnings). Produce incluso más advertencias que /W4. Sin embargo, desde mi experiencia, produce demasiadas advertencias.
Adam Badura
12
/Wallse puede utilizar si desea seguir una estrategia 'sustractiva' para las advertencias, como la de clang -Weverything. En lugar de seleccionar advertencias para habilitar, habilita todo y luego selecciona advertencias específicas para deshabilitar.
bames53
86

En CMake moderno, lo siguiente funciona bien:

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

Mi colega sugirió una versión alternativa:

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

Reemplazar ${TARGET_NAME}con el nombre real del objetivo. -Werrores opcional, convierte todas las advertencias en errores.

O utilícelo add_compile_options(...)si desea aplicarlo a todos los objetivos como lo sugiere @aldo en los comentarios.

Además, asegúrese de comprender la diferencia entre PRIVATEy PUBLIC(las opciones públicas serán heredadas por los destinos que dependen del destino dado).

mrts
fuente
19
O simplemente add_compile_options(...)si desea aplicarlo a todos los objetivos.
aldo
1
Para su información, CMake moderno no requiere que se repita la condición en else()o endif().
Timmmm
1
@Timmmm ¡Gracias por el aviso! ¿Es solo una nota o prefiere que elimine las condiciones?
mrts
1
@helmesjo No, Timmmm se refería al código CMake tal como existía antes de la edición del 9 de abril. Puede echar un vistazo al historial de edición para ver los bits que se eliminaron, que son las mismas cosas que Timmmm estaba señalando.
2019
2
@aldo, el problema con add_compile_options()es que las advertencias se propagarán a los objetivos agregados a través de add_subdirectory(). Si incluye bibliotecas externas de esta manera, puede recibir muchas advertencias si esa biblioteca fue diseñada con un nivel de advertencia diferente.
trozen
24

Algunos módulos de CMake que he escrito incluyen la supresión de advertencias experimentales entre plataformas :

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:

  • Establecer el CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSIONatributo Xcode (también conocido como configuración de compilación -> advertencias -> conversiones implícitas sospechosas -> )
  • Agregar marca de compilador: -Werror

Makefile gcc y clang:

  • Añadir opciones del compilador: -Wconversion,-Werror

Estudio visual:

  • Añadir opciones del compilador: /WX,/w14244

Enlaces

xaxxon
fuente
1
es una pena que cmake no proporcione esta funcionalidad
Slava
3
Buenas noticias. Perdón por publicarlo aquí y no en la lista de correo de cmake, pero sin nivel, esto será inútil. Hay demasiadas advertencias para enumerarlas todas explícitamente. Si desea unificarlo, una forma de hacerlo es con dos cmake_level separados: un conjunto unificado de advertencias, basado por ejemplo en clang, y native_level con el significado específico de un compilador. Uno de ellos probablemente se puede acortar a nivel. Lo siento si realmente no seguí la conversación y me equivoqué en algo
Slava
1
@ void.pointer plantea un punto válido. Su respuesta propuesta dice: " Estoy planeando agregar esta función" . No dice que hiciste una investigación superficial y ahora esperas que alguien más haga el trabajo pesado por ti. Si no desea que se le atribuya la implementación (y preguntas sobre su progreso), debe editar su respuesta y desasociarse de la tarea en la que no ha progresado en más de un año.
Inspectable
"Más de un año después, todavía no hay avances". - Eso es un punto válido. Ha pasado más de un año, sin avances. Esa es una indicación muy fuerte de un proyecto abandonado. Si quieres demostrar que estamos equivocados, muéstranos algunos avances. Eso no ha sucedido, pero su respuesta propuesta aún sugiere que la función está a punto de agregarse a CMake. ¿Por qué hacer tanto alboroto por una función que no estará disponible en años? Eso no ayuda en absoluto. Muestra algún progreso o edita tu respuesta para que sea menos engañosa.
IInspectable
5
No pareces entender. Si sugiere que va a implementar una función, debe implementar esa función a su debido tiempo. De lo contrario, se le pedirá que elimine esa promesa de su respuesta propuesta. No ha mostrado ningún compromiso para implementar dicha función, así que no afirme lo contrario. Entiendo que es grande. También entiendo que es posible que no seas capaz de lograrlo. Simplemente le pido que haga que su respuesta refleje eso.
IInspectable
6

Aquí está la mejor solución que encontré hasta ahora (incluida una verificación del compilador):

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

Esto establecerá el nivel de advertencia 2 en Visual Studio. Supongo que con un-W2 también funcionaría en GCC (no probado).

Actualización de @Williams: debería ser -Wallpara GCC.

Wernight
fuente
6
La bandera de advertencia para GCC sería -Wally tal vez -Wextracomo se detalla en gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Milliams
1
La lista que utilizo es -W -Wall -Wextra -pedantic. -WextraIIRC reemplazado -Wen una versión posterior de GCC, pero dejo ambos por el bien de las compatibilidades.
Jimmio92
2
Ese no es el propósito de add_definitions ( "está destinado a agregar definiciones de preprocesador" ). Tampoco es solo una recomendación de mejores prácticas. Los argumentos pasados ​​a este comando se mostrarán en los scripts de construcción generados invocando herramientas que no los esperan (por ejemplo, el compilador de recursos).
Inspectable
Eso no es una "verificación del compilador", es una verificación de la herramienta de construcción.
Thomas
3

Según la documentación de 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()

GCC y Clang comparten estos indicadores, por lo que debería cubrir los 3.

Arrendajo
fuente
No uses esto. En su lugar, use target_compile_options (). Hacer referencia al último documento parece ser "correcto", pero es una entrada antigua simplemente por compatibilidad con versiones anteriores.
caoanan
1
@caoanan La documentación no menciona nada de compatibilidad con versiones anteriores para esto. add_compile_optionses para todo el directorio, mientras que target_compile_optionses solo para un único destino.
TehWan
2
if(MSVC)
    string(REGEX REPLACE "/W[1-3]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()

Si usa target_compile_options- cmake intentará usar doble /W*bandera, lo que dará una advertencia por parte del compilador.

TarmoPikaro
fuente
Gracias por esto. Ingenuamente estaba usando el add_compile_optionsúnico para recibir toneladas de advertencias que /W3están siendo anuladas /W4. El hecho de que CMake no esté abordando esta opción rudimentaria (establecer el nivel de advertencia) es increíble.
Resurrección