c++makefilecmakeshared-objectsmpic++

Shared objects with libraries and directory inclusions in Cmake


I'm very new to Cmake, and I'm trying to use it as an alternative to this approach, which did not work fine.

My structure is actually simple, I have:

App/src/
App/src/so1
App/src/so2
App/src/so3

And in each App/src/soN folder, I have a .cpp file, that shall be compiled into a shared object. I know I must add a CMakeLists.txt file in each folder listed above, but I'm really lost with the library linkage and inclusion.

For example, suppose there are the following files under App/src/so1:

App/src/so1/so1.hpp
App/src/so1/so1.cpp

And the shared object so1.so requires -I /some/dir/include, and also needs to be linked to -L /some/other/dir/lib -l otherdirlib. What are the appropriate directives for to make this using CMake?


Solution

  • EDIT:

    Use file and GLOB_RECURSE:

    GLOB_RECURSE will generate a list similar to the regular GLOB, except it will traverse all the subdirectories of the matched directory and match the files.

    I advice you to rearrenge your files like this:

    app/
     |_ src/
     |_ include/
     |_ CMakeLists.txt
    so1/
     |_ src/
     |_ include/
     |_ CMakeLists.txt
    so2/
     |_ src/
     |_ include/
     |_ CMakeLists.txt
    so3/
     |_ src/
     |_ include/
     |_ CMakeLists.txt
    CMakeLists.txt
    

    The CMakeLists.txt in app folder:

    SET (APP_NAME app)
    
    # Print variables to stdout
    MESSAGE ( STATUS )
    MESSAGE ( STATUS "Configuring ${APP_NAME}:" )
    MESSAGE ( STATUS )
    
    # Source code files
    FILE (GLOB_RECURSE SOURCE_FILES src/*.cpp include/*.h include/*.inl)
    
    # Compiler options
    IF (CMAKE_COMPILER_IS_GNUCXX)
      ADD_DEFINITIONS (-ansi -Wall -Wextra -Werror -pthread)
    ENDIF ()
    
    # Build application
    ADD_EXECUTABLE (${APP_NAME} ${SOURCE_FILES})
    
    TARGET_LINK_LIBRARIES (${APP_NAME}
      ${SO1_LIB}
      ${SO2_LIB}
      ${SO3_LIB}
    )
    
    INSTALL (TARGETS ${APP_NAME} RUNTIME DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE  OWNER_EXECUTE GROUP_READ GROUP_WRITE  GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
    

    The CMakeLists.txt in each lib folder would be something like this(change the LIB_OUTPUT_NAME in each file accordingly):

    SET (LIB_OUTPUT_NAME so1)
    
    # Print variables to stdout
    MESSAGE ( STATUS )
    MESSAGE ( STATUS "Configuring ${LIB_OUTPUT_NAME}:" )
    MESSAGE ( STATUS )
    
    # Source code, headers and test files
    FILE (GLOB_RECURSE HEADER_FILES include/*.h include/*.inl)
    FILE (GLOB_RECURSE SOURCE_FILES src/*.cpp include/*.h include/*.inl)
    FILE (GLOB_RECURSE TEST_SRC_FILES tests/*.cpp tests/*.h tests/*.inl)
    
    # Compiler options
    IF (CMAKE_COMPILER_IS_GNUCXX)
      ADD_DEFINITIONS (-ansi -Wall -Wextra -Werror -pthread)
    ENDIF ()
    
    # Build library
    ADD_LIBRARY (${LIB_OUTPUT_NAME} SHARED ${SOURCE_FILES})
    

    Then in the main CMakeLists.txt:

    CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
    PROJECT (App CXX)
    
    # Set common variables
    IF ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
      SET (BUILD_DIR build/release)
    ELSE ()
      SET (BUILD_DIR build/debug)
    ENDIF ()
    
    # Print variables to stdout
    MESSAGE ( STATUS )
    MESSAGE ( STATUS "Building App:" )
    MESSAGE ( STATUS "change a configuration variable with: cmake -D<Variable>=<Value>" )
    MESSAGE ( STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}" )
    MESSAGE ( STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}" )
    MESSAGE ( STATUS "CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}" )
    MESSAGE ( STATUS )
    
    # Remove build directory on clean target
    SET_DIRECTORY_PROPERTIES (PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${BUILD_DIR})
    
    # Include directories
    INCLUDE_DIRECTORIES (
      "app/include"
      "so1/include"
      "so2/include"
      "so3/include"
    )
    
    # Add common compiler flags
    IF (CMAKE_COMPILER_IS_GNUCXX)
      SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CPP_FLAGS_RELEASE} -O2")
      SET(CMAKE_CXX_FLAGS_DEBUG  "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g)
    ENDIF ()
    
    # Build all dynamic Libraries
    ADD_SUBDIRECTORY (smartmatic ${BUILD_DIR}/so1)
    SET (SO1_LIB ${CMAKE_CURRENT_SOURCE_DIR}/${BUILD_DIR}/so1/so1.so)
    
    ADD_SUBDIRECTORY (saes-runtime ${BUILD_DIR}/so2)
    SET (SO2_LIB ${CMAKE_CURRENT_SOURCE_DIR}/${BUILD_DIR}/so2/so2.so)
    
    ADD_SUBDIRECTORY (saes-devices ${BUILD_DIR}/so3)
    SET (SO3_LIB ${CMAKE_CURRENT_SOURCE_DIR}/${BUILD_DIR}/so3/so3.so)
    
    # Add dynamic lib to app build for linking.
    ADD_SUBDIRECTORY (so1 ${BUILD_DIR}/so1)
    SET (SO1_LIB  ${CMAKE_CURRENT_SOURCE_DIR}/${BUILD_DIR}/so1/so1.so)
    
    ADD_SUBDIRECTORY (so2 ${BUILD_DIR}/so2)
    SET (SO2_LIB  ${CMAKE_CURRENT_SOURCE_DIR}/${BUILD_DIR}/so2/so2.so)
    
    ADD_SUBDIRECTORY (so3 ${BUILD_DIR}/so3)
    SET (SO3_LIB  ${CMAKE_CURRENT_SOURCE_DIR}/${BUILD_DIR}/so3/so3.so)
    
    # Build Application
    ADD_SUBDIRECTORY (app ${CMAKE_CURRENT_SOURCE_DIR}/${BUILD_DIR}/app)
    

    More information on:

    http://www.cmake.org/cmake/help/cmake2.6docs.html