Cmake линковка на библиотеку подпроекта

147
22 ноября 2018, 07:50

Имеется примерно следующий проект на Cmake:

                                   +-----------------+
                              +----|  lpviop_server  |
                              |    +-----------------+
+------------+                |         |           |
|            |----------------+         |           |
|   lpviop   |----------+               |           |
|            |----+     |        +---------------+  |
+------------+    |     +--------| lpvoip_client |  |
                  |              +---------------+  |
           +---------------+----/                   |
           |  lpvoip_core  |------------------------+
           +---------------+

Что бы было более понятно опишу словами: lpviop_client так же как lpviop_server должны ссылаться на проект lpvoip_core.

Проект Cmake lpvoip:

cmake_minimum_required(VERSION 3.12)
project(lpvoip)
add_subdirectory(lpvoip_server) # executable
add_subdirectory(lpvoip_client) # executable
add_subdirectory(lpvoip_core)   # library

Как мне правильно слинковать оба проекта, на проект lpviop_core?

Я не понимаю как линковаться на проект расположенный в сабдиректории.

Answer 1

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

set(ANY_LIB "my_lib" CACHE STRING "it is my lib" FORCE)

Последний параметр указывает что если имеется глобальная переменная с этим же именем, то перезаписать его. Так что сдесь есть по крайней мере одна проблема. К тому же если вы в этом файле поменяете имя переменной, то придется менять его и в других файлах. Я предложу лучший способ - он прекрасен)

В главном CMakeLists.txt указываете:

set(TARGETS_LIST CACHE STRING "list for all targets" FORCE)

Этим действием мы заводим список в глобальной области видимости - в него то мы и будем записывать все переменные (названия библиотек). Дальше в ваших субдиректориях добавляете только одну строку:

set(TARGETS_LIST "${TARGETS_LIST};${ANY_LIB}" CACHE STRING "reload list" FORCE)

Сдесь нельзя использовать APPEND так как он не работает с глобальной областью видимости. Таким образом, после обхода субдиректорий вы получите список всех библиотек. А дальше их линковку можно автоматизировать с помощью foreach:

foreach(SOME_TARGET ${TARGETS_LIST})
    target_link_libraries(${PROJECT_NAME} ${SOME_TARGET})
endforeach()

Таким образом, сколько бы у вас не бало библиотек, вам не нужно прыгать по всем файлам и добавлять данные, просто пишите смаке файл для субдиректории и в главном файле добавляете субдиректорию. Кстати, с субдиректориями тоже можно поступить также.

Answer 2

Примерно так, с плюшками для MS студии:

project(mytest)
set_property( GLOBAL PROPERTY USE_FOLDERS ON )
set( CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE )
set( CMAKE_SUPPRESS_REGENERATION true )
set( CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true )
set( CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY true )
set( PREDEFINED_TARGETS_FOLDER "CmakeDepends" )
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Release")
endif()
include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/../include
    ${CMAKE_CURRENT_SOURCE_DIR}/../src
)
set(lib_hdrs
    ${CMAKE_CURRENT_SOURCE_DIR}/../include/header1.h
    ${CMAKE_CURRENT_SOURCE_DIR}/../src/header2.h
    ....
)
set(lib_srcs
    ${CMAKE_CURRENT_SOURCE_DIR}/../src/func1.c
    ${CMAKE_CURRENT_SOURCE_DIR}/../src/func2.c
    ....
)
set( lib_target "libmy" )
add_library( ${lib_target} STATIC ${lib_srcs} ${lib_hdrs} )
set( app_target "TestMy" )
add_executable( ${app_target} "../my-main.c" )
target_link_libraries( ${app_target} ${lib_target} )
set_property( DIRECTORY
    ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${app_target}
)

пояснять мне кажется тут нечего :)

READ ALSO
Как получить данные из камеры?

Как получить данные из камеры?

Вообще хотел бы получить данные из камеры, преобразовать это в flv формат, и вывести по rtmp, но наверное это только мечтаПробывал ffmpeg программу...

127
Обмен данными между сокетами

Обмен данными между сокетами

Написал сокет-сервер на python (ubuntu), а клиента на c++ (windows)Проблема в том, что на сервере функция recv требует оповещение об закрытиии сокета (shutdown)...

135
Ошибка class not found

Ошибка class not found

При компиляции кода в IntelliJ IDEA всё работает отлично, но как только вывожуjar и пытаюсь запустить его, пишет ошибку:

168
Java, массив и двойной цикл for

Java, массив и двойной цикл for

Есть массив, нужно каждый элемент массива прогнать через цикл с добавлением цифрПроблема в том, что код прогоняет только первый элемент массива

158