buildcmakesubdirectorysubrepos

How can I tell, within a CMakeLists.txt, whether it's used with add_subdirectory()?


I have this code project can be built either independently or as a subproject of a larger repository (checking it our as a sub-repository). In the latter case, I have a top-level CMakeLists.txt for the main project which has

add_subdirectory(${MY_SUBPROJ_SUBDIR})

now, I want the subproject to behave somewhat differently in case it's used via the add_directory(). Obviously, I would be using a large if instruction. But what condition do I check? How can CMake "tell", when running for some CMakeLists.txt, whether it's a subdir file or the main file?


Solution

    1. After the project() call in project's CMakeLists.txt and in the project's subdirectories you may use:

       if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
           # I am top-level project.
       else()
           # I am called from other project with add_subdirectory().
       endif()
      

      NOTE: As stated in the comments, this approach may to not work on Windows, where CMAKE_SOURCE_DIR contains lower-case version of PROJECT_SOURCE_DIR and thus cannot be compared directly for equality. For that case approach with checking PARENT_DIRECTORY property, as described in that answer to the duplicate question, seems to be more robust.

    2. Alternative for use before the project() call:

       if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
           # I am top-level project.
       else()
           # I am called from other project with add_subdirectory().
       endif()
      

      This alternative can also be used anywhere in project's CMakeLists.txt (but not in subdirectories).


    Assume you have a project A with two CMakeLists.txt: one in the project's directory, and one in subdirectory src/. Scheme for use approaches described above:

    CMakeLists.txt:

    cmake_minimum_required(...)
    ...
    <only approach *2* can be used there>
    ...
    project(A)
    ...
    <approach *1* or *2* can be used there>
    ...
    add_subdirectory(src)
    ...
    

    src/CMakeLists.txt:

    ...
    <only approach *1* can be used there>
    ...
    

    With given scheme project A may detect, whether it is built standalone (top-level project) or as a part of another project B.