[CMake] Optional submodules best practice?

Doug douglas.linder at gmail.com
Fri Feb 3 22:26:39 EST 2012


Hi,

I'm currently using a combination of the include and file directives to
find and bind optional submodules to one of my projects, but its a bit of a
pain to do.

I was wondering if there was a more cmake-y way of doing this?

Here's what I currently do:

# Optional: build pthreads
cmake_minimum_required (VERSION 2.6)
project (N)

# Collect source files
file(GLOB_RECURSE SOURCES src/*.c)

# Deps: self
set(PROJECT_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include")
set(PROJECT_EXTRA_LIBRARIES "")
set(PROJECT_EXTRA_INCLUDES "")
set(PROJECT_EXTRA_SOURCES "")
set(PROJECT_EXTRA_TESTS "")

# Look for optional modules
file(GLOB PROJECT_IMPL impl/*.txt)
foreach(IMPL ${PROJECT_IMPL})
  message("Adding: ${IMPL}")
  include(${IMPL})
endforeach(IMPL)

# Add extra parts to build
set(SOURCES "${SOURCES};${PROJECT_EXTRA_SOURCES}")
set(PROJECT_INCLUDE_DIRS
"${PROJECT_INCLUDE_DIRS};${PROJECT_EXTRA_INCLUDES}")

# Debug mode?
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_C_FLAGS "-Wall -pedantic -Wimplicit-function-declaration
-Wreturn-type -Wextra")

# Code type
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")

# Build library
add_library(n ${SOURCES})
target_link_libraries(n ${PROJECT_EXTRA_LIBRARIES})
include_directories(${PROJECT_INCLUDE_DIRS})
set(PROJECT_LIBRARIES "${PROJECT_BINARY_DIR}/libn.a"
${PROJECT_EXTRA_LIBRARIES})

# Find tests
file(GLOB_RECURSE TESTS tests/CMakeLists*)
set(TESTS "${TESTS};${PROJECT_EXTRA_TESTS}")

# Load tests
if(TESTS)
  enable_testing()
  foreach(TEST ${TESTS})
    string(REGEX REPLACE "CMakeLists.txt" "" TEST_DIR ${TEST})
    add_subdirectory(${TEST_DIR})
  endforeach(TEST)
endif(TESTS)

Inside the 'impl' directory are a set of include files, one per optional
submodule, that bind additional sources and include directories:

# Optional: build pthreads
option(BUILD_THREADS_PTHREADS "Building pthreads thread implementation" ON)
if(BUILD_THREADS_PTHREADS)

  # Absolute path to module base
  set(EXTRA_PATH "${PROJECT_SOURCE_DIR}/impl/pthreads")

  # Add include directories
  set(PROJECT_EXTRA_INCLUDES ${PROJECT_EXTRA_INCLUDES}
${EXTRA_PATH}/include)

  # Add sources
  file(GLOB_RECURSE PROJECT_EXTRA_SOURCES_LOCAL "${EXTRA_PATH}/src/*.c")
  set(PROJECT_EXTRA_SOURCES
"${PROJECT_EXTRA_SOURCES};${PROJECT_EXTRA_SOURCES_LOCAL}")

  # Add tests
  file(GLOB_RECURSE PROJECT_EXTRA_TESTS_LOCAL
"${EXTRA_PATH}/tests/CMakeLists*")
  set(PROJECT_EXTRA_TESTS
"${PROJECT_EXTRA_TESTS};${PROJECT_EXTRA_TESTS_LOCAL}")

endif(BUILD_THREADS_PTHREADS)

I mean, this approach works perfectly for what I'm trying to do, and it has
the benefit of compiling a single final library including all the
submodules (instead of building like 30 shared libraries, which is highly
undesirable). It's highly extensible too, since to add a new submodule you
just drop a new folder into impl/

It's quite... verbose though. Manually munging all the sources into a
single list, etc.

Has anyone else had similar experience / a better way of doing this?

(The submodules are for platform specific code; rather than having a tonnes
of #ifdefs in a single code group we've split it into a common header file
and separate submodules for different people to look after independently).

Cheers,
Doug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.cmake.org/pipermail/cmake/attachments/20120204/6a56e7ea/attachment.htm>


More information about the CMake mailing list