2

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?

Community
  • 1
  • 1
Rubens
  • 14,478
  • 11
  • 63
  • 92

1 Answers1

3

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

AngelCastillo
  • 2,385
  • 2
  • 18
  • 26
  • +1 Thank you very much for your assistance, but I haven't yet been able to produce the makefiles. I have some particular questions: what, in your post, states I'm producing shared objects? where is the linkage with dynamic libraries (`-L /path/to/mylib -l mylib`)? The inclusion seems to work fine, I guess these two are the only left dependencies now. I'm able to add the path with `link_directories ("path/to/mylib")`, but I don't know which name to use in `target_link_libraries (??? mylib)`. From what I think, `???` should be replaced for each `.so` produced. – Rubens May 04 '13 at 14:12
  • I may haven't been clear, but I do actually have to compile each `soN/soN.cpp, soN/soN.hpp` into a shared library, so there would first be a `soN.o`, and then, a `soN.so`. I'm mean, I'm not going to have an unique executable, I'll just have `N` shared objects `.so`. – Rubens May 04 '13 at 14:32
  • Oh those are dynamic libs, then you DO need a CMakeLists in each folder, let me update the post. – AngelCastillo May 04 '13 at 15:30
  • I guess it's fine; you actually got me going nuts, trying to make this run, but now I guess I've learned a bit of `cMake` -- at least enough for to build one proper `CMakeLists.txt` in each folder I need. I'll try to finish things here, and I ask for help if I get stuck at any step. I've just noticed your edit; thanks for the answer! – Rubens May 04 '13 at 16:14