Multiple directories under CMake

I'm currently using recursive make and autotools and am looking to migrate to CMake for a project that looks something like this:

lx/ (project root)
    src/
        lx.c (contains main method)
        conf.c
        util/
            str.c
            str.h
            etc.c
            etc.h
        server/
            server.c
            server.h
            request.c
            request.h
        js/
            js.c
            js.h
            interp.c
            interp.h
    bin/
        lx (executable)

How should I go about this?


If there's never any source higher than the lx/src directory, then there's no need for the lx/CMakeLists.txt file. If there is, it should look something like this:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(lx)

add_subdirectory(src)
add_subdirectory(dir1)
add_subdirectory(dir2)

# And possibly other commands dealing with things
# directly in the "lx" directory

...where the subdirectories are added in library dependency order. Libraries that depend on nothing else should be added first, and then libraries that depend on those, and so on.

lx/src/CMakeLists.txt

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(lx_exe)

add_subdirectory(util)
add_subdirectory(js)
add_subdirectory(server)

set(lx_source_files conf.c lx.c)
add_executable(lx ${lx_source_files})

target_link_libraries(lx server)
  # also transitively gets the "js" and "util" dependencies

lx/src/util/CMakeLists.txt

set(util_source_files
  etc.c
  etc.h
  str.c
  str.h
)
add_library(util ${util_source_files})

lx/src/js/CMakeLists.txt

set(js_source_files
  interp.c
  interp.h
  js.c
  js.h
)
add_library(js ${js_source_files})

target_link_libraries(js util)

lx/src/server/CMakeLists.txt

set(server_source_files
  request.c
  request.h
  server.c
  server.h
)
add_library(server ${server_source_files})

target_link_libraries(server js)
  # also transitively gets the "util" dependency

Then, in a command prompt:

mkdir lx/bin
cd lx/bin

cmake ..
  # or "cmake ../src" if the top level
  # CMakeLists.txt is in lx/src

make

By default, the lx executable will end up in the "lx/bin/src" directory using this exact layout. You can control what directory it ends up in by using the RUNTIME_OUTPUT_DIRECTORY target property and the set_property command.

http://www.cmake.org/cmake/help/cmake-2-8-docs.html#prop_tgt:RUNTIME_OUTPUT_DIRECTORY

http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_property

Refer to target_link_libraries libs either by CMake target name, if the lib is built as a CMake target via add_library, or by full path to the library file otherwise.

See also, the output of "cmake --help-command target_link_libraries", or any other cmake command, and the full online documentation for cmake commands found here:

http://www.cmake.org/cmake/help/cmake-2-8-docs.html#section_Commands

http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:target_link_libraries


Steinberg VST3 library has a reusable method which recursively loops through subdirectories and adds them if they include a CMakeLists.txt file:

# add every sub directory of the current source dir if it contains a CMakeLists.txt
function(smtg_add_subdirectories)
    file(GLOB subDirectories RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *)
    foreach(dir ${subDirectories})
        if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
            if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${dir}/CMakeLists.txt")
                add_subdirectory(${dir})
            endif()
        endif()
    endforeach(dir)
endfunction()

https://github.com/steinbergmedia/vst3_cmake/blob/master/modules/SMTG_AddSubDirectories.cmake