CMake : multiple subprojects using the same static library

21,074

Solution 1

A simple solution is to guard the add_subdirectory calls in both the client and the server CMake list file with an if using a TARGET conditional, i.e.:

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

This prevents the libplugin sub-directory from being added more than once.

Solution 2

I would suggest putting three add_subdirectory calls in your root CMakeLists.txt. libstuff first, then client and server....

Setup the Stuff project as if it is standalone, but add variables to the cmake cache such that it can be "imported" by other projects. Then, in client and server, you can refer to the Stuff project... using ordinary call include_directories and target_link_libraries.

E.g. in 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 )

And then in Client (and similarly in Server)

# 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 )

You can then "compile" only the Client directory, by stepping into the Client dir and running make or msbuild there. Alternatively, you could add a cmake-flag to the root-cmakelistt which is used to filter between Client, Server or both...

Share:
21,074
Intrepidd
Author by

Intrepidd

Passionate about IT since my early years, I chose to specialize in web development, especially with Ruby and Javascript. I enjoy solving complex problems with code and building features that benefit users / customers. I believe in open source software and have written and contributed to several open source projects from small libraries to well known web frameworks. I recently started looking into Security and am really interested in helping build secure applications and find vulnerabilities.

Updated on February 20, 2020

Comments

  • Intrepidd
    Intrepidd about 4 years

    I'm using cmake to compile one of my work projets, here is the deal

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

    So i want to be able to compile each subproject individually, and build both the client and the server from the root folder.

    Let's say the client and the server need libstuff.

    I tried to use "add_subdirectory" with the path of the lib in both client and server CMakeLists.txt, it works when you compile the server or the client, but if you try to run both from the root directory :

    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.
    

    So i'm kind of new w/ cmake and i'm not sure what i should do, should i use add_dependencies?

    Thanks for your help,