Question

I'm working on a project that consists of 3 server executables and one library for shared code. I want it to be cross-platform, so I'm using CMake (since Xcode is being a pain anyway) to handle the build process. I'm having trouble with setting up the CMakeLists so that I can include the library from a directory at the same level when I'm building the executable.

Here's the directory structure (and the CMake files):

tethealla2.0/
    CMakeLists.txt
    libtethealla/
        CMakeLists.txt
        encryption/
        utils/
    patch_server/
        CMakeLists.txt
    login_server/
        CMakeLists.txt
    ship_server/
        CMakeLists.txt

My top-level CMake (tethealla2.0/CMakeLists.txt, only includes the sub-project that should compile):

project(tethealla CXX)
cmake_minimum_required(VERSION 2.6)

add_subdirectory(libtethealla)
add_subdirectory(patch_server)

tethealla2.0/libtethealla/CMakeLists.txt, which generates a static library:

project(Libtethealla C)
cmake_minimum_required(VERSION 2.6)

include_directories(encryption)

set(ENC_DR encryption/)

set(ENCRYPTION_SOURCES 
  ${ENC_DR}/psobb-crypt.c
  ${ENC_DR}/psogc-crypt.c
  ${ENC_DR}/psobb-crypt.c
  ${ENC_DR}/encryption.c
  )

add_library(tethealla STATIC ${ENCRYPTION_SOURCES})

tethealla2.0/patch_server/CMakeLists.txt thus far:

project(patch_server CXX)
cmake_minimum_required(VERSION 2.6)

add_executable(server main.cc)
target_link_libraries(server tethealla)

So it makes more sense if I build it from the top level since tethealla2.0/CMakeLists.txt will inherit the targets from each of the subdirectories and the one in patch_server will have access to the tethealla library. However what I want is to be able to build from within these subdirectories to generate Xcode projects so that I can work on/recompile them individually. To do so I need to be able to get to the libtethealla/build directory (where CMake outputs) to access the libtethealla.a library from patch_server. Is this possible?

On kind of another note, even in building from the top-level directory my source in patch_server can't include "encryption.h", the header file for the library in encryption. Which seems to be building fine. Any thoughts on that are also greatly appreciated!

Was it helpful?

Solution

My solution is to use add_subdirectory with relative patch to shared_lib directory. I don't think that this is a perfect solution it has its caveats:

  • Logic very similar to a header guard must be added to library CMakeLists.txt to prevent from defining targets multiple times.
  • Each CMakeList.txt file must know the relative path to the library, if one want to move library all CMakeLists must be updated.

Let's assume that the directory structure looks like this:

root/
    CMakeLists.txt
    shared_lib/
        CMakeLists.txt
        inc/
            foo.h
        src/
            foo.c
    exec1/
       CMakeLists.txt
       main.c
    exec2/
       CMakeLists.txt
       main.c

root/CMakeList.txt

cmake_minimum_required(VERSION 2.6)

add_subdirectory(shared_lib)

add_subdirectory(exec1)
add_subdirectory(exec2)

I have decided that shared_lib/CMakeLists.txt will export a variable named SHARED_DIR_INCLUDE_DIR. This approach helps to decouple things a little bit.

root/exec1/CMakeLists.txt

cmake_minimum_required(VERSION 2.6)

add_subdirectory(./../shared_lib shared_lib)

include_directories(${SHARED_LIB_INCLUDE_DIR})

set(SRCS main.c)
add_executable(exec1 ${SRCS})
target_link_libraries(exec1 shared_lib)

if() in the fourth line solves the issue with target's multiple definition in case the CMakeLists file is added multiple times. The second and the third lines exports the include directory for library in SHARED_LIB_INCLUDE_DIR

root/shared_lib/CMakeLists.txt

cmake_minimum_required(VERSION 2.6)

set(SHARED_LIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/inc)

set(SHARED_LIB_INCLUDE_DIR ${SHARED_LIB_INCLUDE_DIR} PARENT_SCOPE)

if(TARGET shared_lib)

message("shared_lib is already defined")

else()

include_directories(${SHARED_LIB_INCLUDE_DIR})

set(LIB_SRCS ./src/foo.c)

add_library(shared_lib STATIC ${LIB_SRCS})

endif()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top