Anular marcas de compilación para archivos individuales

109

Me gustaría usar un conjunto global de indicadores para compilar un proyecto, lo que significa que en mi archivo CMakeLists.txt de nivel superior he especificado:

ADD_DEFINITIONS ( -Wall -Weffc++ -pedantic -std=c++0x )

Sin embargo, para un archivo específico (digamos "foo.cpp") en un subdirectorio, quiero cambiar las marcas de compilación para que no se apliquen -Weffc ++ (biblioteca comercial incluida que no puedo cambiar). Para simplificar la situación para usar solo -Wall, intenté:

 SET_SOURCE_FILES_PROPERTIES( foo.cpp PROPERTIES COMPILE_FLAGS -Wall )
 ADD_EXECUTABLE( foo foo.cpp )

, que no funcionó. También lo intenté

SET_PROPERTY( SOURCE foo.cpp PROPERTY COMPILE_FLAGS -Wall )
ADD_EXECUTABLE( foo foo.cpp )

y

ADD_EXECUTABLE( foo foo.cpp )
SET_TARGET_PROPERTIES( foo PROPERTIES COMPILE_FLAGS -Wall )

, en el que ninguno funcionó.

Finalmente, intenté eliminar esta definición:

REMOVE_DEFINITIONS( -Weffc++ )
ADD_EXECUTABLE( foo foo.cpp )
ADD_DEFINITIONS( -Weffc++ )

, que tampoco funcionó (es decir, recibo muchas advertencias de estilo sobre la biblioteca comercial). (** Nota: Las advertencias se suprimen si NO vuelvo a incluir la directiva -Weffc ++ después de que se compile el ejecutable).

También intenté eliminar temporalmente las marcas de compilación: http://www.cmake.org/pipermail/cmake/2007-June/014614.html , pero eso no ayudó.

¿No hay una solución elegante para esto?

JB marrón
fuente
1
Espera, si tu último intento funciona, pero solo después de compilado, ¿no podría ser un problema de almacenamiento en caché? Intente eliminar CMakeCache después de realizar sus cambios.
Cameron
Relacionado, consulte ¿Cómo cambiar un indicador de compilador para un solo ejecutable en CMake? La respuesta de Andre muestra lo que parece ser una forma de reemplazar las opciones existentes con opciones nuevas.
jww

Respuestas:

126

Sus intentos anteriores están agregando más banderas a su archivo / destino en lugar de sobrescribir como parece esperar. Por ejemplo, de los documentos de Propiedades en archivos de origen - COMPILE_FLAGS :

Estos indicadores se agregarán a la lista de indicadores de compilación cuando se compile este archivo fuente.

Debería poder -Weffc++anular la bandera de foo.cpp haciendo

set_source_files_properties(foo.cpp PROPERTIES COMPILE_FLAGS -Wno-effc++)

Esto debería tener el efecto de agregar -Wno-effc++after -Weffc++en el comando del compilador, y la última configuración gana. Para ver el comando completo y comprobar que este es realmente el caso, puede hacer

make VERBOSE=1

Como acotación al margen, uno de los mantenedores de la biblioteca estándar de GNU C ++ presenta una opinión bastante negativa -Weffc++en esta respuesta .

Otro punto es que está haciendo un mal uso add_definitionsen el sentido de que lo está usando para los indicadores del compilador en lugar de las definiciones del preprocesador previstas.

Seria preferible usar add_compile_options

add_compile_options(-Wall -Weffc++ -pedantic -std=c++0x)

o para las versiones de CMake <3.0 para hacer algo más como:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Weffc++ -pedantic -std=c++0x")

En respuesta a más preguntas en los comentarios a continuación, creo que es imposible eliminar de manera confiable una marca en un solo archivo. La razón es que para cualquier archivo fuente dado, tiene el COMPILE_OPTIONSy 1 de su destino aplicado, pero estos no aparecen en ninguna de las propiedades de ese archivo fuente.COMPILE_FLAGS

Podría buscar quitar el indicador de problema del objetivo COMPILE_OPTIONSy luego aplicarlo a cada una de las fuentes del objetivo individualmente, omitiéndolo del archivo fuente específico según sea necesario.

Sin embargo, aunque esto podría funcionar en muchos escenarios, tiene un par de problemas.

Primero, las propiedades de los archivos de origen no incluyen COMPILE_OPTIONS, solo COMPILE_FLAGS. Esto es un problema porque el COMPILE_OPTIONSde un destino puede incluir expresiones generadoras , pero COMPILE_FLAGSno las admite. Por lo tanto, tendría que acomodar las expresiones del generador mientras busca su bandera y, de hecho, tal vez incluso tenga que "analizar" las expresiones del generador si su bandera está contenida en una o más para ver si debe volver a aplicarse al resto archivos fuente.

En segundo lugar, desde CMake v3.0, los destinos pueden especificar INTERFACE_COMPILE_OPTIONS. Esto significa que una dependencia de su objetivo puede agregar o anular su objetivo a COMPILE_OPTIONStravés de su INTERFACE_COMPILE_OPTIONS. Entonces, además, tendría que iterar recursivamente a través de todas las dependencias de su objetivo (no es una tarea particularmente fácil ya que la lista de LINK_LIBRARIESpara el objetivo también puede contener expresiones generadoras) para encontrar cualquiera que esté aplicando el indicador de problema, e intentar eliminarlo de esos objetivos ' INTERFACE_COMPILE_OPTIONStambién.

En esta etapa de complejidad, estaría buscando enviar un parche a CMake para proporcionar la funcionalidad para eliminar una marca específica incondicionalmente de un archivo fuente.


1: tenga en cuenta que, a diferencia de la COMPILE_FLAGSpropiedad de los archivos de origen, la COMPILE_FLAGSpropiedad de los destinos está obsoleta.

Fraser
fuente
6
Pero, ¿cómo se configuran los indicadores de compilación para los archivos por separado sin agregarlos? Por ejemplo, quiero usar diferentes indicadores de compilación para el objetivo resultante que para los archivos, pero como están agregados, tendría que eliminarlos manualmente. ¿No hay ninguna propiedad que no se agregue sino que realmente la configure solo para el archivo / destino especificado?
Baradé
2
¿Qué podemos hacer cuando -fno-flag no está disponible (y el -fflag está configurado)?
gnzlbg
@ Baradé No puedes, no para un archivo fuente.
Fraser
@gnzlbg Nuevamente, estamos bastante estancados. Actualicé mi respuesta para dar un poco más de información (y una posible solución que probablemente funcionaría en algunos escenarios).
Fraser
¿Realmente no existe una solución alternativa para la configuración de las opciones de compilación de un solo archivo? Tengo que deshabilitar la generación de cobertura de gcc para algunos archivos que bloquean gcov.
Lothar
5

Solo agregando a la respuesta correcta de @ Fraser.

En caso de que desee agregar la bandera especial a carpetas específicas, puede hacer:

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_property(SOURCE ${SPECIAL_SRC_FILES} PROPERTY COMPILE_FLAGS -Wno-effc++)

o

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_source_files_properties(${SPECIAL_SRC_FILES} PROPERTIES COMPILE_FLAGS -Wno-effc++)

Tenga en cuenta que no se recomienda utilizar GLOB como se describe aquí

Levon
fuente
0

Usando la respuesta de @Fraser, creé lo siguiente para manejar las inclusiones de Qt porque la variable incluye múltiples rutas separadas por punto y coma. Esto significa que primero tuve que agregar un foreach()bucle y crear las banderas de inclusión a mano . Pero eso me permite tener una excepción: foo.cpp (ese archivo usa Qt por ahora, pero a largo plazo quiero eliminar esa dependencia y quiero asegurarme de que Qt no se cuele en ningún otro lugar).

find_package(Qt5Core REQUIRED)
set(QT_INCLUDE_PROPERTIES "")
foreach(DIR ${Qt5Core_INCLUDE_DIRS})
    set(QT_INCLUDE_PROPERTIES "${QT_INCLUDE_PROPERTIES} -isystem ${DIR}")
endforeach()
set_source_files_properties(foo.cpp PROPERTIES
    COMPILE_FLAGS
        ${QT_INCLUDE_PROPERTIES}
)

Tenga en cuenta también que uso el en -isystemlugar de -Ipara evitar algunas advertencias que los encabezados de Qt generan (tengo un montón de advertencias activadas).

Alexis Wilke
fuente