Страницы

Поиск по вопросам

четверг, 21 марта 2019 г.

Слинковать CMake с еще не собранным таргетом

Есть директория с компонентами, все из которых являются статическими библиотеками. Они лежат в общей папке, каждая компонента имеет свой CMakeLists.txt и может собраться отдельно через CMake.
Также есть несколько утилит, каждая из которых может тянуть свои зависимости.
Пример иерархия папок:
[ git ] - libraries - strings - my_math - media_converter - logger - utilities - calc - video_player
Примеры CMakeLists.txt:
Для библиотеки:
project( library_name ) add_library( ${PROJECT_NAME} STATIC < .. > )
Для утилиты:
project( utility_name ) add_executable( ${PROJECT_NAME} < .. > )
# import components :
add_subdirectory( <..> ) # компонента еще не собрана, собираем ее target_include_directories( <..> ) # добавляю пути к заголовкам компоненты target_link_libraries( <..> ) # линкуем к таргету 'utility_name' библиотеки компоненты
Таким образом, если одна из импортируемых компонент тянет что-нибудь еще, например, media_converter тянет за собой ffmpeg и когда я добавлю media_converter к video_player, то в CMakeLists.txt у video_player придется добавить конструкции типа "find_library( ffmpeg )", "target_link ..", чтобы разрешить все зависимости.
Вопрос в следующем. Как посредством CMake в скрипте для статической библиотеки указать утилите, которой ее использует, сразу подтягивать внешние зависимости компоненты?
Я попытался в CMakeLists.txt для компоненты использовать такую конструкцию:
project( library_name ) add_library( ${PROJECT_NAME} STATIC < .. > ) target_link_libraries( ${CMAKE_PROJECT_NAME} < .. > )
По документации CMAKE_PROJECT_NAME - это название проекта для которого вызван CMake, т.е. в моем случае - это video_player. Но при таком раскладе у меня возникает ошибка - я пытаюсь слинковать компоненту с несуществующим таргетом.
Кто-нибудь сталкивался с такой проблемой? Пока не смог найти решение самостоятельно.


Ответ

Структура
├── libs │   └── media_converter │   ├── CMakeLists.txt │   └── main.cpp └── utils └── video_player ├── CMakeLists.txt └── main.cpp
media_converter
Сшздаём статическую библиотеку media_converter, находим и линкуем к ней зависимости. Обрати внимание, что зависимости публичные (PUBLIC).
cmake_minimum_required(VERSION 3.10) project(media_converter CXX)
add_library(${PROJECT_NAME} STATIC main.cpp)
find_library(MPG123_LIB mpg123) target_link_libraries(${PROJECT_NAME} PUBLIC ${MPG123_LIB}) target_include_directories(${PROJECT_NAME} PUBLIC /some/secret/path/to/mpg123)
video_player
Создаём приложение video_player и линкуемся с media_converter. Это автоматически добавит все публичные зависимости media_converter к video_player
cmake_minimum_required(VERSION 3.10) project(video_player CXX)
add_executable(${PROJECT_NAME} main.cpp)
add_subdirectory(../../libs/media_converter media_converter) target_link_libraries(${PROJECT_NAME} media_converter)
Проверка
$ cmake ../utils/video_player/ ... Build files have been written to: .../build
$ make VERBOSE=1 ... [ 75%] Building CXX object CMakeFiles/video_player.dir/main.cpp.o /usr/bin/c++ -I/some/secret/path/to/mpg123 -o CMakeFiles/video_player.dir/main.cpp.o -c .../utils/video_player/main.cpp [100%] Linking CXX executable video_player /usr/bin/cmake -E cmake_link_script CMakeFiles/video_player.dir/link.txt --verbose=1 /usr/bin/c++ CMakeFiles/video_player.dir/main.cpp.o -o video_player media_converter/libmedia_converter.a /usr/lib64/libmpg123.so
Как видно, video_player компилируется с -I/some/secret/path/to/mpg123 и линкуется с /usr/lib64/libmpg123.so

Комментариев нет:

Отправить комментарий