Как добавить компоновщик или флаг компиляции в файл CMake?

220

Я использую 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")

По-прежнему отображается ошибка.

Solti
источник
сейчас у меня та же проблема, и я пробую разные вещи. Повесьте немного и я выложу ответ. Для флагов компиляции есть грязный, но простой способ: add_definitions ("- truc")
Offirmo
Для более актуального обсуждения этого вопроса (особенно если вы используете CMake 3.x или новее): каков современный метод установки общих флагов компиляции в CMake? ,
ComicSansMS
Если требуемые флаги ссылки направлены на настройку rpath , взгляните на конкретные команды CMake rpath gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
Габриэль Девиллерс

Ответы:

243

Предположим, вы хотите добавить эти флаги (лучше объявить их в константе):

SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS    "-lgcov")

Есть несколько способов добавить их:

  1. Самый простой (не чистый, но легкий и удобный, и работает только для флагов компиляции, C & C ++ сразу):

    add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
  2. Присоединение к соответствующим переменным 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}")
  3. Используя целевые свойства, ср. 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.

Offirmo
источник
4
почему add_definitions () нечист?
leinaD_natipaC
14
@leinaD_natipaC: Официальная документация гласит: Эта команда может использоваться для добавления любых флагов, но она предназначена для добавления определений препроцессора . Я думаю вот почему.
Бенуа Бланшон
В то время как это принятый ответ, он действительно показывает очень старый стиль CMAKE, обратитесь к ответу @vitaut о том, как любой новый код CMAKE должен быть структурирован с учетом параметров времени компиляции
Харальд Шейрих
1
string(APPEND CMAKE_EXE_LINKER_FLAGS "new_value")короче и чищеset(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} new_value")
кровавый
165

В более новых версиях CMake вы можете установить флаги компилятора и компоновщика для одной цели с target_compile_optionsи target_link_librariesсоответственно (да, последняя также устанавливает опции компоновщика):

target_compile_options(first-test PRIVATE -fexceptions)

Преимущество этого метода заключается в том, что вы можете контролировать распространение опций на другие цели, которые зависят от этого, с помощью PUBLIC и PRIVATE.

Начиная с CMake 3.13, вы также можете использовать target_link_optionsдля добавления параметров компоновщика, что делает намерение более ясным.

Витовт
источник
2
Я пытался использовать это: target_compile_options(main_static PRIVATE --static)но это не похоже на работу, есть идеи, почему?
Павел Щур
2
-staticэто, вероятно, компоновщик, а не опция компилятора. Попробуйте передать его target_link_libraries.
Витаут
9
О, target_link_librariesя пропустил ту часть документа: «Укажите библиотеки или флаги, которые будут использоваться при связывании определенной цели». Спасибо.
Павел Щур
3
Недавнее добавление: CMake 3.13 представляет target_link_optionsболее чистый способ задания флагов компоновщика. Вы должны избегать использования target_link_librariesдля флагов компоновщика в будущем и использовать target_link_optionsвместо этого.
ComicSansMS
1
Существует также add_compile_options - см stackoverflow.com/questions/39501481/... и совсем недавно add_link_options
Брюс Адамс
46

Попробуйте установить переменную CMAKE_CXX_FLAGSвместо CMAKE_C_FLAGS:

set (CMAKE_CXX_FLAGS "-fexceptions")

Переменная CMAKE_C_FLAGS влияет только на компилятор C, но вы компилируете код C ++.

Добавление флага CMAKE_EXE_LINKER_FLAGSявляется излишним.

Sakra
источник
Я попробовал это, но это все равно дает ошибку. Устанавливается (CMAKE_CXX_FLAGS "-fexceptions") единственным способом указать флаг компилятора.
Солти
3
я решил проблему, но не в хорошем смысле, это плохой обходной путь .. я сделал -DCMAKE_CXX_FLAGS = "-fexceptions" в командной строке. по какой-то причине cmake не читает флаги из файла .cmake. :( .. спасибо Сакра за ваш ответ ..
Solti
8
-DCMAKE_CXX_FLAGS = "-fexceptions" НЕ должно быть пробела между = и "
evandrix
Что касается того, что вы сказали: «по какой-то причине cmake не читает флаги из файла .cmake». Убедитесь, что вы очистили существующий кеш. Это можно сделать, удалив все из каталога сборки перед повторным cmake.
Зайдзен
1

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

set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${flag}")

Если вы хотите распространить это изменение на другие цели, вы можете создать фиктивную цель для ссылки.

kaveish
источник
0

Оформить заказ на ucm_add_flags и ucm_add_linker_flags макросы ЦСМА (мой набор полезных CMake макросов) - они имеют дело с прилагаемыми флагами компилятора / линкера.

onqtam
источник