cmake - настройка глобального флага компоновщика (для всех целей в каталоге)

Я хочу передать флаги компоновщика всем подпроектам (подкаталог CMakeList) в моем проекте.

Перед переключением на новый cmake 3.3 я использовал следующий код (cmake 3.2), который работал хорошо, добавив флаги для компиляции и компоновки:

set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -stdlibc++")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -stdlibc++")

С cmake 3.3 это больше не работает и устанавливает флаги только для шага компиляции. Я обновил CMakeList, чтобы использовать более "современный" синтаксис cmake:

set(MY_DEBUG_OPTIONS -g -stdlib=libstdc++ -Wfatal-errors)
set(MY_RELEASE_OPTIONS -O3 -stdlib=libstdc++ -Wfatal-errors)

add_compile_options(
  "$<$<CONFIG:DEBUG>:${MY_DEBUG_OPTIONS}>"
  "$<$<CONFIG:RELEASE>:${MY_RELEASE_OPTIONS}>")

Этот набор флагов компиляции для всех подпроектов, есть ли подобный способ сделать это для флагов компоновщика? Я знаю, что можно добавить флаги компоновщика на целевой основе с target_link_librariesкоманда, но больше ничего не могу найти.

Я пытался с помощью CMAKE_SHARED_LINKER_FLAGS (и соответствующая переменная для exe, module,..) переменная без успеха.

Обновить:

Оказывается, это не имеет ничего общего с версией cmake, все работает правильно CMAKE_CXX_FLAGS_XXXпеременные, кроме первой команды make. Если один прогон make во второй раз (с модификацией в CmakeList) присутствуют флаги.

Я думаю, что нашел решение во время тестирования с простым CMakeList: если флаги объявлены после project Команда это просто работает, как ожидалось. Я не знаю, является ли это требованием самого cmake или просто странным поведением.

cmake_minimum_required (VERSION 3.2)

set(PROJECT Test_Project)

# Not working (on first run)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -stdlib=libstdc++ -Wfatal-errors")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -stdlib=libstdc++ -Wfatal-errors")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -stdlib=libstdc++ -Wfatal-errors")

project(${PROJECT})

# Declare here instead...

add_executable(Test test.cpp)

MESSAGE( STATUS "Config flags : " ${CMAKE_CXX_FLAGS_RELEASE})

С помощью:

cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release .

1 ответ

Решение

Ваши проблемы не связаны с конкретной версией CMake.

Это одинаково для всех переменных флагов компоновщика / компилятора в CMake. Потому что эти переменные являются кэшированными переменными и устанавливаются с project() / enable_language() команда (подробности см. здесь), вы должны

  1. предварительно заполнить кэш set(... CACHE ...) перед project() команда
  2. обычно используют set(... CACHE ... FORCE) заставить / переписать
  3. переместить set() после project() команда, чтобы скрыть или добавить к кэшированным переменным

Вот пример для CMAKE_EXE_LINKER_FLAGS показывая все три варианта:

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

# 1. prefill
#set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map" CACHE INTERNAL "")

project(Test_Project CXX)

# 2. force
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map" CACHE INTERNAL "" FORCE)

# 3. hide
#set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map")
# 3. or append
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=output.map")

# TODO: Remove, this is just for testing
file(WRITE "foo.cpp" "int main() {}") 

add_executable(${PROJECT_NAME} foo.cpp)

Какими бы ни были значения этих переменных в конце любого CMakeLists.txt файл будет применен ко всем соответствующим целям в том же CMakeLists.txt файл как значения по умолчанию (см. CMAKE - установка флагов компиляции для библиотек и каков синтаксис CMake для установки и использования переменных?).

Первый вариант имеет тот недостаток, что на самом деле это только начальное значение. Второй и третий вариант, скорее всего, потребуется if (CMAKE_COMPILER_IS_GNUCXX) вокруг, поэтому я предпочитаю второй вариант с перемещением этих настроек в собственный файл начального кэша:

MyGNUSettings.cmake

set(CMAKE_CXX_FLAGS "-stdlib=libstdc++ -Wfatal-errors" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "-g" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE INTERNAL "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map" CACHE INTERNAL "" FORCE)

Используя, например,

cmake -G "Unix Makefiles" -C MyGNUSettings.cmake -DCMAKE_BUILD_TYPE=Release  .

И да - для глобальных настроек и параметров компилятора - я предпочитаю глобальные кэшированные переменные add_compile_options() команда. Я думаю add_compile_options() не заменил глобальные переменные, он был в основном введен, чтобы люди не помещали опции компилятора в add_definitions() команды.

Другие вопросы по тегам