Как добавить компоновщик или флаг компиляции в файл CMake?
Я использую arm-linux-androideabi-g++
компилятор. Когда я пытаюсь скомпилировать простое "Привет, мир!" программа компилируется нормально. Когда я тестирую его, добавляя простую обработку исключений в этот код, он тоже работает (после добавления -fexceptions
.. Я думаю, он отключен по умолчанию).
Это для устройства Android, и я хочу использовать только CMake, а не ndk-build
,
Например - first.cpp
#include <iostream>
using namespace std;
int main()
{
try{
}
catch(...)
{
}
return 0;
}
./arm-linux-androideadi-g++ -o first-test first.cpp -fexceptions
Работает без проблем...
Проблема... Я пытаюсь скомпилировать файл с файлом CMake.
Я хочу добавить -fexceptions
как флаг. Я пробовал с
set (CMAKE_EXE_LINKER_FLAGS -fexceptions ) or set (CMAKE_EXE_LINKER_FLAGS "fexceptions" )
а также
set ( CMAKE_C_FLAGS "fexceptions")
По-прежнему отображается ошибка.
9 ответов
Предположим, вы хотите добавить эти флаги (лучше объявить их в константе):
SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS "-lgcov")
Есть несколько способов добавить их:
Самый простой (не чистый, но легкий и удобный, и работает только для флагов компиляции, C & C++ сразу):
add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
Присоединение к соответствующим переменным CMake:
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}") SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
Используя целевые свойства, ср. doc CMake свойство флага компиляции и должно знать имя цели.
get_target_property(TEMP ${THE_TARGET} COMPILE_FLAGS) if(TEMP STREQUAL "TEMP-NOTFOUND") SET(TEMP "") # Set to empty string else() SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content endif() # Append our values SET(TEMP "${TEMP}${GCC_COVERAGE_COMPILE_FLAGS}" ) set_target_properties(${THE_TARGET} PROPERTIES COMPILE_FLAGS ${TEMP} )
Прямо сейчас я использую метод 2.
В новых версиях CMake вы также можете установить флаги компилятора и компоновщика для одной цели, используя target_compile_options
а также target_link_libraries
соответственно (да, последний также устанавливает параметры компоновщика):
target_compile_options(first-test PRIVATE -fexceptions)
Преимущество этого метода заключается в том, что вы можете контролировать распространение опций на другие цели, которые зависят от этого, с помощью PUBLIC
а также PRIVATE
,
Попробуйте установить переменную CMAKE_CXX_FLAGS
вместо CMAKE_C_FLAGS
:
set (CMAKE_CXX_FLAGS "-fexceptions")
Переменная CMAKE_C_FLAGS
влияет только на компилятор C, но вы компилируете код C++.
Добавление флага в CMAKE_EXE_LINKER_FLAGS
избыточно
Предпочтительный способ указать параметры, специфичные для инструментальной цепочки, - использовать инструментальную цепочку CMake. Это гарантирует четкое разделение между:
- инструкции о том, как организовать исходные файлы в целевые объекты - выраженные в файлах CMakeLists.txt, полностью независимые от инструментальной цепочки; а также
- подробные сведения о том, как должны быть настроены определенные наборы инструментов - разделены на файлы сценариев CMake, расширяются будущими пользователями вашего проекта, масштабируемы.
В идеале в файлах CMakeLists.txt не должно быть флагов компилятора / компоновщика - даже внутриif
/endif
блоки. И ваша программа должна быть создана для собственной платформы с набором инструментов по умолчанию (например, GCC в GNU/Linux или MSVC в Windows) без каких-либо дополнительных флагов.
Шаги по добавлению цепочки инструментов:
Создайте файл, например, arm-linux-androidadi-gcc.cmake, с глобальными настройками инструментальной цепочки:
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++) set(CMAKE_CXX_FLAGS_INIT "-fexceptions")
(Вы можете найти пример Linux кросс-компиляции файла ToolChain здесь.)
Если вы хотите создать систему сборки с помощью этой инструментальной цепочки, укажите
CMAKE_TOOLCHAIN_FILE
параметр в командной строке:mkdir android-arm-build && cd android-arm-build cmake -DCMAKE_TOOLCHAIN_FILE=$(pwd)/../arm-linux-androideadi-gcc.cmake ..
(Примечание: вы не можете использовать относительный путь.)
Строить как обычно:
cmake --build .
Файлы Toolchain упрощают кросс-компиляцию, но у них есть и другие применения:
Усиленная диагностика для ваших модульных тестов.
set(CMAKE_CXX_FLAGS_INIT "-Werror -Wall -Wextra -Wpedantic")
Инструменты разработки, которые сложно настроить.
# toolchain file for use with gcov set(CMAKE_CXX_FLAGS_INIT "--coverage -fno-exceptions -g")
Усиленные проверки безопасности.
# toolchain file for use with gdb set(CMAKE_CXX_FLAGS_DEBUG_INIT "-fsanitize=address,undefined -fsanitize-undefined-trap-on-error") set(CMAKE_EXE_LINKER_FLAGS_INIT "-fsanitize=address,undefined -static-libasan")
Вы также можете добавить флаги компоновщика к определенной цели, используя LINK_FLAGS
имущество:
set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${flag}")
Если вы хотите распространить это изменение на другие цели, вы можете создать фиктивную цель для ссылки.
Начиная с CMake 3.13 существует
add_link_options
команда.
Это касается всех последующихadd_library
иadd_executable
команды в той же области и подобластях.
Например:
add_link_options("-fexceptions")
add_executable(first-test first.cpp)
Это сработало для меня, когда мне понадобилось определение прекомпиляции с именем "NO_DEBUG":
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DNO_DEBUG")
Тогда из кода
#ifdef NO_DEBUG
.....
Изучите макросы ucm_add_flags и ucm_add_linker_flags для ucm (мой набор полезных макросов CMake) - они имеют дело с добавлением флагов компилятора / компоновщика.
С CMake 3.4+,APPEND
можно использовать сstring
команда для добавления флагов.
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fexceptions")