Search code examples
cmakestatic-librariesbuild-system

How to structure CMake library project with optional executable


I'm trying to learn CMake but i'm dealing with a problem that is too difficult for me to just google through the documentation, because i don't even know what phrases to search for.

I have a repository whose primary target is a static library. However i also wrote a simple command line demo tool that demonstrates what the library can do and that helps me with testing and debugging it. The directory structure of the project looks like this

libname
    include  - header files of the library
    src  - sources of the library
    tools
        cli
            src  - sources of the demo executable

If this description is not enough, the whole repository can be found here https://github.com/Youda008/OpenRGB-cppSDK

Now i would like to write the CMakeList files in a way so that it adds the executable as an optional target, so that later i when i run make it only builds the library and when i write make cli it builds the demo tool.

My main problems are:

  1. How do i add an optional target to the root CMakeLists and point it to the cli directory.
  2. How to specify that the executable depends on the library and make the library build first.
  3. How to link the executable to that library after it has been built in the user's build directory.

Can you please point me in the right direction?


Solution

  • when i run make

    Do not use make, use cmake --build <builddir>, so that when you decide to move to Ninja for speed you will not have to change your scripts.

    How do i add an optional target to the root CMakeLists and point it to the cli directory.

    You do add_executable(executable_name EXCLUDE_FROM_ALL sources), that way the target will be excluded when building without explicitly specifying target (ie. when building with --target all).

    I would write a normal CMakeLists.txt inside tools/cli and then do add_subdirectory(tools/cli EXCLUDE_FROM_ALL).

    How to specify that the executable depends on the library

    Just lint it, use target_link_libraries(executable_name PRIVATE library_name).

    make the library build first.

    No action need to be taken - cmake will generate build system that already does that by itself, it's what cmake basically exists for.

    How to structure CMake library project with optional executable

    I would do like:

    # libname/CMakeLists.txt
    add_library(libname ...)
    option(BUILD_CLI "Set me to enable building cli executable")
    set(arg)
    if(BUILD_CLI)
       set(arg EXCLUDE_FROM_ALL)
    endif()
    add_subdirectory(tools/cli ${arg})
    
    # libname/tools/cli/CMakeLists.txt
    add_executable(exename ...)
    target_link_libraries(exename libname)
    

    For example you could peek at https://github.com/Lora-net/LoRaMac-node/blob/master/src/CMakeLists.txt#L206 , but it's not the best.

    what phrases to search for.

    Search for EXCLUDE_FROM_ALL and because of question #2, search for basic cmake introduction about library and linking.