Подтвердить что ты не робот

CMake: несколько подпроектов, использующих одну и ту же статическую библиотеку

Я использую cmake для компиляции одного из моих рабочих проектов, вот сделка

-
  client/
    CMakeLists.txt
  server/
    CMakeLists.txt
  libs/
    libstuff/
      CMakeLists.txt
  CMakeLists.txt

Итак, я хочу иметь возможность компилировать каждый подпроект индивидуально и строить как клиент, так и сервер из корневой папки.

Скажем, клиенту и серверу нужен libstuff.

Я попытался использовать "add_subdirectory" с контуром lib как на клиентском, так и на сервере CMakeLists.txt, он работает при компиляции сервера или клиента, но если вы попытаетесь запустить оба из корневого каталога:

CMake Error at common/libplugin/CMakeLists.txt:33 (ADD_LIBRARY):
  add_library cannot create target "plugin" because another target with the
  same name already exists.  The existing target is a static library created
  in source directory "/home/adrien/git/r-type/common/libplugin".  See
  documentation for policy CMP0002 for more details.

Итак, я вроде как новый w/cmake, и я не уверен, что делать, должен ли я использовать add_dependencies?

Спасибо за вашу помощь,

4b9b3361

Ответ 1

Простым решением является защита вызовов add_subdirectory как в файле клиента, так и в сервере CMake с помощью if с помощью TARGET условный, т.е.:

if (NOT TARGET plugin)
    add_subdirectory("${CMAKE_SOURCE_DIR}/common/libplugin")
endif() 

Это предотвращает добавление подкаталога libplugin более одного раза.

Ответ 2

Я бы предложил добавить три вызова add_subdirectory в ваш root CMakeLists.txt. сначала libstuff, затем клиент и сервер....

Настройте проект Stuff, как если бы он был автономным, но добавляйте переменные в кэш-память cmake, чтобы их можно было импортировать другими проектами. Затем в клиенте и сервере вы можете обратиться к проекту Stuff... используя обычный вызов include_directories и target_link_libraries.

например. в libstuff...

# libstuff CMakeLists
project( Stuff )
# ... whatever you need here: collect source files, ...
add_library( LibStuff ${Stuff_Sources} )
# Then, define a very useful variables which gets exported to the cmakecache and can be 
# used by other cmakelists
set( STUFF_INCLUDE_DIRS ${Stuff_SOURCE_DIR} CACHE STRING "Include-dir for Stuff." FORCE )

И затем в Client (и аналогично на сервере)

# client CMakeLists
project( Client )
# refer to Stuff-includes here...
include_directories( ${STUFF_INCLUDE_DIRS} )

add_executable( Client client.h client.cpp main.cpp ) # 
target_link_libraries( Client LibStuff )

Затем вы можете "скомпилировать" только каталог "Клиент", перейдя в каталог "Клиент" и запустив make или msbuild. Кроме того, вы можете добавить флаг cmake в root-cmakelistt, который используется для фильтрации между клиентом, сервером или обоими...