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

253
13 января 2018, 01:59

Есть директория с компонентами, все из которых являются статическими библиотеками. Они лежат в общей папке, каждая компонента имеет свой 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. Но при таком раскладе у меня возникает ошибка - я пытаюсь слинковать компоненту с несуществующим таргетом.

Кто-нибудь сталкивался с такой проблемой? Пока не смог найти решение самостоятельно.

Answer 1

Структура

├── 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.

READ ALSO
Построение ромба по его ширине и длине

Построение ромба по его ширине и длине

Я написал основную часть кода по построению ромбаНа ввод - символ, который будет являться границей, и ширина (еще одновременно и длина)

279
Межпроцессное взаимодействие (Shared Memory)

Межпроцессное взаимодействие (Shared Memory)

Kак я могу создать общий class для двух процессов в Shared Memory? Например я хочу чтобы этот class был обшим для двух процессовСпасибо

248
Работа с файлами.Создание новых файлов.Иерархия классов

Работа с файлами.Создание новых файлов.Иерархия классов

Был класс Student и Класс Group который содержал вектор обьектов Student

272
Нажатие мыши WinAPI, во время перемещение курсора

Нажатие мыши WinAPI, во время перемещение курсора

Каким образом определить какая из переданных клавиш была нажата используя WPARAM

255