Переопределить флаги компиляции для отдельных файлов
Я хотел бы использовать глобальный набор флагов для компиляции проекта, что означает, что в моем файле 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, но это не помогло.
Нет ли элегантного решения для этого?
4 ответа
Ваши попытки выше добавляют дополнительные флаги к вашему файлу / цели, а не перезаписывают, как вы ожидаете. Например, из документов по свойствам исходных файлов - 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
имущество по целям устарело.
Просто добавлю к правильному ответу @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, как обсуждено здесь
Используя ответ @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 (у меня включена масса предупреждений).
Хотя это не совсем ответ на вопрос ОП, следующий совет решил проблему для меня. Некоторые компиляторы позволяют устанавливать или сбрасывать параметр в самом исходном файле:
#pragma option -Xinteger-divide-fast=0
Это отключило бы опцию integer-divide-fast в компиляторе diab, что в моем случае привело к сбою в этом конкретном файле.