Отменить флаги компиляции для отдельных файлов


110

Я хотел бы использовать глобальный набор флагов для компиляции проекта, что означает, что в моем файле CMakeLists.txt верхнего уровня я указал:

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

Однако для конкретного файла (скажем, «foo.cpp») в подкаталоге я хочу отключить флаги компиляции, чтобы не применять -Weffc ++ (включенная коммерческая библиотека, которую я не могу изменить). Чтобы упростить ситуацию использовать только -Wall, я попробовал:

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

, что не сработало. Я тоже пробовал

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

и

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

, в котором ни один из них не работал.

Наконец, я попытался удалить это определение:

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

, что также не сработало (то есть я получаю много предупреждений о стилях коммерческой библиотеки). (** Примечание: предупреждения ПОДАВАЮТСЯ, если Я НЕ повторно включаю директиву -Weffc ++ после сборки исполняемого файла.)

Я также попытался временно удалить флаги компиляции: http://www.cmake.org/pipermail/cmake/2007-June/014614.html , но это не помогло.

Разве это не изящное решение?


1
Подождите, если ваша последняя попытка сработает, но только после ее создания, может это не проблема кеширования? Попробуйте удалить CMakeCache после внесения изменений.
— Кэмерон

По теме см. Как изменить флаг компилятора только для одного исполняемого файла в CMake? Ответ Андре показывает способ заменить существующие параметры новыми.
— jww

Ответы:


126

Ваши попытки выше добавляют дополнительные флаги к вашему файлу / цели, а не перезаписывают, как вы, кажется, ожидаете. Например, из документации по свойствам исходных файлов - COMPILE_FLAGS :

Эти флаги будут добавлены в список флагов компиляции при сборке этого исходного файла.

Вы должны иметь возможность отменить -Weffc++флаг для foo.cpp, выполнив

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

Это должно иметь эффект добавления -Wno-effc++после -Weffc++в команде компилятора, и последний параметр выигрывает. Чтобы увидеть полную команду и убедиться, что это действительно так, вы можете сделать

make VERBOSE=1

Кстати, один из разработчиков стандартной библиотеки GNU C ++ высказывает довольно отрицательное мнение -Weffc++в этом ответе .

Другой момент заключается в том, что вы злоупотребляете add_definitionsв том смысле, что используете это для флагов компилятора, а не для предполагаемых определений препроцессора.

Было бы предпочтительнее использовать add_compile_options

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

или для версий CMake <3.0, чтобы сделать что-то вроде:

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

Отвечая на дополнительные вопросы в комментариях ниже, я считаю, что невозможно надежно удалить флаг в одном файле. Причина в том, что для любого исходного файла он имеет COMPILE_OPTIONSиCOMPILE_FLAGS 1 его целевого объекта, но они не отображаются ни в одном из свойств этого исходного файла.

Вы могли бы посмотреть, как убрать флаг проблемы с целевой COMPILE_OPTIONS , а затем применить его к каждому из целевых источников по отдельности, при необходимости исключив его из конкретного исходного файла.

Однако, хотя это может работать во многих сценариях, у него есть несколько проблем.

Во-первых, свойства исходных файлов не включают COMPILE_OPTIONS, только COMPILE_FLAGS. Это проблема, потому что COMPILE_OPTIONSцель может включать выражения генератора , ноCOMPILE_FLAGS не поддерживает их. Таким образом, вам придется использовать выражения генератора при поиске вашего флага, и вам, возможно, даже придется «анализировать» выражения генератора, если ваш флаг содержится в одном или нескольких, чтобы увидеть, следует ли его повторно применить к оставшимся исходные файлы.

Во-вторых, начиная с CMake v3.0, цели могут указывать INTERFACE_COMPILE_OPTIONS. Это означает, что зависимость вашей цели может добавлять или переопределять вашу цель COMPILE_OPTIONSчерез свои INTERFACE_COMPILE_OPTIONS. Таким образом, вам также придется рекурсивно перебирать все зависимости вашей цели (не особенно простая задача, поскольку список LINK_LIBRARIESдля цели также может содержать выражения генератора), чтобы найти любые, которые применяют флаг проблемы, и попытаться удалить его из тех цели INTERFACE_COMPILE_OPTIONSтоже.

На этом этапе сложности я хотел бы отправить патч в CMake, чтобы обеспечить функциональность для безоговорочного удаления определенного флага из исходного файла.


1: Обратите внимание, что, в отличие от COMPILE_FLAGSсвойства исходных файлов, COMPILE_FLAGSсвойство целевых объектов устарело.


6
Но как на самом деле установить флаги компиляции для файлов отдельно, не добавляя их? Например, я хочу использовать разные флаги компиляции для результирующей цели, чем для файлов, но поскольку они добавлены, мне пришлось бы удалить их вручную. Нет ли свойства, которое не добавляется, а фактически устанавливает их только для указанного файла / цели?
— Baradé

2
Что мы можем сделать, если -fno-flag недоступен (и установлен -fflag)?
— gnzlbg 05

@ Baradé Вы не можете - не для исходного файла.
— Fraser

@gnzlbg Опять же, мы в значительной степени застряли. Я обновил свой ответ, чтобы дать немного больше информации (и возможный обходной путь, который, вероятно, сработает в некоторых сценариях).
— Fraser

Действительно ли нет обходного пути для настройки параметров компиляции одного файла? Мне нужно отключить создание покрытия gcc для некоторых файлов, которые вызывают сбой gcov.
— Lothar

5

Просто добавив к правильному ответу @Fraser.

В случае, если вы хотите добавить специальный флаг в определенные папки, вы можете сделать:

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

или

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++)

Обратите внимание, что не рекомендуется использовать GLOB, как обсуждается здесь


0

Используя ответ @Fraser, я создал следующее для обработки включений Qt, потому что переменная включает несколько путей, разделенных точкой с запятой. Это означает, что мне пришлось сначала добавить foreach()цикл и вручную создать флаги включения . Но это позволяет мне иметь одно исключение: foo.cpp (этот файл сейчас использует Qt, но в долгосрочной перспективе я хочу удалить эту зависимость, и я хочу убедиться, что Qt не закрадывается в другое место).

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}
)

Также обратите внимание, что я использую -isystemвместо, -Iчтобы избежать некоторых предупреждений, которые в противном случае генерируются заголовками Qt (у меня включена масса предупреждений).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.