Как стать автором
Обновить

Комментарии 5

Честно говоря, какие-то детские проблемы — как можно не понимать что используемые глобально сущности не могут быть определены локально? А именно в этом проблема в обоих примерах.

Касательно разруливания этого в CMake, красивое решение для встроенной в проект библиотеки — set(MYLIB_DEFINITIONS "-DFOO" PARENT_SCOPE). Так логика установки флагов остаётся у библиотеки, а родительский проект получает оные после add_subdirectory так же как это обычно получается после find_package.

Ещё надёжнее решение с configure_file — так (как вы заметили) флаги не будут болтаться в командах, их нельзя будет забыть включить, но библиотеке в любом случае надо будет передавать родителю MYLIB_INCLUDE_DIRS (source и binary пути к заголовочным файлам — не забудьте что сгенерённый после configure_file заголовок попадает в binary директорию), и MYLIB_LIBRARY (тут просто имя цели библиотеки) с упомянутым PARENT_SCOPE. Решение с configure_file также удобнее в плане выноса библиотеки в самостоятельный проект — т.е. такой который можно без изменений как установить в систему через make install, так и включить непосредственно в проект, причём для проекта разница также будет всего в одной строке — find_package vs. add_subdirectory.

> При использовании configure_file следует помнить, что теперь проставления препроцессорных определений «снаружи» конкретного проекта через add_definitions работать не будет

А вот так делать и не нужно. Библиотека должна конфигурироваться через CMake — родительский проект должен только установить высокоуровневые cmake-переменные, а не лезть в низкоуровневые флаги компилятора. При этом если эти настройки действительно повлияют на флаги, оные вернутся родителю описанным выше способом.
По поводу тривиальности проблем — в том и дело, что в случае с #define-ами в заголовках из-за отсутствия опыта и/или невнимательности можно забыть, что сущности, оказывается, глобальные. Конечно, во второй раз такую ошибку уже не допустишь.

В остальном — спасибо, ценная информация, с вами полностью согласен.
в cmake есть не только add_definitions

SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS -DHELLO_WORLD)
SET_SOURCE_FILES_PROPERTIES(main.cpp PROPERTIES COMPILE_FLAGS -DHELLO_WORLD)
TARGET_COMPILE_DEFINITIONS/COMPILE_DEFINITIONS

Ваш пример 1 исправляется очень просто:

lib_config.cmake
add_definitions(-DMYFLAG=1)

lib/CMakeLists.txt
project(lib)
include(lib_config)
add_library(lib lib.h lib.cpp)

exe/CMakeLists.txt
project(exe)
include(lib_config)
add_executable(exe exe.cpp)
target_link_libraries(exe lib)

и никакой генерации конфигов
более трудоемкий способ через find_package и руками сделанный Find*package name*.cmake
Ваш пример 2 «сработал», — выдал " Stack around the variable 'a' was corrupted." когда освобождается стек при выходе из стек-фрейма (из функции just_segfault())

Ну так получается, что поля типа заключать под #ifdef'ами в заголовочных файлах — потенциально опасная вещь.
Сами подумайте:
Хедерник может включаться многократно в разные единицы трансляции (т.е. в разные cpp/c/cxx и т.п. файлы)
И в разных единицах трансляции могут быть разные определения препроцессора.
Мы получим разные размеры объектов одного и того же типа в разных единицах трансляции, они могут слинковаться, могут не слинковаться, если слинкуются, то получится потенциально небезопасный код.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации